#!/usr/bin/env php "vendor/webmozart/glob/src/Glob.phphC_hC9vendor/webmozart/glob/src/Iterator/GlobFilterIterator.php!_!, :vendor/webmozart/glob/src/Iterator/RegexFilterIterator.phpY _Y ؘ3vendor/webmozart/glob/src/Iterator/GlobIterator.phpW _W XGAvendor/webmozart/glob/src/Iterator/RecursiveDirectoryIterator.php_/vendor/webmozart/glob/LICENSE<_<t}&vendor/webmozart/path-util/src/Url.php _ ô'vendor/webmozart/path-util/src/Path.php|_|B$"vendor/webmozart/path-util/LICENSE<_<t}%vendor/webmozart/assert/src/Mixin.php_ȏд&vendor/webmozart/assert/src/Assert.php_Nvendor/webmozart/assert/LICENSE<_<t}8vendor/psr/container/src/ContainerExceptionInterface.php_)/vendor/psr/container/src/ContainerInterface.php`_`7vendor/psr/container/src/NotFoundExceptionInterface.php=_=vendor/psr/container/LICENSEy_yOp)vendor/psr/log/Psr/Log/AbstractLogger.php@ _@ Ҏ?*vendor/psr/log/Psr/Log/LoggerInterface.php9 _9 \%vendor/psr/log/Psr/Log/NullLogger.php_Icݴ+vendor/psr/log/Psr/Log/LoggerAwareTrait.php_ &vendor/psr/log/Psr/Log/LoggerTrait.phpf_fVM/vendor/psr/log/Psr/Log/LoggerAwareInterface.php`_`橲#vendor/psr/log/Psr/Log/LogLevel.phpP_PI3vendor/psr/log/Psr/Log/InvalidArgumentException.phpw_wh4vendor/psr/log/LICENSE=_=pO'vendor/symfony/polyfill-php73/Php73.php_>6+vendor/symfony/polyfill-php73/bootstrap.php_J[%vendor/symfony/polyfill-php73/LICENSE)_)`e0?vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php_I'vendor/symfony/polyfill-ctype/Ctype.php_.9+vendor/symfony/polyfill-ctype/bootstrap.php_Hj%vendor/symfony/polyfill-ctype/LICENSE)_)`e05vendor/symfony/polyfill-intl-normalizer/bootstrap.php_IX/vendor/symfony/polyfill-intl-normalizer/LICENSE)_)\6vendor/symfony/polyfill-intl-normalizer/Normalizer.phpy#_y#SمFvendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php _ qyWLvendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php._.Rvendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php=_=dcTvendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php_aXvendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php_ʼn0$vendor/symfony/string/LazyString.phpC_C۴/vendor/symfony/string/AbstractUnicodeString.phpj_jKEɴ(vendor/symfony/string/AbstractString.phpAK_AK "6vendor/symfony/string/Exception/ExceptionInterface.phpg_g9~g4vendor/symfony/string/Exception/RuntimeException.php_`c<vendor/symfony/string/Exception/InvalidArgumentException.php_vendor/symfony/string/LICENSE)_)a6vendor/symfony/string/Inflector/InflectorInterface.php_3۴4vendor/symfony/string/Inflector/EnglishInflector.php:_: ߦc2vendor/symfony/string/Slugger/SluggerInterface.php)_)}(.vendor/symfony/string/Slugger/AsciiSlugger.php_7A)vendor/symfony/string/CodePointString.php#_#W'vendor/symfony/string/UnicodeString.php6_6N$vendor/symfony/string/ByteString.phpB_B6<vendor/symfony/string/Resources/data/wcswidth_table_wide.php_v<vendor/symfony/string/Resources/data/wcswidth_table_zero.phpf_fY&-vendor/symfony/string/Resources/functions.php_V3vendor/symfony/polyfill-intl-grapheme/bootstrap.php _ _ 2vendor/symfony/polyfill-intl-grapheme/Grapheme.php!_!-vendor/symfony/polyfill-intl-grapheme/LICENSE)_)\'vendor/symfony/polyfill-php80/Php80.php _ j+vendor/symfony/polyfill-php80/bootstrap.php_/9%vendor/symfony/polyfill-php80/LICENSE$_$LO! <vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php _ 3a<vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php_մEvendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php_똢&vendor/symfony/console/Application.phph_h&Ž/vendor/symfony/console/Logger/ConsoleLogger.php<_</vendor/symfony/console/Output/ConsoleOutput.php_ z)1vendor/symfony/console/Output/OutputInterface.php _ |%(vendor/symfony/console/Output/Output.php_]O6vendor/symfony/console/Output/ConsoleSectionOutput.php_u.vendor/symfony/console/Output/StreamOutput.php_W,vendor/symfony/console/Output/NullOutput.php _ )'8vendor/symfony/console/Output/ConsoleOutputInterface.php_0vendor/symfony/console/Output/BufferedOutput.php_6vendor/symfony/console/Helper/DebugFormatterHelper.php _ [ ٴ7vendor/symfony/console/Helper/SymfonyQuestionHelper.php_k+'vendor/symfony/console/Helper/Table.phpv_v\Sթ0vendor/symfony/console/Helper/TableSeparator.phpb_bl2vendor/symfony/console/Helper/DescriptorHelper.php _ Kݴ+vendor/symfony/console/Helper/TableRows.phpi_i,vendor/symfony/console/Helper/TableStyle.php0_0%Er2vendor/symfony/console/Helper/InputAwareHelper.php_G1vendor/symfony/console/Helper/FormatterHelper.php* _* |+vendor/symfony/console/Helper/HelperSet.php _ ~<0vendor/symfony/console/Helper/QuestionHelper.phpH_H7/vendor/symfony/console/Helper/ProcessHelper.php_-Ǵ1vendor/symfony/console/Helper/HelperInterface.php_w!%"+vendor/symfony/console/Helper/TableCell.php_1oEg(vendor/symfony/console/Helper/Helper.phpw_wfwo3vendor/symfony/console/Helper/ProgressIndicator.php5_52 -vendor/symfony/console/Helper/ProgressBar.php I_ IU_(vendor/symfony/console/Helper/Dumper.php@ _@ ya]2vendor/symfony/console/Question/ChoiceQuestion.php^_^z 8vendor/symfony/console/Question/ConfirmationQuestion.phph_hK]vD,vendor/symfony/console/Question/Question.php_/vendor/symfony/console/Tester/CommandTester.php _ D/-vendor/symfony/console/Tester/TesterTrait.phps_sfÎ3vendor/symfony/console/Tester/ApplicationTester.php_~^3vendor/symfony/console/SingleCommandApplication.php_2ȵ !vendor/symfony/console/Cursor.phpw_w3vendor/symfony/console/Exception/LogicException.php_P2Դ;vendor/symfony/console/Exception/InvalidOptionException.phpN_N$?vendor/symfony/console/Exception/NamespaceNotFoundException.php,_,:?=vendor/symfony/console/Exception/CommandNotFoundException.php_g7vendor/symfony/console/Exception/ExceptionInterface.php_Wa:vendor/symfony/console/Exception/MissingInputException.php|_|5vendor/symfony/console/Exception/RuntimeException.php_ J*=vendor/symfony/console/Exception/InvalidArgumentException.php_/vendor/symfony/console/Style/StyleInterface.phpT _T GV,vendor/symfony/console/Style/OutputStyle.php _ QV-vendor/symfony/console/Style/SymfonyStyle.php>_>c6vendor/symfony/console/EventListener/ErrorListener.php _ L.vendor/symfony/console/Command/ListCommand.php _ 4(*vendor/symfony/console/Command/Command.phpN_N_0vendor/symfony/console/Command/LockableTrait.php_ Z^\.vendor/symfony/console/Command/HelpCommand.php _ TqDvendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php_]1#vendor/symfony/console/Terminal.php_ (vendor/symfony/console/ConsoleEvents.php@_@e9vendor/symfony/console/LICENSE)_)=Bvendor/symfony/console/Formatter/OutputFormatterStyleInterface.phpk_kQ8vendor/symfony/console/Formatter/NullOutputFormatter.php_yY=vendor/symfony/console/Formatter/NullOutputFormatterStyle.php_9vendor/symfony/console/Formatter/OutputFormatterStyle.phpR_RWr=vendor/symfony/console/Formatter/OutputFormatterInterface.php_ӴFvendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php_}j4vendor/symfony/console/Formatter/OutputFormatter.php _ Ljȴ>vendor/symfony/console/Formatter/OutputFormatterStyleStack.php _ `-4vendor/symfony/console/Descriptor/JsonDescriptor.php_MkN9vendor/symfony/console/Descriptor/DescriptorInterface.php_+-<vendor/symfony/console/Descriptor/ApplicationDescription.php_;33vendor/symfony/console/Descriptor/XmlDescriptor.phpV&_V&ڤ4vendor/symfony/console/Descriptor/TextDescriptor.php|7_|7y0vendor/symfony/console/Descriptor/Descriptor.php._.( v8vendor/symfony/console/Descriptor/MarkdownDescriptor.php_ru[&vendor/symfony/console/Input/Input.php_d0vendor/symfony/console/Input/InputDefinition.php,_,!`ƛ+vendor/symfony/console/Input/ArrayInput.php_*Z%K,vendor/symfony/console/Input/InputOption.php_vM9vendor/symfony/console/Input/StreamableInputInterface.php_a/vendor/symfony/console/Input/InputInterface.php_j.vendor/symfony/console/Input/InputArgument.php:_: ,vendor/symfony/console/Input/StringInput.php _ **vendor/symfony/console/Input/ArgvInput.php-_-b4vendor/symfony/console/Input/InputAwareInterface.php_oA?vendor/symfony/console/CommandLoader/ContainerCommandLoader.php_vst=vendor/symfony/console/CommandLoader/FactoryCommandLoader.php_f34?vendor/symfony/console/CommandLoader/CommandLoaderInterface.php_>4vendor/symfony/console/Event/ConsoleCommandEvent.php_nV)-vendor/symfony/console/Event/ConsoleEvent.php_' 2vendor/symfony/console/Event/ConsoleErrorEvent.php._.6vendor/symfony/console/Event/ConsoleTerminateEvent.php]_]T4vendor/symfony/console/Resources/bin/hiddeninput.exe$_$v-vendor/symfony/polyfill-mbstring/Mbstring.phpRm_Rm#Jܴ.vendor/symfony/polyfill-mbstring/bootstrap.phpC#_C#](vendor/symfony/polyfill-mbstring/LICENSE)_)\@vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.phpU_U?Fvendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php_@vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php V_ V3vendor/symfony/service-contracts/ResetInterface.php_?vendor/symfony/service-contracts/ServiceSubscriberInterface.php_=7vendor/symfony/service-contracts/Attribute/Required.php_P^8vendor/symfony/service-contracts/ServiceLocatorTrait.php_71;vendor/symfony/service-contracts/ServiceSubscriberTrait.phpl_lއ5(vendor/symfony/service-contracts/LICENSE)_)i8z=vendor/symfony/service-contracts/ServiceProviderInterface.php _ $vLvendor/felixfbecker/language-server-protocol/src/TextDocumentSyncOptions.php_!Fvendor/felixfbecker/language-server-protocol/src/CodeActionContext.php_ Nvendor/felixfbecker/language-server-protocol/src/SymbolLocationInformation.php_ac=vendor/felixfbecker/language-server-protocol/src/TextEdit.php_fpEvendor/felixfbecker/language-server-protocol/src/InitializeResult.php_:`Ivendor/felixfbecker/language-server-protocol/src/SignatureHelpOptions.php_Cִ?vendor/felixfbecker/language-server-protocol/src/Diagnostic.phpj_j ôHvendor/felixfbecker/language-server-protocol/src/DependencyReference.php_Im?vendor/felixfbecker/language-server-protocol/src/SymbolKind.php_%5Evendor/felixfbecker/language-server-protocol/src/InsertTextFormat.php_J;Jvendor/felixfbecker/language-server-protocol/src/DocumentHighlightKind.php_Evendor/felixfbecker/language-server-protocol/src/ReferenceContext.php`_`5Bvendor/felixfbecker/language-server-protocol/src/WorkspaceEdit.php_5:vendor/felixfbecker/language-server-protocol/src/Hover.php_ Kvendor/felixfbecker/language-server-protocol/src/TextDocumentIdentifier.php[_[=vendor/felixfbecker/language-server-protocol/src/CodeLens.phpu_uR:vendor/felixfbecker/language-server-protocol/src/Range.php_&n YGvendor/felixfbecker/language-server-protocol/src/ServerCapabilities.php _ $@vendor/felixfbecker/language-server-protocol/src/MessageType.phpk_k\ -Bvendor/felixfbecker/language-server-protocol/src/SignatureHelp.php_:Fvendor/felixfbecker/language-server-protocol/src/DocumentHighlight.php_ccôGvendor/felixfbecker/language-server-protocol/src/DiagnosticSeverity.phpk_k:Fvendor/felixfbecker/language-server-protocol/src/CompletionContext.php_=vendor/felixfbecker/language-server-protocol/src/Position.phpN_NGTvendor/felixfbecker/language-server-protocol/src/DocumentOnTypeFormattingOptions.php_reFvendor/felixfbecker/language-server-protocol/src/FormattingOptions.php>_>mʱAvendor/felixfbecker/language-server-protocol/src/MarkedString.phpf_f3 Fvendor/felixfbecker/language-server-protocol/src/SymbolInformation.php_1 8Dvendor/felixfbecker/language-server-protocol/src/CodeLensOptions.phpq_q@vendor/felixfbecker/language-server-protocol/src/SaveOptions.php'_'_$S<vendor/felixfbecker/language-server-protocol/src/Command.php|_|nGvendor/felixfbecker/language-server-protocol/src/ContentChangeEvent.phpR_RԍGvendor/felixfbecker/language-server-protocol/src/ClientCapabilities.php_&"Cvendor/felixfbecker/language-server-protocol/src/FileChangeType.phpT_T>BFvendor/felixfbecker/language-server-protocol/src/CompletionOptions.php_HXOIvendor/felixfbecker/language-server-protocol/src/ReferenceInformation.php_>IIvendor/felixfbecker/language-server-protocol/src/SignatureInformation.phpg_gz´Evendor/felixfbecker/language-server-protocol/src/SymbolDescriptor.php_T>vendor/felixfbecker/language-server-protocol/src/ErrorCode.phpi_iRBTGvendor/felixfbecker/language-server-protocol/src/CompletionItemKind.php _ x״Cvendor/felixfbecker/language-server-protocol/src/CompletionItem.php_ =vendor/felixfbecker/language-server-protocol/src/Location.php_Jvendor/felixfbecker/language-server-protocol/src/CompletionTriggerKind.php6_6U61Svendor/felixfbecker/language-server-protocol/src/TextDocumentContentChangeEvent.php^_^;Fvendor/felixfbecker/language-server-protocol/src/PackageDescriptor.php_HT?vendor/felixfbecker/language-server-protocol/src/MarkupKind.php$_$hƴIvendor/felixfbecker/language-server-protocol/src/ParameterInformation.php_>vendor/felixfbecker/language-server-protocol/src/FileEvent.php_vTvendor/felixfbecker/language-server-protocol/src/VersionedTextDocumentIdentifier.php_q)Ivendor/felixfbecker/language-server-protocol/src/TextDocumentSyncKind.php>_>wxCvendor/felixfbecker/language-server-protocol/src/CompletionList.php3_3:QEvendor/felixfbecker/language-server-protocol/src/TextDocumentItem.php_]{vFvendor/felixfbecker/language-server-protocol/src/MessageActionItem.php._.=^Bvendor/felixfbecker/language-server-protocol/src/MarkupContent.phpd_d0>vendor/felixfbecker/language-server-protocol/package-lock.jsonN_Nj\4vendor/felixfbecker/language-server-protocol/LICENSE_>99vendor/felixfbecker/language-server-protocol/package.jsonN_N2W>8vendor/felixfbecker/advanced-json-rpc/lib/Dispatcher.php_";vendor/felixfbecker/advanced-json-rpc/lib/ErrorResponse.php_Zv6vendor/felixfbecker/advanced-json-rpc/lib/Response.php_.1k5vendor/felixfbecker/advanced-json-rpc/lib/Request.php_b,:vendor/felixfbecker/advanced-json-rpc/lib/Notification.php _ Ϊ7vendor/felixfbecker/advanced-json-rpc/lib/ErrorCode.php _ t=vendor/felixfbecker/advanced-json-rpc/lib/SuccessResponse.php_nnid3vendor/felixfbecker/advanced-json-rpc/lib/Error.php_p >5vendor/felixfbecker/advanced-json-rpc/lib/Message.php _ Q睴-vendor/felixfbecker/advanced-json-rpc/LICENSE_>9?vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php_4vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php_ϋ>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.phpD_DmP޴>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php_cf:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php_4J>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php!_!X]7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php_5s:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php_,Wߴ=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php;_;~޴9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php_:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php_,y>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php_<;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php_j<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php_k :vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php _ 0MFvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.phpZ_Zˁ۴;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php_c:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.phpv_vҴ;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php _ ??w=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php/_/8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php_rD:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php_ٶ<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php_s[>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.phpR_R :vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php_hBvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php_<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php_[6@<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php_n;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php_Ep~ :vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.phpo_oMW<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.phpm _m ;9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php_pʹ7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php_ȭ9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.phpe_e_r!<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php_ Dvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.phpa_aҌ:9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php_u8Lk8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php~_~ @vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.phpL_Lːδ=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php _ v?vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php_J:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php,_,B=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php _ ^7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php_);vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php_!fX<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php_fqLvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php_jWQvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php_4մ9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php_`7vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php_]+5vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php|_|:Z<vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php_bO}Bvendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php_]x3vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php_%/>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php<_<`T:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php _  |;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php_HT:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php_ :vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php_ D~<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php_&=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php_:ɴ<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.phpv_vÍݴ9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php_v=Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php_9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.phpq_qe>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php_FAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php_ʣFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php_{@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php_R4vϴKvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php_ԴGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php_:UдIvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php_Up?@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php_ 0Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php_O(Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php_XUDvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php_jr"Evendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php_w(mKvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php_lsBvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php_ydFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php_'Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php_ZdrGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php_hy8Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php__۴Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php_ Dvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php_65Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php_VJGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php_oizFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php_¤;Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php_*m]@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php_Evendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php_Gʹ@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php_Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php_|8vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php_ȴ8vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php&_& =vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php_:=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php_]霴Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.phpy_yAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php_-4<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php_b):vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php_e>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php_tޢ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php_b;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php` _` `Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php>_>?˴@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php<_<CGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.phpJ_J@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php<_<NδCvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.phpB_BBvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php@_@uGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.phpJ_J2T Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.phpJ_J.Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.phpH_Hat8Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.phpH_H@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php<_<W.ӴEvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.phpF_FHC@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php<_<V&>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php_,%>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php_ڴ?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php_~ܴ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php_r:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php__ /,9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php+_+4Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php~_~^Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.phpY_YX(EAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.phpn _n ~AGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php_5 ;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php_V:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php_-B7 :vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php_==vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php_S >vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.phpB_B#S:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php_82X9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.phpG_GɒҴ=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php _ rIvendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php_:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php}_}i;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php_2Ð<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php_0>잴?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php_Tl=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php-_-À"?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php1_1:=^>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php/_/ ɴ@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php3_3H @vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php3_3δE?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php1_1>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php_zh<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php_!3vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php_44vendor/nikic/php-parser/lib/PhpParser/Node/Param.phpS _S ̴@vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php:_:9vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.php-_-y=vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php_?5vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php_H1Hvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php+_+㣱Evendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php__Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php_끴Kvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php_UгGvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php_X; Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php_޴Jvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php_^Evendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php_{΢Dvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php_̘S-=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php_Kh@vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php_v>vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php-_-N'q=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php _ O=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php_[ e68vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php_c ழ;vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.phpc_c2vendor/nikic/php-parser/lib/PhpParser/Node/Arg.php_,);vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.phpH_H`3vendor/nikic/php-parser/lib/PhpParser/Node/Name.phpR_RZ8vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php_ɴ<vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php(_(qҬ5vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php_wS5vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php _ h@vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.phpI_IEi[/vendor/nikic/php-parser/lib/PhpParser/Lexer.phpFY_FY95vendor/nikic/php-parser/lib/PhpParser/NameContext.php&,_&,^8vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php/_/ /ʴ6vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php`_`'0vendor/nikic/php-parser/lib/PhpParser/Parser.php_0)7vendor/nikic/php-parser/lib/PhpParser/ParserFactory.phpm_m5=vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.phpA_AsPLvendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php_њ9vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php__m(>vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php"_" QV;vendor/nikic/php-parser/lib/PhpParser/Internal/DiffElem.phpF_F1vendor/nikic/php-parser/lib/PhpParser/Builder.php_eFvendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.phpn_nU$@vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php_#9vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php$_$*Kvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php_BT]vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php_Q#Pvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php2_2ʙ~jWvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php_Mvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.phpc_c HMvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php)_)7eWvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php _ -޴Svendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.phpO_Ou>UMvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php_Ovendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.phpc_c G534vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php _ G8vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php)_)BDvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php_zBvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php+_+DKvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php_c^Mvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php _ aNIvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php_*Dvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php_E=vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.phpD_D hD8vendor/nikic/php-parser/lib/PhpParser/Builder/Method.phpW_W i<vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php1_1)Dvendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.phpB_B.NP7vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php _ .O״6vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php_v8vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.phpN_N!Uܴ<vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php# _# 笪8vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php'_'_:vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php_;vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.phpW_W7JJ>vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php%_%U`r:vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.phpx_x{~{\6vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php_{/vendor/nikic/php-parser/lib/PhpParser/Error.php_(1vendor/nikic/php-parser/lib/PhpParser/Comment.php_ߴAvendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php_ʿ?vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php_Q !.vendor/nikic/php-parser/lib/PhpParser/Node.php_M8vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php_l5vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.phpC_C=7vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.phpj)_j)-k#9vendor/nikic/php-parser/lib/PhpParser/Parser/Multiple.php_&5vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.phpU_Uyj7vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php_71I5vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php`_`rʹ%vendor/nikic/php-parser/bin/php-parse_"ϓ(vendor/nikic/php-parser/grammar/tokens.y _ v&vendor/nikic/php-parser/grammar/php7.y_I&vendor/nikic/php-parser/grammar/php5.y__(A/vendor/nikic/php-parser/grammar/parser.template _ -ɚQ2vendor/nikic/php-parser/grammar/rebuildParsers.php_ __ 8ݴ/vendor/nikic/php-parser/grammar/tokens.template*_*_ִvendor/nikic/php-parser/LICENSE_*3vendor/phpdocumentor/reflection-common/src/File.php_SYl6vendor/phpdocumentor/reflection-common/src/Project.php_Kn6vendor/phpdocumentor/reflection-common/src/Element.phpI_IW7vendor/phpdocumentor/reflection-common/src/Location.php_T%s4vendor/phpdocumentor/reflection-common/src/Fqsen.php_h꿴=vendor/phpdocumentor/reflection-common/src/ProjectFactory.php_.vendor/phpdocumentor/reflection-common/LICENSE9_9*2Ȑ@vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php(_(bNƴ9vendor/phpdocumentor/reflection-docblock/src/DocBlock.php_]vlGvendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php_h0TEvendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php_8Lvendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.phpF_F9Dvendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.phpv_vΈ=vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php_ 4Dvendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php_-τtEvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php4_4ؕȕCvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php _ Evendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.phpQ#_Q# Lvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php_pEFvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php_lŴDvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php _ ϴJvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php=_=9oFvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.phpg _g LDvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php_^ᏴFvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.phpF _F G.Ivendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php _ Cvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php_Bvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.phpu_uך~Evendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.phpW _W h2ySvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php-_-PCvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.phpe _e Gvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php_> ӴEvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.phpR _R cQ Evendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php]_]kHvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.phpv_vЀKvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php_nIvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php_c5Fvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php_df;]vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php`_`;Wvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php_Rvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php_b]Lvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php]_]mNvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php_ 1Fvendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php _ eTLvendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php:_:\Hvendor/phpdocumentor/reflection-docblock/src/Exception/PcreException.php_/S6vendor/phpdocumentor/reflection-docblock/src/Utils.php _ FIvendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.phpg_g}0vendor/phpdocumentor/reflection-docblock/LICENSE8_8ʴ/vendor/phpdocumentor/type-resolver/src/Type.php_Rk8vendor/phpdocumentor/type-resolver/src/Types/Context.php _ 3e;vendor/phpdocumentor/type-resolver/src/Types/Expression.php_8A?vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php _ O}+<vendor/phpdocumentor/type-resolver/src/Types/ClassString.phpf_fYƴ:vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php_8vendor/phpdocumentor/type-resolver/src/Types/Parent_.php3_3N]\8vendor/phpdocumentor/type-resolver/src/Types/Static_.phpT_T M7vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php_`]9vendor/phpdocumentor/type-resolver/src/Types/Nullable.php_6vendor/phpdocumentor/type-resolver/src/Types/Null_.php_]i6D8vendor/phpdocumentor/type-resolver/src/Types/Boolean.php_մ8vendor/phpdocumentor/type-resolver/src/Types/Integer.php_ 9vendor/phpdocumentor/type-resolver/src/Types/Compound.php\_\;#ɴ6vendor/phpdocumentor/type-resolver/src/Types/Void_.phpV_V$8vendor/phpdocumentor/type-resolver/src/Types/Object_.php_k7vendor/phpdocumentor/type-resolver/src/Types/Float_.php_$V:vendor/phpdocumentor/type-resolver/src/Types/Resource_.php_.˴7vendor/phpdocumentor/type-resolver/src/Types/Scalar.php_)ౢ:vendor/phpdocumentor/type-resolver/src/Types/Callable_.php_0}ô;vendor/phpdocumentor/type-resolver/src/Types/Collection.php_V(=vendor/phpdocumentor/type-resolver/src/Types/Intersection.phpk_kW]5vendor/phpdocumentor/type-resolver/src/Types/This.php_4q?vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php:_:zɴ6vendor/phpdocumentor/type-resolver/src/Types/Self_.php_m58vendor/phpdocumentor/type-resolver/src/Types/String_.php_Ң 47vendor/phpdocumentor/type-resolver/src/Types/Array_.php!_!}O=vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php _ O5vendor/phpdocumentor/type-resolver/src/PseudoType.php_.7vendor/phpdocumentor/type-resolver/src/TypeResolver.phpVQ_VQuՒ8vendor/phpdocumentor/type-resolver/src/FqsenResolver.php _ <vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php_F=vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php_,*vendor/phpdocumentor/type-resolver/LICENSE8_8ʴ+vendor/dnoegel/php-xdg-base-dir/src/Xdg.php _ :('vendor/dnoegel/php-xdg-base-dir/LICENSE!_!W&0vendor/netresearch/jsonmapper/src/JsonMapper.php"k_"knL:vendor/netresearch/jsonmapper/src/JsonMapper/Exception.php_Oa:%vendor/netresearch/jsonmapper/LICENSER(_R((}.vendor/openlss/lib-array2xml/LSS/Array2XML.phpf _f ~.vendor/openlss/lib-array2xml/LSS/XML2Array.php_f$vendor/openlss/lib-array2xml/COPYINGJ_JƤ~+vendor/openlss/lib-array2xml/COPYING LESSER_(\%vendor/composer/autoload_classmap.php8_8m^Y-vendor/composer/xdebug-handler/src/Status.phpO_OB0vendor/composer/xdebug-handler/src/PhpConfig.php0_0>4vendor/composer/xdebug-handler/src/XdebugHandler.phphG_hG0.vendor/composer/xdebug-handler/src/Process.php_  &vendor/composer/xdebug-handler/LICENSE)_)#;^#vendor/composer/autoload_static.php_Zvendor/composer/ClassLoader.php4_4s|!vendor/composer/autoload_psr4.php _ λ5 "vendor/composer/autoload_files.php_?mvendor/composer/LICENSE._. Tvendor/composer/package-versions-deprecated/src/PackageVersions/FallbackVersions.php_@]&wMvendor/composer/package-versions-deprecated/src/PackageVersions/Installer.php$_$Lvendor/composer/package-versions-deprecated/src/PackageVersions/Versions.php_.33vendor/composer/package-versions-deprecated/LICENSE!_!!vendor/composer/autoload_real.phpu_u(vendor/composer/semver/src/Intervals.php[_[3c,vendor/composer/semver/src/VersionParser.phpT_TOM˴%vendor/composer/semver/src/Semver.php_I'4vendor/composer/semver/src/Constraint/Constraint.php1_1'tY9vendor/composer/semver/src/Constraint/MultiConstraint.php_STRc=vendor/composer/semver/src/Constraint/MatchNoneConstraint.php_A=vendor/composer/semver/src/Constraint/ConstraintInterface.php_"Դ<vendor/composer/semver/src/Constraint/MatchAllConstraint.php_z/vendor/composer/semver/src/Constraint/Bound.php _ wJ'vendor/composer/semver/src/Interval.phpo_ou^/vendor/composer/semver/src/CompilingMatcher.php _ #L)vendor/composer/semver/src/Comparator.php _ VZvendor/composer/semver/LICENSE_Bh'vendor/composer/autoload_namespaces.php_t!״vendor/autoload.php_F"vendor/sebastian/diff/src/Diff.phpy_y:I?vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php#_#(?vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php<_<'@:vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.phpf _f c{sCvendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php+_+;O=vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.phpU!_U!$vendor/sebastian/diff/src/Differ.php&_&/Mvendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php8_83fiʹ$vendor/sebastian/diff/src/Parser.php _ T@vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php_@|>vendor/sebastian/diff/src/Exception/ConfigurationException.php_ ߴ1vendor/sebastian/diff/src/Exception/Exception.phpX_Xf@vendor/sebastian/diff/src/Exception/InvalidArgumentException.php_nʹ#vendor/sebastian/diff/src/Chunk.php_"vendor/sebastian/diff/src/Line.php[_[| 4Ovendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php_J|qvendor/sebastian/diff/LICENSE _ a1!vendor/amphp/amp/lib/Iterator.phpx_xrY*vendor/amphp/amp/lib/InvalidYieldError.php_[$vendor/amphp/amp/lib/LazyPromise.php_[tU-vendor/amphp/amp/lib/MultiReasonException.php_P vendor/amphp/amp/lib/Promise.php_m!vendor/amphp/amp/lib/Producer.php6_6"q vendor/amphp/amp/lib/Success.php_ vendor/amphp/amp/lib/Emitter.php_Q%ʴ vendor/amphp/amp/lib/Delayed.php"_"6z'+vendor/amphp/amp/lib/CancelledException.phpk_kV;"vendor/amphp/amp/lib/Coroutine.php_]3&vendor/amphp/amp/lib/Loop/UvDriver.php,_,2儲)vendor/amphp/amp/lib/Loop/EventDriver.php(_(@Y&vendor/amphp/amp/lib/Loop/EvDriver.phpw$_w$!9vendor/amphp/amp/lib/Loop/UnsupportedFeatureException.php(_(6vendor/amphp/amp/lib/Loop/Internal/TimerQueueEntry.php;_;̕1vendor/amphp/amp/lib/Loop/Internal/TimerQueue.php_Im+vendor/amphp/amp/lib/Loop/DriverFactory.phpk_k2dp%vendor/amphp/amp/lib/Loop/Watcher.php_w+vendor/amphp/amp/lib/Loop/TracingDriver.phpS_S|&$vendor/amphp/amp/lib/Loop/Driver.phpk_k*vendor/amphp/amp/lib/Loop/NativeDriver.phpq4_q4Ef1vendor/amphp/amp/lib/Loop/InvalidWatcherError.php*_*$[J vendor/amphp/amp/lib/Failure.php_r)&vendor/amphp/amp/lib/CallableMaker.php _ ޹ Ŵ0vendor/amphp/amp/lib/CancellationTokenSource.php3_3.9!*vendor/amphp/amp/lib/CancellationToken.php_m ꓴ0vendor/amphp/amp/lib/Internal/PrivatePromise.phpi_i寭*vendor/amphp/amp/lib/Internal/Producer.php[_[+޴-vendor/amphp/amp/lib/Internal/Placeholder.php_;1vendor/amphp/amp/lib/Internal/ResolutionQueue.php( _( _ݴ1vendor/amphp/amp/lib/Internal/PrivateIterator.php_8u+vendor/amphp/amp/lib/Internal/functions.php _ եpfvendor/amphp/amp/lib/Struct.php_ٴ1vendor/amphp/amp/lib/TimeoutCancellationToken.php_r δ)vendor/amphp/amp/lib/TimeoutException.php_o.vendor/amphp/amp/lib/NullCancellationToken.php_ҿFavendor/amphp/amp/lib/Loop.phpF_F໴2vendor/amphp/amp/lib/CombinedCancellationToken.php_b!vendor/amphp/amp/lib/Deferred.php_"vendor/amphp/amp/lib/functions.phph_h9Ҵvendor/amphp/amp/LICENSEq_qrg0vendor/amphp/byte-stream/lib/ZlibInputStream.php _ ǼAvendor/amphp/byte-stream/lib/Base64/Base64EncodingInputStream.php_J>Bvendor/amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.phpf_fZT>Avendor/amphp/byte-stream/lib/Base64/Base64DecodingInputStream.phpK_K*MBvendor/amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.php _ ̭/4vendor/amphp/byte-stream/lib/ResourceInputStream.phpt_ti1vendor/amphp/byte-stream/lib/ZlibOutputStream.php _ 6(vendor/amphp/byte-stream/lib/Payload.php _ ءj0vendor/amphp/byte-stream/lib/ClosedException.php_;11vendor/amphp/byte-stream/lib/PendingReadError.php_|-vendor/amphp/byte-stream/lib/OutputStream.php_ml0vendor/amphp/byte-stream/lib/StreamException.phpf_faf,vendor/amphp/byte-stream/lib/InputStream.phpk_k /vendor/amphp/byte-stream/lib/InMemoryStream.php_5vendor/amphp/byte-stream/lib/ResourceOutputStream.php-_- m+vendor/amphp/byte-stream/lib/LineReader.phpj_j{(vendor/amphp/byte-stream/lib/Message.php_߂/vendor/amphp/byte-stream/lib/IteratorStream.php_c˴*vendor/amphp/byte-stream/lib/functions.php_sb+-vendor/amphp/byte-stream/lib/OutputBuffer.php_1vendor/amphp/byte-stream/lib/InputStreamChain.phpx_xԴ vendor/amphp/byte-stream/LICENSE6_6\c2stubs/Xdebug.php_ȴ"stubs/CoreImmutableClasses.phpstubd_d\"stubs/CoreGenericFunctions.phpstubC_C=stubs/ext-ds.phpzF_zF״ stubs/CoreGenericClasses.phpstub_cpsalm_Zps)src/psalm-refactor.php3 _3 Ŵsrc/psalter.php:_:g src/psalm.php\Z_\Z 1src/psalm_plugin.php]_]dsrc/psalm-language-server.phpW_WDĴsrc/spl_object_id.php_]Kgsrc/command_functions.php@_@,ssrc/Psalm/Context.phpQ_Q'src/Psalm/NodeTypeProvider.php _ 0-src/Psalm/IssueBuffer.phpf_fjh$src/Psalm/FileBasedPluginAdapter.php_*src/Psalm/Type.phpM_M zsrc/Psalm/Config.php_e )src/Psalm/Issue/TooManyTemplateParams.php_Kz"src/Psalm/Issue/InternalMethod.php_^:&src/Psalm/Issue/InvalidStringClass.php_./src/Psalm/Issue/UnimplementedAbstractMethod.php_އc2src/Psalm/Issue/PossiblyNullPropertyAssignment.php9_9٦,src/Psalm/Issue/UnnecessaryVarAnnotation.php_1X0src/Psalm/Issue/ImplementedParamTypeMismatch.php_@%src/Psalm/Issue/DuplicateFunction.php_\!src/Psalm/Issue/InvalidParent.php_ܓF#src/Psalm/Issue/InvalidArgument.php_f\$src/Psalm/Issue/ImpureMethodCall.php_(h5&src/Psalm/Issue/InaccessibleMethod.php_m15src/Psalm/Issue/PossiblyInvalidPropertyAssignment.php_YM'src/Psalm/Issue/PossiblyUnusedParam.php_/0/-src/Psalm/Issue/InvalidFalsableReturnType.php_R(src/Psalm/Issue/ArgumentTypeCoercion.php_I(T"src/Psalm/Issue/UndefinedClass.php_pxe+src/Psalm/Issue/NullableReturnStatement.php_NĴsrc/Psalm/Issue/Trace.php_&src/Psalm/Issue/RawObjectIteration.php_/<`'src/Psalm/Issue/ImpurePropertyFetch.php_Yϴsrc/Psalm/Issue/PluginIssue.php]_]䕿H/src/Psalm/Issue/LessSpecificReturnStatement.php_)src/Psalm/Issue/UnrecognizedStatement.php_Q ʴ#src/Psalm/Issue/UnevaluatedCode.php_δ%src/Psalm/Issue/CircularReference.php_Q$*src/Psalm/Issue/OverriddenMethodAccess.php_*src/Psalm/Issue/InvalidLiteralArgument.php_Ճb(src/Psalm/Issue/PossiblyInvalidClone.php_"#src/Psalm/Issue/InvalidDocblock.php_`(src/Psalm/Issue/ImpureStaticProperty.php_%:Դ.src/Psalm/Issue/UncaughtThrowInGlobalScope.php_n1src/Psalm/Issue/ExtensionRequirementViolation.php_5̚!src/Psalm/Issue/MixedArgument.php_8'src/Psalm/Issue/UnusedPsalmSuppress.php_wF.$src/Psalm/Issue/MixedArrayOffset.php_w]#src/Psalm/Issue/UndefinedMethod.php_!vش*src/Psalm/Issue/TypeDoesNotContainType.phpr_rZ3.src/Psalm/Issue/PossiblyInvalidArrayAccess.php_茥'src/Psalm/Issue/ContinueOutsideLoop.php_;nk+src/Psalm/Issue/PossiblyInvalidIterator.php_D.#src/Psalm/Issue/NullArrayOffset.php_At[+src/Psalm/Issue/PossiblyInvalidArgument.php_|%src/Psalm/Issue/NonStaticSelfCall.php_Xs&src/Psalm/Issue/ImpureFunctionCall.php_a'%src/Psalm/Issue/UndefinedVariable.php_)a!src/Psalm/Issue/VariableIssue.php_Yp-src/Psalm/Issue/InvalidPropertyAssignment.php_)src/Psalm/Issue/PossiblyFalseIterator.php_10src/Psalm/Issue/ReferenceConstraintViolation.php_*src/Psalm/Issue/UndefinedPropertyFetch.php_C*src/Psalm/Issue/PossiblyUnusedProperty.php_m)src/Psalm/Issue/PossiblyFalseArgument.php_Q,src/Psalm/Issue/OverriddenPropertyAccess.php_X/%src/Psalm/Issue/NullPropertyFetch.php%_%~"src/Psalm/Issue/UndefinedTrace.php_u)src/Psalm/Issue/NoInterfaceProperties.php_< ۴+src/Psalm/Issue/FalsableReturnStatement.php_|\ִ%src/Psalm/Issue/ParamNameMismatch.php_/; src/Psalm/Issue/InvalidScope.php_+"늴%src/Psalm/Issue/MissingReturnType.php_c6!src/Psalm/Issue/ForbiddenCode.php_C8src/Psalm/Issue/PossiblyFalsePropertyAssignmentValue.php__x"src/Psalm/Issue/DuplicateParam.php_,Z] src/Psalm/Issue/MixedOperand.php_%2j'src/Psalm/Issue/UnsafeInstantiation.php_,src/Psalm/Issue/PossiblyNullFunctionCall.php_bDp)src/Psalm/Issue/UninitializedProperty.php_g4-src/Psalm/Issue/PossiblyInvalidMethodCall.php_ 3src/Psalm/Issue/UndefinedThisPropertyAssignment.php_IJ4src/Psalm/Issue/UndefinedMagicPropertyAssignment.php_K:['src/Psalm/Issue/PossiblyInvalidCast.php_&src/Psalm/Issue/InvalidArrayOffset.php_p4src/Psalm/Issue/MoreSpecificImplementedParamType.php_2s*src/Psalm/Issue/InvalidPassByReference.php_%  src/Psalm/Issue/TaintedInput.php_)7src/Psalm/Issue/PossiblyNullPropertyAssignmentValue.php_Z(src/Psalm/Issue/PossiblyUnusedMethod.php_ s/̴src/Psalm/Issue/NoValue.php_81src/Psalm/Issue/MismatchingDocblockReturnType.php_[80src/Psalm/Issue/TraitMethodSignatureMismatch.php_J[.src/Psalm/Issue/UndefinedThisPropertyFetch.php_%v(src/Psalm/Issue/ImplicitToStringCast.php_‡*src/Psalm/Issue/LessSpecificReturnType.php_lʹ-src/Psalm/Issue/MixedArgumentTypeCoercion.php_#j"src/Psalm/Issue/ImpureVariable.php_7)src/Psalm/Issue/AbstractInstantiation.php_x]jδsrc/Psalm/Issue/NullOperand.php_X/src/Psalm/Issue/ImpureByReferenceAssignment.php_P_!src/Psalm/Issue/PropertyIssue.phps_s!&src/Psalm/Issue/AbstractMethodCall.php_9-src/Psalm/Issue/DocblockTypeContradiction.phpv_vab(src/Psalm/Issue/MixedReturnStatement.php_i)`#(src/Psalm/Issue/InvalidTemplateParam.php_%src/Psalm/Issue/MutableDependency.php_+src/Psalm/Issue/MethodIssue.php_=.src/Psalm/Issue/MissingImmutableAnnotation.php_EW&src/Psalm/Issue/InvalidExtendClass.php_{ϴ+src/Psalm/Issue/MissingClosureParamType.php_i>,src/Psalm/Issue/UndefinedInterfaceMethod.php_ $src/Psalm/Issue/MixedArrayAccess.php_Դsrc/Psalm/Issue/CodeIssue.php _ n/src/Psalm/Issue/MixedStringOffsetAssignment.php_EDcʴ#src/Psalm/Issue/StringIncrement.php_&src/Psalm/Issue/RedundantCondition.phpo_o^7src/Psalm/Issue/RedundantConditionGivenDocblockType.php_~?w0src/Psalm/Issue/MismatchingDocblockParamType.php_`*src/Psalm/Issue/NullPropertyAssignment.php*_*t+src/Psalm/Issue/InvalidStaticInvocation.php_Y̴(src/Psalm/Issue/MixedArrayAssignment.php_|a%src/Psalm/Issue/UndefinedConstant.php_!M&'src/Psalm/Issue/InvalidParamDefault.php_$Ͱ"src/Psalm/Issue/UndefinedTrait.php_'src/Psalm/Issue/DeprecatedInterface.php_C'src/Psalm/Issue/UnresolvableInclude.php_$w-src/Psalm/Issue/PossiblyNullPropertyFetch.php4_4Qݴ#src/Psalm/Issue/MixedMethodCall.php_ę(src/Psalm/Issue/InvalidPropertyFetch.php_VŴ&src/Psalm/Issue/MissingConstructor.phpn_nj 4*src/Psalm/Issue/MoreSpecificReturnType.php_z/ src/Psalm/Issue/InvalidClass.php_+src/Psalm/Issue/PossiblyNullArrayOffset.php_!j:src/Psalm/Issue/PossiblyInvalidPropertyAssignmentValue.php_ɵ!src/Psalm/Issue/InternalClass.php_18$src/Psalm/Issue/MissingParamType.php_ I'src/Psalm/Issue/MissingDocblockType.php_r%src/Psalm/Issue/InvalidTypeImport.php_9h2src/Psalm/Issue/ConflictingReferenceConstraint.php_*src/Psalm/Issue/UndefinedDocblockClass.php_Lx3{+src/Psalm/Issue/PossiblyNullArrayAccess.php2_2e +5src/Psalm/Issue/MethodSignatureMustOmitReturnType.php_e?(src/Psalm/Issue/MissingTemplateParam.php_G3+src/Psalm/Issue/MixedInferredReturnType.php_ $src/Psalm/Issue/UnusedMethodCall.php_΅ src/Psalm/Issue/UnusedMethod.php_0src/Psalm/Issue/UnimplementedInterfaceMethod.php_O;!src/Psalm/Issue/ForbiddenEcho.php_ԅ%src/Psalm/Issue/MixedFunctionCall.php_ h!src/Psalm/Issue/InvalidGlobal.php_%j.src/Psalm/Issue/PossibleRawObjectIteration.php_4src/Psalm/Issue/UnusedClass.php_76}(src/Psalm/Issue/PropertyTypeCoercion.php_@:'src/Psalm/Issue/InvalidFunctionCall.php_3"src/Psalm/Issue/UnusedProperty.php_L{*src/Psalm/Issue/PossiblyInvalidOperand.php_[폂,src/Psalm/Issue/MissingClosureReturnType.php_U% src/Psalm/Issue/NullArgument.php_oV/src/Psalm/Issue/PropertyNotSetInConstructor.php_'aԴ1src/Psalm/Issue/ImplementedReturnTypeMismatch.php_ t*src/Psalm/Issue/UnrecognizedExpression.php_/i2src/Psalm/Issue/InvalidPropertyAssignmentValue.php_e$src/Psalm/Issue/LoopInvalidation.php_b-@(src/Psalm/Issue/InvalidNamedArgument.php_fc(src/Psalm/Issue/ImpureStaticVariable.php_È&src/Psalm/Issue/DeprecatedFunction.php_@/src/Psalm/Issue/UndefinedPropertyAssignment.php_ 'src/Psalm/Issue/MissingPropertyType.php_׻%src/Psalm/Issue/MissingDependency.php}_}( src/Psalm/Issue/InvalidThrow.php_S2P 3src/Psalm/Issue/PossiblyUndefinedGlobalVariable.php_Sx&src/Psalm/Issue/UndefinedInterface.php_%src/Psalm/Issue/UndefinedFunction.php_*E+src/Psalm/Issue/MixedReturnTypeCoercion.php_H/src/Psalm/Issue/PossiblyNullArrayAssignment.php_`#src/Psalm/Issue/InvalidCast.php_ I&src/Psalm/Issue/PsalmInternalError.php_%ݹ(src/Psalm/Issue/PossiblyFalseOperand.php_$ɴ&src/Psalm/Issue/DeprecatedConstant.php_k  src/Psalm/Issue/FalseOperand.php_H!src/Psalm/Issue/FunctionIssue.php_D+src/Psalm/Issue/UndefinedGlobalVariable.php_k*`(src/Psalm/Issue/PossiblyNullArgument.php_$src/Psalm/Issue/NullFunctionCall.php_Hcy~"src/Psalm/Issue/InvalidOperand.php_Q%src/Psalm/Issue/DuplicateArrayKey.php_*src/Psalm/Issue/MixedArrayTypeCoercion.php_NQ+src/Psalm/Issue/MixedPropertyAssignment.php_$)],#src/Psalm/Issue/TooFewArguments.php_m&0src/Psalm/Issue/ConstructorSignatureMismatch.php_UO+src/Psalm/Issue/MethodSignatureMismatch.php_/ src/Psalm/Issue/InvalidClone.php_p,src/Psalm/Issue/ImpurePropertyAssignment.php_S$src/Psalm/Issue/InternalProperty.php_vp!src/Psalm/Issue/ArgumentIssue.php_*src/Psalm/Issue/InterfaceInstantiation.php_isrc/Psalm/Issue/ClassIssue.php_̴"src/Psalm/Issue/UnusedVariable.php_>2src/Psalm/Issue/PossiblyInvalidArrayAssignment.php_~$src/Psalm/Issue/DeprecatedMethod.php_2p #src/Psalm/Issue/DeprecatedTrait.php_)݆0src/Psalm/Issue/PossiblyInvalidPropertyFetch.php_uD`src/Psalm/Issue/ParseError.php_`Pf*src/Psalm/Issue/InvalidReturnStatement.php_%~6-src/Psalm/Issue/RedundantIdentityWithTrue.php_,*%src/Psalm/Issue/InvalidMethodCall.php_O*src/Psalm/Issue/TypeDoesNotContainNull.phpr_roO0src/Psalm/Issue/PossiblyUndefinedArrayOffset.php_53#src/Psalm/Issue/MixedAssignment.php_9-src/Psalm/Issue/InaccessibleClassConstant.php_T*src/Psalm/Issue/PossiblyFalseReference.php_H3src/Psalm/Issue/PossiblyUndefinedIntArrayOffset.php_*~&src/Psalm/Issue/MixedPropertyFetch.php_Dn5src/Psalm/Issue/LessSpecificImplementedReturnType.php_r""src/Psalm/Issue/DuplicateClass.php_V6c#src/Psalm/Issue/InvalidToString.php_ӌPԴ+src/Psalm/Issue/PossiblyUndefinedMethod.php_2,src/Psalm/Issue/InvalidDocblockParamName.php_3 -src/Psalm/Issue/MixedPropertyTypeCoercion.php_rl  src/Psalm/Issue/InvalidCatch.php_@ʹ src/Psalm/Issue/NullIterator.php_3%(src/Psalm/Issue/PossiblyNullIterator.php_6$src/Psalm/Issue/AssignmentToVoid.php_`#src/Psalm/Issue/MissingFile.phpv_v)src/Psalm/Issue/MissingThrowsDocblock.php_)6src/Psalm/Issue/ImplementationRequirementViolation.php_[-src/Psalm/Issue/PossiblyUndefinedVariable.php_/src/Psalm/Issue/UndefinedMagicPropertyFetch.php_ 8'&src/Psalm/Issue/UnusedClosureParam.php_VɌ(src/Psalm/Issue/ParadoxicalCondition.php_sH$src/Psalm/Issue/EmptyArrayAccess.php_~*src/Psalm/Issue/InvalidArrayAssignment.php_YN src/Psalm/Issue/ReservedWord.php_a #src/Psalm/Issue/NullArrayAccess.php#_#P~%src/Psalm/Issue/InvalidReturnType.php_G(src/Psalm/Issue/InaccessibleProperty.php_]G+src/Psalm/Issue/UnhandledMatchCondition.php_(src/Psalm/Issue/UndefinedMagicMethod.php_A-src/Psalm/Issue/InvalidNullableReturnType.php_SM#src/Psalm/Issue/InvalidIterator.php_R.src/Psalm/Issue/PossiblyInvalidArrayOffset.php_nI'src/Psalm/Issue/PossiblyNullOperand.php_r&src/Psalm/Issue/UnusedFunctionCall.php_w&src/Psalm/Issue/InvalidArrayAccess.php_%Bƴ&src/Psalm/Issue/DeprecatedProperty.php_}Ǵ6src/Psalm/Issue/PossiblyUndefinedStringArrayOffset.php_B/()src/Psalm/Issue/InvalidScalarArgument.php_nj-src/Psalm/CodeLocation/ParseErrorLocation.php_5/src/Psalm/CodeLocation/DocblockTypeLocation.php_y;src/Psalm/CodeLocation/Raw.php_>Mpsrc/Psalm/Plugin/Shepherd.phpR_R*X4src/Psalm/Plugin/Hook/AfterFileAnalysisInterface.php_ֹp;5src/Psalm/Plugin/Hook/BeforeFileAnalysisInterface.php_@u9src/Psalm/Plugin/Hook/AfterClassLikeAnalysisInterface.php_?fb;src/Psalm/Plugin/Hook/MethodVisibilityProviderInterface.php_Ǯ1<src/Psalm/Plugin/Hook/PropertyExistenceProviderInterface.php-_-F9src/Psalm/Plugin/Hook/AfterStatementAnalysisInterface.phpp_pJ:(9src/Psalm/Plugin/Hook/FunctionParamsProviderInterface.php_;۴:src/Psalm/Plugin/Hook/MethodExistenceProviderInterface.php_Դ:src/Psalm/Plugin/Hook/AfterMethodCallAnalysisInterface.phpL_LΌd<src/Psalm/Plugin/Hook/AfterFunctionCallAnalysisInterface.php_9 :src/Psalm/Plugin/Hook/AfterExpressionAnalysisInterface.phpt_tQk;src/Psalm/Plugin/Hook/MethodReturnTypeProviderInterface.php_@4src/Psalm/Plugin/Hook/StringInterpreterInterface.php_q<src/Psalm/Plugin/Hook/AfterFunctionLikeAnalysisInterface.php_LNѴAsrc/Psalm/Plugin/Hook/AfterEveryFunctionCallAnalysisInterface.php_![7src/Psalm/Plugin/Hook/MethodParamsProviderInterface.php_*׳0src/Psalm/Plugin/Hook/AfterAnalysisInterface.php_=src/Psalm/Plugin/Hook/PropertyVisibilityProviderInterface.php_|9src/Psalm/Plugin/Hook/AfterCodebasePopulatedInterface.php_e27src/Psalm/Plugin/Hook/PropertyTypeProviderInterface.php7_7`ʴ<src/Psalm/Plugin/Hook/FunctionExistenceProviderInterface.php|_|lt6src/Psalm/Plugin/Hook/AfterClassLikeVisitInterface.phpL_Lj{=src/Psalm/Plugin/Hook/FunctionReturnTypeProviderInterface.php_?src/Psalm/Plugin/Hook/AfterClassLikeExistenceCheckInterface.php_Sʗ.src/Psalm/Plugin/PluginEntryPointInterface.php_<?*src/Psalm/Plugin/RegistrationInterface.php_Vޢysrc/Psalm/Type/Atomic.php!F_!FV src/Psalm/Type/Atomic/TNever.phpe_e|)src/Psalm/Type/Atomic/TNonEmptyScalar.php_#src/Psalm/Type/Atomic/TArrayKey.phpi_i?ӡsrc/Psalm/Type/Atomic/TInt.php!_!-src/Psalm/Type/Atomic/TKeyOfClassConstant.php _ Sߴ%src/Psalm/Type/Atomic/TEmptyMixed.php_ُsrc/Psalm/Type/Atomic/TList.php_ #src/Psalm/Type/Atomic/TCallable.php(_(%v{src/Psalm/Type/Atomic/TVoid.php_H񛫴$src/Psalm/Type/Atomic/TTypeAlias.php_RG'src/Psalm/Type/Atomic/TNonEmptyList.phpF_FҾ@-src/Psalm/Type/Atomic/TLiteralClassString.php_ߴsrc/Psalm/Type/Atomic/TNull.phpT_T[ src/Psalm/Type/Atomic/TMixed.phpg_gO=&src/Psalm/Type/Atomic/TPositiveInt.php_w2~)src/Psalm/Type/Atomic/TClosedResource.php_i/ݷ)src/Psalm/Type/Atomic/TCallableObject.php._.Uz-src/Psalm/Type/Atomic/TTemplateParamClass.php_6rG&src/Psalm/Type/Atomic/GenericTrait.php_NZ(src/Psalm/Type/Atomic/TNumericString.php<_<}(src/Psalm/Type/Atomic/TNonEmptyMixed.php_`%src/Psalm/Type/Atomic/TKeyedArray.php*_*ťӴ/src/Psalm/Type/Atomic/TValueOfClassConstant.php_ (src/Psalm/Type/Atomic/TCallableArray.php>_>У&src/Psalm/Type/Atomic/TConditional.php8 _8 'src/Psalm/Type/Atomic/TSingleLetter.php`_`(src/Psalm/Type/Atomic/TTemplateParam.php^ _^ A"=&src/Psalm/Type/Atomic/TClassString.php_=8)src/Psalm/Type/Atomic/TCallableString.php_*W~)src/Psalm/Type/Atomic/TClassStringMap.php_MPw"src/Psalm/Type/Atomic/TNumeric.phpd_dF,src/Psalm/Type/Atomic/TDependentGetClass.php_[ src/Psalm/Type/Atomic/TFalse.phpc_cMG״.src/Psalm/Type/Atomic/TScalarClassConstant.php_Ս#src/Psalm/Type/Atomic/TResource.php`_`{?Դ+src/Psalm/Type/Atomic/TDependentGetType.php#_#/src/Psalm/Type/Atomic/TTrue.php`_`E2e/src/Psalm/Type/Atomic/TObjectWithProperties.php?_?&src/Psalm/Type/Atomic/TTraitString.php_n*src/Psalm/Type/Atomic/TLowercaseString.php_k&src/Psalm/Type/Atomic/TNamedObject.php& _& ~%src/Psalm/Type/Atomic/TLiteralInt.php_Se1src/Psalm/Type/Atomic/TAnonymousClassInstance.php_.7)src/Psalm/Type/Atomic/TAssertionFalsy.php_u src/Psalm/Type/Atomic/Scalar.php_;Ӵ)src/Psalm/Type/Atomic/TNonEmptyString.php_Nn!src/Psalm/Type/Atomic/TString.php-_-]src/Psalm/Type/Atomic/TBool.php%_%ߴ(src/Psalm/Type/Atomic/TGenericObject.php# _# u(src/Psalm/Type/Atomic/TTemplateKeyOf.php/_/'src/Psalm/Type/Atomic/TEmptyNumeric.php_!src/Psalm/Type/Atomic/TObject.php_{ϴ src/Psalm/Type/Atomic/TFloat.php)_),2src/Psalm/Type/Atomic/TNonEmptyLowercaseString.php_K](src/Psalm/Type/Atomic/TLiteralString.php?_?렴!src/Psalm/Type/Atomic/TScalar.php_N src/Psalm/Type/Atomic/TEmpty.php_'`'src/Psalm/Type/Atomic/CallableTrait.php_z(src/Psalm/Type/Atomic/TNonEmptyArray.php _ ʴ#src/Psalm/Type/Atomic/TIterable.phpy _y z'src/Psalm/Type/Atomic/TLiteralFloat.php_Uac&src/Psalm/Type/Atomic/TEmptyScalar.php_s src/Psalm/Type/Atomic/TArray.php3_3E,src/Psalm/Type/Atomic/THtmlEscapedString.php_0src/Psalm/Type/Atomic/TDependentGetDebugType.php/_/;(.src/Psalm/Type/Atomic/HasIntersectionTrait.php _ dM'src/Psalm/Type/Atomic/TCallableList.php_&0d-src/Psalm/Type/Atomic/TCallableKeyedArray.php _ [!0src/Psalm/Type/Atomic/TTemplateIndexedAccess.php_b"src/Psalm/Type/Atomic/TClosure.phpZ_Zfssrc/Psalm/Type/TaintKind.phpu_uš1src/Psalm/Type/Algebra.phpa_aVsrc/Psalm/Type/Union.php_Usrc/Psalm/Type/TypeNode.php_Å˴src/Psalm/Type/NodeVisitor.php_$c;!src/Psalm/Type/TaintKindGroup.php-_-%src/Psalm/Type/Reconciler.php!_!Wsrc/Psalm/Aliases.php_d0src/Psalm/Codebase.php_$src/Psalm/Progress/DebugProgress.php_ ȴsrc/Psalm/Progress/Progress.php_ h#src/Psalm/Progress/LongProgress.php _ 5Q̴&src/Psalm/Progress/DefaultProgress.php_yfm##src/Psalm/Progress/VoidProgress.phpZ_Zfsrc/Psalm/DocComment.php`_`ALBsrc/Psalm/Report/JsonReport.phpq_qr"-"src/Psalm/Report/ConsoleReport.phpm _m "src/Psalm/Report/CompactReport.phph _h if src/Psalm/Report/XmlReport.phpX_XxkK(src/Psalm/Report/GithubActionsReport.php&_&]src/Psalm/Report/TextReport.php%_%5$src/Psalm/Report/SonarqubeReport.phpW_W8to&src/Psalm/Report/JsonSummaryReport.php_ݳ#src/Psalm/Report/PhpStormReport.phpo _o {ƴ!src/Psalm/Report/PylintReport.phpO_O z %src/Psalm/Report/CheckstyleReport.php _ $$"src/Psalm/Report/ReportOptions.phpF_FT>[ src/Psalm/Report/EmacsReport.php_ src/Psalm/Report/JunitReport.phpn_nF*src/Psalm/Internal/ReferenceConstraint.php_@2src/Psalm/Internal/Provider/StatementsProvider.phpx4_x4lF7src/Psalm/Internal/Provider/MethodExistenceProvider.php_u !,4src/Psalm/Internal/Provider/MethodParamsProvider.php _ *ER'9src/Psalm/Internal/Provider/PropertyExistenceProvider.php_S9src/Psalm/Internal/Provider/FunctionExistenceProvider.php_i1Ŵ0src/Psalm/Internal/Provider/NodeDataProvider.php_3src/Psalm/Internal/Provider/ParserCacheProvider.php-_-Eo8src/Psalm/Internal/Provider/ClassLikeStorageProvider.php _ "lf3src/Psalm/Internal/Provider/FileStorageProvider.php _ +݃=src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php_9TشKsrc/Psalm/Internal/Provider/ReturnTypeProvider/MktimeReturnTypeProvider.php_-Nsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.phpA_AV7Nsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayRandReturnTypeProvider.php _ 8!_1Rsrc/Psalm/Internal/Provider/ReturnTypeProvider/GetObjectVarsReturnTypeProvider.php+_+{l,[src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPointerAdjustmentReturnTypeProvider.phpU _U |Tsrc/Psalm/Internal/Provider/ReturnTypeProvider/IteratorToArrayReturnTypeProvider.php _ gPsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReduceReturnTypeProvider.phpl%_l%$<Ssrc/Psalm/Internal/Provider/ReturnTypeProvider/FirstArgStringReturnTypeProvider.php_S<ŴPsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayValuesReturnTypeProvider.php_J9tOsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArraySliceReturnTypeProvider.php _ pۭMsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php;_;X ۴Osrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMergeReturnTypeProvider.phpt!_t! /1Ksrc/Psalm/Internal/Provider/ReturnTypeProvider/HexdecReturnTypeProvider.php^_^8Osrc/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php_5POsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayChunkReturnTypeProvider.php_OĴPsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayColumnReturnTypeProvider.php_yȜTsrc/Psalm/Internal/Provider/ReturnTypeProvider/GetClassMethodsReturnTypeProvider.phpK_KSHɴHsrc/Psalm/Internal/Provider/ReturnTypeProvider/SimpleXmlElementAsXml.php_^ѴMsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPadReturnTypeProvider.phpq_qnDxMsrc/Psalm/Internal/Provider/ReturnTypeProvider/ParseUrlReturnTypeProvider.php_K|Psrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayUniqueReturnTypeProvider.php_Lsrc/Psalm/Internal/Provider/ReturnTypeProvider/ExplodeReturnTypeProvider.php2 _2 oceSsrc/Psalm/Internal/Provider/ReturnTypeProvider/VersionCompareReturnTypeProvider.phpz _z \lS4Nsrc/Psalm/Internal/Provider/ReturnTypeProvider/FilterVarReturnTypeProvider.phpU_U.pR Esrc/Psalm/Internal/Provider/ReturnTypeProvider/DomNodeAppendChild.php_,Xsrc/Psalm/Internal/Provider/ReturnTypeProvider/ClosureFromCallableReturnTypeProvider.php_aNPsrc/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFilterReturnTypeProvider.php$_$`xQsrc/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php _ 0src/Psalm/Internal/Diff/FileStatementsDiffer.php_!v#)src/Psalm/Internal/DataFlow/TaintSink.phpm_m>*+$src/Psalm/Internal/DataFlow/Path.php_o4,src/Psalm/Internal/DataFlow/DataFlowNode.phpA _A jn+src/Psalm/Internal/DataFlow/TaintSource.phpo_o?src/Psalm/Internal/Composer.phpr_rxG>5src/Psalm/Internal/Codebase/ReferenceMapGenerator.php{_{h4src/Psalm/Internal/Codebase/ConstantTypeResolver.php4"_4"QE.-src/Psalm/Internal/Codebase/DataFlowGraph.phpV _V b!۴'src/Psalm/Internal/Codebase/Methods.php߅_߅bp)src/Psalm/Internal/Codebase/Populator.php_ޠp*src/Psalm/Internal/Codebase/ClassLikes.php_N6src/Psalm/Internal/Codebase/InternalCallMapHandler.phpf3_f3柴'src/Psalm/Internal/Codebase/Scanner.php{d_{d; )src/Psalm/Internal/Codebase/Functions.phplE_lEsƴ(src/Psalm/Internal/Codebase/Analyzer.php_J*src/Psalm/Internal/Codebase/Reflection.phpD_Dzߴ0src/Psalm/Internal/Codebase/VariableUseGraph.php _ ^ *src/Psalm/Internal/Codebase/Properties.php%%_%%GFȫ.src/Psalm/Internal/Codebase/TaintFlowGraph.php%_%+src/Psalm/Internal/Codebase/PropertyMap.php_,"6src/Psalm/Internal/Scanner/FunctionDocblockComment.php_wa*src/Psalm/Internal/Scanner/FileScanner.php< _< w^)-src/Psalm/Internal/Scanner/ParsedDocblock.php _ 6t1src/Psalm/Internal/Scanner/VarDocblockComment.php_2src/Psalm/Internal/Scanner/PhpStormMetaScanner.phpE9_E9[-src/Psalm/Internal/Scanner/DocblockParser.php_GFsrc/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedDivisionOp.php_" Isrc/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedSubtractionOp.php_Dsrc/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.phpO_O0]h<src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php_]+:src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php_]{?src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php_Dsrc/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedConcatOp.php_>src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php>_>r}sLsrc/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedMultiplicationOp.php_MKCsrc/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.phpL_LkBsrc/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.phpH_Ha!*Esrc/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBitwiseOr.php_=src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php_̩Fsrc/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedAdditionOp.php_src/Psalm/Internal/Type/ParseTree/MethodWithReturnTypeTree.php_`4src/Psalm/Internal/Type/ParseTree/TemplateIsTree.php{_{@src/Psalm/Internal/Type/ParseTree/CallableWithReturnTypeTree.php_Zȴ<src/Psalm/Internal/Type/ParseTree/KeyedArrayPropertyTree.phpo_ot61src/Psalm/Internal/Type/ParseTree/GenericTree.php_ʨ+src/Psalm/Internal/Type/ParseTree/Value.php__5src/Psalm/Internal/Type/ParseTree/ConditionalTree.php_;0src/Psalm/Internal/Type/ParseTree/MethodTree.phpc_ckRC2src/Psalm/Internal/Type/ParseTree/NullableTree.php_.]7src/Psalm/Internal/Type/ParseTree/EncapsulationTree.php_:6src/Psalm/Internal/Type/ParseTree/IntersectionTree.php_6l5src/Psalm/Internal/Type/ParseTree/MethodParamTree.phpm_mbw/src/Psalm/Internal/Type/ParseTree/UnionTree.php_Դ4src/Psalm/Internal/Type/ParseTree/KeyedArrayTree.php_ݿ7src/Psalm/Internal/Type/ParseTree/IndexedAccessTree.phpj_j/BI4src/Psalm/Internal/Type/ParseTree/TemplateAsTree.php_J<2src/Psalm/Internal/Type/ParseTree/CallableTree.php_%SJB*src/Psalm/Internal/Type/ParseTree/Root.php|_|.+src/Psalm/Internal/Type/TypeCombination.php#_##%src/Psalm/Internal/Type/ParseTree.php_)src/Psalm/Internal/Type/TypeTokenizer.php+2_+2^Ĵ<src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php2_2Y̜%src/Psalm/Internal/Type/TypeAlias.php?_?45src/Psalm/Internal/Type/SimpleAssertionReconciler.php _ Ky6src/Psalm/Internal/Type/NegatedAssertionReconciler.php3_3%(src/Psalm/Internal/Type/TypeExpander.phpM_M7M0src/Psalm/Internal/Type/UnionTemplateHandler.php_4&src/Psalm/Internal/Type/TypeParser.php_Ӕ<src/Psalm/Internal/Type/Comparator/ClassStringComparator.php _ ܿ<src/Psalm/Internal/Type/Comparator/GenericTypeComparator.phpo"_o"9&=src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php5_55&:src/Psalm/Internal/Type/Comparator/UnionTypeComparator.php5_5U;src/Psalm/Internal/Type/Comparator/TypeComparisonResult.phpk_k(X;src/Psalm/Internal/Type/Comparator/KeyedArrayComparator.php7_7uɴ7src/Psalm/Internal/Type/Comparator/ObjectComparator.php/)_/)*T:src/Psalm/Internal/Type/Comparator/ArrayTypeComparator.php'_'/j;src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.phpX_XŴ;src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.phpjF_jFδ'src/Psalm/Internal/IncludeCollector.php#_#FD7-src/Psalm/Internal/Analyzer/ClassAnalyzer.php^_^0src/Psalm/Internal/Analyzer/FunctionAnalyzer.php_0A)src/Psalm/Internal/Analyzer/IssueData.php! _! 1src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php_T+0src/Psalm/Internal/Analyzer/DataFlowNodeData.phpP_PFw.src/Psalm/Internal/Analyzer/MethodAnalyzer.phpC _C a>ϴ1src/Psalm/Internal/Analyzer/InterfaceAnalyzer.php _ Ԇ嶴/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php\+_\+v~(src/Psalm/Internal/Analyzer/CanAlias.phpM_M?d/src/Psalm/Internal/Analyzer/AlgebraAnalyzer.php_h0src/Psalm/Internal/Analyzer/MethodComparator.php_D,src/Psalm/Internal/Analyzer/FileAnalyzer.phprO_rON@ݴ/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php?_?Ky}Gsrc/Psalm/Internal/Analyzer/Statements/Expression/YieldFromAnalyzer.php_0ԴHsrc/Psalm/Internal/Analyzer/Statements/Expression/BitwiseNotAnalyzer.php:_:}9Bsrc/Psalm/Internal/Analyzer/Statements/Expression/ExitAnalyzer.php7 _7 Gsrc/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php$F_$F+<Lsrc/Psalm/Internal/Analyzer/Statements/Expression/UnaryPlusMinusAnalyzer.php _ ]Csrc/Psalm/Internal/Analyzer/Statements/Expression/IssetAnalyzer.php_GeCsrc/Psalm/Internal/Analyzer/Statements/Expression/YieldAnalyzer.php_ɪCsrc/Psalm/Internal/Analyzer/Statements/Expression/PrintAnalyzer.php _ KmCsrc/Psalm/Internal/Analyzer/Statements/Expression/CloneAnalyzer.php_Esrc/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php& _& Ysrc/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/NonDivArithmeticOpAnalyzer.php.p_.p)EOsrc/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/CoalesceAnalyzer.php_hJsrc/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.phpT_TMŧMsrc/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ConcatAnalyzer.php!E_!EK\Vsrc/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/NonComparisonOpAnalyzer.php_iIsrc/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php._.ҒXǴHsrc/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php_ HBsrc/Psalm/Internal/Analyzer/Statements/Expression/EvalAnalyzer.php_ݴNsrc/Psalm/Internal/Analyzer/Statements/Expression/IncDecExpressionAnalyzer.php_H `Esrc/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php5_5NPsrc/Psalm/Internal/Analyzer/Statements/Expression/EncapsulatedStringAnalyzer.php_s*Bsrc/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.phpY_YFsrc/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.phpG_GiMsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php6_6JYsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.phpz_z }[Lsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.phpn_ng1Fsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.phprh_rhbOsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php_a쟴Vsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/ClassTemplateParamCollector.php&_&YZsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MissingMethodCallHandler.php# _# r;&8_src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodCallProhibitionAnalyzer.php_5hM`src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalysisResult.phpb_bN FZsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodVisibilityAnalyzer.php_J#.]src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodCallReturnTypeFetcher.phpO-_O-@r`Zsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php_O<}Ssrc/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicCallContext.php_.ôZsrc/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodCallPurityAnalyzer.phpk_k.Msrc/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php_9Ksrc/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php_i2Osrc/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentMapPopulator.php_؟jWsrc/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.phpbu_buNsrc/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.phpy%_y%f;Qsrc/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php D_ D2hYsrc/Psalm/Internal/Analyzer/Statements/Expression/Fetch/InstancePropertyFetchAnalyzer.php:_:))`Wsrc/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php'5_'5>9Nsrc/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php_oSsrc/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ClassConstFetchAnalyzer.php9_9AuEsrc/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php_Jsrc/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php!_!x뚴Hsrc/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php _ SHsrc/Psalm/Internal/Analyzer/Statements/Expression/MagicConstAnalyzer.phpQ_Q !\Hsrc/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php?_?Csrc/Psalm/Internal/Analyzer/Statements/Expression/ArrayAnalyzer.phpS0_S0匴Fsrc/Psalm/Internal/Analyzer/Statements/Expression/NullsafeAnalyzer.php _ asrc/Psalm/Internal/Analyzer/Statements/Expression/Assignment/StaticPropertyAssignmentAnalyzer.php)_)#Xsrc/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.phpo_o%Kcsrc/Psalm/Internal/Analyzer/Statements/Expression/Assignment/InstancePropertyAssignmentAnalyzer.php_0FsBsrc/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php0_0`sCsrc/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php_0?gKCsrc/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php_LI9src/Psalm/Internal/Analyzer/Statements/StaticAnalyzer.php_>*=src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php<_<Q8src/Psalm/Internal/Analyzer/Statements/BreakAnalyzer.php_r<7src/Psalm/Internal/Analyzer/Statements/EchoAnalyzer.php_d맑;src/Psalm/Internal/Analyzer/Statements/ContinueAnalyzer.php_xZ#Bsrc/Psalm/Internal/Analyzer/Statements/UnusedAssignmentRemover.php.5_.5!Rh8src/Psalm/Internal/Analyzer/Statements/UnsetAnalyzer.php_WRh8src/Psalm/Internal/Analyzer/Statements/ThrowAnalyzer.php _ 0KV9src/Psalm/Internal/Analyzer/Statements/GlobalAnalyzer.php _ Пd9src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.phpV_V󃷒<src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php$_$Zܴ?src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php_L<src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.phpvH_vHi*>src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.phpI_Iq@src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php_;src/Psalm/Internal/Analyzer/Statements/Block/IfAnalyzer.php_N>Csrc/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.phpcb_cbѴ;src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php_:=src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php|h_|h)Փ1src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php H_ Hp`д/src/Psalm/Internal/Analyzer/CommentAnalyzer.php_-src/Psalm/Internal/Analyzer/ScopeAnalyzer.php4_4 q!̴,src/Psalm/Internal/Analyzer/TypeAnalyzer.php _ N-src/Psalm/Internal/Analyzer/TraitAnalyzer.php%_%M!.src/Psalm/Internal/Analyzer/SourceAnalyzer.phpR_R`4src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php_M 2src/Psalm/Internal/Analyzer/StatementsAnalyzer.phpۅ_ۅrQ`O@src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeCollector.phpS#_S#U?src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeAnalyzer.phpn_nF5z<src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.phpR _R o>src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php{)_{)i3Asrc/Psalm/Internal/ExecutionEnvironment/SystemCommandExecutor.php_Y/src/Psalm/Internal/PluginManager/PluginList.phpT _T NE/src/Psalm/Internal/PluginManager/ConfigFile.php_Ѵ1src/Psalm/Internal/PluginManager/ComposerLock.php _ F:src/Psalm/Internal/PluginManager/Command/EnableCommand.php _ -\;src/Psalm/Internal/PluginManager/Command/DisableCommand.php _ f(8src/Psalm/Internal/PluginManager/Command/ShowCommand.php' _' X6src/Psalm/Internal/PluginManager/PluginListFactory.php _ r6src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php*_*>Tݴ9src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php_Q[19src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php _ xȒa9src/Psalm/Internal/PhpVisitor/CheckTrivialExprVisitor.php _ }qԴ5src/Psalm/Internal/PhpVisitor/ShortClosureVisitor.php_ۋ4src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php_Ij74src/Psalm/Internal/PhpVisitor/NodeCounterVisitor.php_K4src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php!_!jʹ2src/Psalm/Internal/PhpVisitor/ReflectorVisitor.phpY_Y'4src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php_i-src/Psalm/Internal/PhpVisitor/TraitFinder.php _ ~6src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php _ eM6src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php._.0src/Psalm/Internal/PhpVisitor/CloningVisitor.php _ ThZsrc/Psalm/Internal/Clause.php_6F3src/Psalm/Internal/PhpTraverser/CustomTraverser.phpA_AW+T'src/Psalm/Internal/MethodIdentifier.phpJ_JDA7;src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php_25src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php\_\˻;.src/Psalm/Internal/TypeVisitor/TypeScanner.php- _- l8src/Psalm/Internal/TypeVisitor/TemplateTypeCollector.php_K.src/Psalm/Internal/TypeVisitor/TypeChecker.phph,_h,3)_ src/Psalm/Internal/Json/Json.phpN_N,l5src/Psalm/Internal/Stubs/Generator/StubsGenerator.php)_)W=src/Psalm/Internal/Stubs/Generator/ClassLikeStubGenerator.phpr$_r$74 src/Psalm/Internal/Fork/Pool.php:_:S#3src/Psalm/Internal/Fork/ForkProcessErrorMessage.php_O/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php/_/ڠX'src/Psalm/Internal/Fork/ForkMessage.phpA_A*src/Psalm/Internal/Fork/PsalmRestarter.php_hI2src/Psalm/Internal/Fork/ForkProcessDoneMessage.php2_2O!yCsrc/Psalm/Internal/FileManipulation/PropertyDocblockManipulator.php0_0w$ECsrc/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php<_<c9δ>src/Psalm/Internal/FileManipulation/FileManipulationBuffer.php\_\M@l@src/Psalm/Internal/FileManipulation/ClassDocblockManipulator.php_XH5src/Psalm/Internal/FileManipulation/CodeMigration.php_H$src/Psalm/Internal/Scope/IfScope.php_Y,/src/Psalm/Internal/Scope/IfConditionalScope.php"_"_X/&src/Psalm/Internal/Scope/CaseScope.php_@N)src/Psalm/Internal/Scope/FinallyScope.phpr_r9K*(src/Psalm/Internal/Scope/SwitchScope.php_&src/Psalm/Internal/Scope/LoopScope.php_`@4src/Psalm/Internal/LanguageServer/ProtocolWriter.php_u 1src/Psalm/Internal/LanguageServer/IdGenerator.phpb_bȴ9src/Psalm/Internal/LanguageServer/Client/TextDocument.php _ :2src/Psalm/Internal/LanguageServer/EmitterTrait.php_}X3src/Psalm/Internal/LanguageServer/ClientHandler.php _ IF4src/Psalm/Internal/LanguageServer/LanguageServer.php_K__K:src/Psalm/Internal/LanguageServer/ProtocolStreamReader.php _ G<4src/Psalm/Internal/LanguageServer/ProtocolReader.php<_<o1f:src/Psalm/Internal/LanguageServer/ProtocolStreamWriter.php_{9src/Psalm/Internal/LanguageServer/Server/TextDocument.phpd2_d26src/Psalm/Internal/LanguageServer/EmitterInterface.php_ Yj-src/Psalm/Internal/LanguageServer/Message.php_ݴ4src/Psalm/Internal/LanguageServer/LanguageClient.php._.-i src/Psalm/FileManipulation.php_"src/Psalm/FileSource.php_ ^&src/Psalm/Storage/ClassLikeStorage.php_@ٴ%src/Psalm/Storage/FunctionStorage.php_@Q!src/Psalm/Storage/FileStorage.php0_0}fXsrc/Psalm/Storage/Assertion.php _ ô)src/Psalm/Storage/CustomMetadataTrait.php_}ѕ%src/Psalm/Storage/PropertyStorage.php=_=j+src/Psalm/Storage/FunctionLikeParameter.php _ c)src/Psalm/Storage/FunctionLikeStorage.php_д*src/Psalm/Storage/ClassConstantStorage.php_ho1#src/Psalm/Storage/MethodStorage.phpm_m2&´src/Psalm/Config/FileFilter.php18_18ͧ!)src/Psalm/Config/ErrorLevelFileFilter.php_Msrc/Psalm/Config/Creator.phpV_Vô,src/Psalm/Config/TaintAnalysisFileFilter.phpc_c0!src/Psalm/Config/IssueHandler.php_ ;&src/Psalm/Config/ProjectFileFilter.php _ >2src/Psalm/Report.php: _:  src/Psalm/ErrorBaseline.php#_#'src/Psalm/Exception/ConfigException.phpP_Pma.src/Psalm/Exception/TypeParseTreeException.phpW_Wrj6src/Psalm/Exception/UnsupportedIssueToFixException.php___,src/Psalm/Exception/FileIncludeException.phpU_U F/src/Psalm/Exception/UnanalyzedFileException.phpX_XCA.src/Psalm/Exception/DocblockParseException.phpW_WB G2src/Psalm/Exception/IncorrectDocblockException.phpx_x˴/src/Psalm/Exception/ConfigCreationException.phpX_X-˴9src/Psalm/Exception/InvalidClasslikeOverrideException.phpb_b}h2src/Psalm/Exception/CircularReferenceException.php[_['ڴ%src/Psalm/Exception/CodeException.phpN_N=ٴ5src/Psalm/Exception/UnpopulatedClasslikeException.phpX_X3src/Psalm/Exception/UnpreparedAnalysisException.php\_\w6src/Psalm/Exception/ComplicatedExpressionException.php___N.src/Psalm/Exception/ScopeAnalysisException.phpW_Wڴ)src/Psalm/Exception/RefactorException.phpR_R0`6src/Psalm/Exception/InvalidMethodOverrideException.php___VHxsrc/Psalm/StatementsSource.php_8 ʴsrc/Psalm/CodeLocation.php*_*&src/Psalm/PluginRegistrationSocket.php _ -src/Psalm/SourceControl/SourceControlInfo.php|_|T*src/Psalm/SourceControl/Git/CommitInfo.php _ 'src/Psalm/SourceControl/Git/GitInfo.php6_6ϳs *src/Psalm/SourceControl/Git/RemoteInfo.php_ dsrc/functions.php._./'dictionaries/CallMap.php_F!dictionaries/CallMap_72_delta.php1_1L"\\!dictionaries/CallMap_73_delta.php _ c״<dictionaries/scripts/update_signaturemap_from_other_tool.php|_|!dictionaries/CallMap_74_delta.php_tou!dictionaries/CallMap_80_delta.phpz_z[z!dictionaries/CallMap_71_delta.phpl _l 3ԗ%dictionaries/InternalTaintSinkMap.php_gݴdictionaries/PropertyMap.php$9_$9e*.box/vendor/composer/autoload_classmap.php_fڴ(.box/vendor/composer/autoload_static.php _ $.box/vendor/composer/ClassLoader.php4_4z&.box/vendor/composer/autoload_psr4.php4_4c.box/vendor/composer/LICENSE._. &.box/vendor/composer/autoload_real.php_ˋ}<1.box/vendor/composer/semver/src/VersionParser.php:_:1D*.box/vendor/composer/semver/src/Semver.php_EJF9.box/vendor/composer/semver/src/Constraint/Constraint.php_-n>.box/vendor/composer/semver/src/Constraint/MultiConstraint.php_ɭ B.box/vendor/composer/semver/src/Constraint/ConstraintInterface.php _ RO>.box/vendor/composer/semver/src/Constraint/EmptyConstraint.php_-A.box/vendor/composer/semver/src/Constraint/AbstractConstraint.php_]..box/vendor/composer/semver/src/Comparator.php_ Ŵ,.box/vendor/composer/autoload_namespaces.php_t!״.box/vendor/autoload.php_94.box/src/Checker.php_d;".box/src/RequirementCollection.php_?,.box/src/IO.php;_;Y!.box/src/IsExtensionFulfilled.php_.;.box/src/Requirement.php|_|IFM.box/src/IsFulfilled.phpu_ui g.box/src/Terminal.phpy _y ".box/src/IsPhpVersionFulfilled.php?_?$.box/src/Printer.php _ * .box/bin/check-requirements.php_"uӍ.box/.requirements.php _ Fassets/psalm-phar/dot-gitignore_P sTassets/psalm-phar/composer.json_uLassets/psalm-phar/README.mdn_n+E config.xsd5_5b{  * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Webmozart\Glob; use InvalidArgumentException; use _HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator\GlobIterator; use _HumbugBoxd02f763d3c56\Webmozart\PathUtil\Path; /** * Searches and matches file paths using Ant-like globs. * * This class implements an Ant-like version of PHP's `glob()` function. The * wildcard "*" matches any number of characters except directory separators. * The double wildcard "**" matches any number of characters, including * directory separators. * * Use {@link glob()} to glob the filesystem for paths: * * ```php * foreach (Glob::glob('/project/**.twig') as $path) { * // do something... * } * ``` * * Use {@link match()} to match a file path against a glob: * * ```php * if (Glob::match('/project/views/index.html.twig', '/project/**.twig')) { * // path matches * } * ``` * * You can also filter an array of paths for all paths that match your glob with * {@link filter()}: * * ```php * $filteredPaths = Glob::filter($paths, '/project/**.twig'); * ``` * * Internally, the methods described above convert the glob into a regular * expression that is then matched against the matched paths. If you need to * match many paths against the same glob, you should convert the glob manually * and use {@link preg_match()} to test the paths: * * ```php * $staticPrefix = Glob::getStaticPrefix('/project/**.twig'); * $regEx = Glob::toRegEx('/project/**.twig'); * * if (0 !== strpos($path, $staticPrefix)) { * // no match * } * * if (!preg_match($regEx, $path)) { * // no match * } * ``` * * The method {@link getStaticPrefix()} returns the part of the glob up to the * first wildcard "*". You should always test whether a path has this prefix * before calling the much more expensive {@link preg_match()}. * * @since 1.0 * * @author Bernhard Schussek */ final class Glob { /** * Flag: Filter the values in {@link Glob::filter()}. */ const FILTER_VALUE = 1; /** * Flag: Filter the keys in {@link Glob::filter()}. */ const FILTER_KEY = 2; /** * Globs the file system paths matching the glob. * * The glob may contain the wildcard "*". This wildcard matches any number * of characters, *including* directory separators. * * ```php * foreach (Glob::glob('/project/**.twig') as $path) { * // do something... * } * ``` * * @param string $glob The canonical glob. The glob should contain forward * slashes as directory separators only. It must not * contain any "." or ".." segments. Use the * "webmozart/path-util" utility to canonicalize globs * prior to calling this method. * @param int $flags A bitwise combination of the flag constants in this * class. * * @return string[] The matching paths. The keys of the array are * incrementing integers. */ public static function glob($glob, $flags = 0) { $results = \iterator_to_array(new \_HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator\GlobIterator($glob, $flags)); \sort($results); return $results; } /** * Matches a path against a glob. * * ```php * if (Glob::match('/project/views/index.html.twig', '/project/**.twig')) { * // path matches * } * ``` * * @param string $path The path to match. * @param string $glob The canonical glob. The glob should contain forward * slashes as directory separators only. It must not * contain any "." or ".." segments. Use the * "webmozart/path-util" utility to canonicalize globs * prior to calling this method. * @param int $flags A bitwise combination of the flag constants in * this class. * * @return bool Returns `true` if the path is matched by the glob. */ public static function match($path, $glob, $flags = 0) { if (!self::isDynamic($glob)) { return $glob === $path; } if (0 !== \strpos($path, self::getStaticPrefix($glob, $flags))) { return \false; } if (!\preg_match(self::toRegEx($glob, $flags), $path)) { return \false; } return \true; } /** * Filters an array for paths matching a glob. * * The filtered array is returned. This array preserves the keys of the * passed array. * * ```php * $filteredPaths = Glob::filter($paths, '/project/**.twig'); * ``` * * @param string[] $paths A list of paths. * @param string $glob The canonical glob. The glob should contain * forward slashes as directory separators only. It * must not contain any "." or ".." segments. Use the * "webmozart/path-util" utility to canonicalize * globs prior to calling this method. * @param int $flags A bitwise combination of the flag constants in * this class. * * @return string[] The paths matching the glob indexed by their original * keys. */ public static function filter(array $paths, $glob, $flags = self::FILTER_VALUE) { if ($flags & self::FILTER_VALUE && $flags & self::FILTER_KEY) { throw new \InvalidArgumentException('The flags Glob::FILTER_VALUE and Glob::FILTER_KEY cannot be passed at the same time.'); } if (!self::isDynamic($glob)) { if ($flags & self::FILTER_KEY) { return isset($paths[$glob]) ? array($glob => $paths[$glob]) : array(); } $key = \array_search($glob, $paths); return \false !== $key ? array($key => $glob) : array(); } $staticPrefix = self::getStaticPrefix($glob, $flags); $regExp = self::toRegEx($glob, $flags); $filter = function ($path) use($staticPrefix, $regExp) { return 0 === \strpos($path, $staticPrefix) && \preg_match($regExp, $path); }; if (\PHP_VERSION_ID >= 50600) { $filterFlags = $flags & self::FILTER_KEY ? \ARRAY_FILTER_USE_KEY : 0; return \array_filter($paths, $filter, $filterFlags); } // No support yet for the third argument of array_filter() if ($flags & self::FILTER_KEY) { $result = array(); foreach ($paths as $path => $value) { if ($filter($path)) { $result[$path] = $value; } } return $result; } return \array_filter($paths, $filter); } /** * Returns the base path of a glob. * * This method returns the most specific directory that contains all files * matched by the glob. If this directory does not exist on the file system, * it's not necessary to execute the glob algorithm. * * More specifically, the "base path" is the longest path trailed by a "/" * on the left of the first wildcard "*". If the glob does not contain * wildcards, the directory name of the glob is returned. * * ```php * Glob::getBasePath('/css/*.css'); * // => /css * * Glob::getBasePath('/css/style.css'); * // => /css * * Glob::getBasePath('/css/st*.css'); * // => /css * * Glob::getBasePath('/*.css'); * // => / * ``` * * @param string $glob The canonical glob. The glob should contain forward * slashes as directory separators only. It must not * contain any "." or ".." segments. Use the * "webmozart/path-util" utility to canonicalize globs * prior to calling this method. * @param int $flags A bitwise combination of the flag constants in this * class. * * @return string The base path of the glob. */ public static function getBasePath($glob, $flags = 0) { // Search the static prefix for the last "/" $staticPrefix = self::getStaticPrefix($glob, $flags); if (\false !== ($pos = \strrpos($staticPrefix, '/'))) { // Special case: Return "/" if the only slash is at the beginning // of the glob if (0 === $pos) { return '/'; } // Special case: Include trailing slash of "scheme:///foo" if ($pos - 3 === \strpos($glob, '://')) { return \substr($staticPrefix, 0, $pos + 1); } return \substr($staticPrefix, 0, $pos); } // Glob contains no slashes on the left of the wildcard // Return an empty string return ''; } /** * Converts a glob to a regular expression. * * Use this method if you need to match many paths against a glob: * * ```php * $staticPrefix = Glob::getStaticPrefix('/project/**.twig'); * $regEx = Glob::toRegEx('/project/**.twig'); * * if (0 !== strpos($path, $staticPrefix)) { * // no match * } * * if (!preg_match($regEx, $path)) { * // no match * } * ``` * * You should always test whether a path contains the static prefix of the * glob returned by {@link getStaticPrefix()} to reduce the number of calls * to the expensive {@link preg_match()}. * * @param string $glob The canonical glob. The glob should contain forward * slashes as directory separators only. It must not * contain any "." or ".." segments. Use the * "webmozart/path-util" utility to canonicalize globs * prior to calling this method. * @param int $flags A bitwise combination of the flag constants in this * class. * * @return string The regular expression for matching the glob. */ public static function toRegEx($glob, $flags = 0, $delimiter = '~') { if (!\_HumbugBoxd02f763d3c56\Webmozart\PathUtil\Path::isAbsolute($glob) && \false === \strpos($glob, '://')) { throw new \InvalidArgumentException(\sprintf('The glob "%s" is not absolute and not a URI.', $glob)); } $inSquare = \false; $curlyLevels = 0; $regex = ''; $length = \strlen($glob); for ($i = 0; $i < $length; ++$i) { $c = $glob[$i]; switch ($c) { case '.': case '(': case ')': case '|': case '+': case '^': case '$': case $delimiter: $regex .= "\\{$c}"; break; case '/': if (isset($glob[$i + 3]) && '**/' === $glob[$i + 1] . $glob[$i + 2] . $glob[$i + 3]) { $regex .= '/([^/]+/)*'; $i += 3; } else { $regex .= '/'; } break; case '*': $regex .= '[^/]*'; break; case '?': $regex .= '.'; break; case '{': $regex .= '('; ++$curlyLevels; break; case '}': if ($curlyLevels > 0) { $regex .= ')'; --$curlyLevels; } else { $regex .= '}'; } break; case ',': $regex .= $curlyLevels > 0 ? '|' : ','; break; case '[': $regex .= '['; $inSquare = \true; if (isset($glob[$i + 1]) && '^' === $glob[$i + 1]) { $regex .= '^'; ++$i; } break; case ']': $regex .= $inSquare ? ']' : '\\]'; $inSquare = \false; break; case '-': $regex .= $inSquare ? '-' : '\\-'; break; case '\\': if (isset($glob[$i + 1])) { switch ($glob[$i + 1]) { case '*': case '?': case '{': case '}': case '[': case ']': case '-': case '^': case '\\': $regex .= '\\' . $glob[$i + 1]; ++$i; break; default: $regex .= '\\\\'; } } else { $regex .= '\\\\'; } break; default: $regex .= $c; break; } } if ($inSquare) { throw new \InvalidArgumentException(\sprintf('Invalid glob: missing ] in %s', $glob)); } if ($curlyLevels > 0) { throw new \InvalidArgumentException(\sprintf('Invalid glob: missing } in %s', $glob)); } return $delimiter . '^' . $regex . '$' . $delimiter; } /** * Returns the static prefix of a glob. * * The "static prefix" is the part of the glob up to the first wildcard "*". * If the glob does not contain wildcards, the full glob is returned. * * @param string $glob The canonical glob. The glob should contain forward * slashes as directory separators only. It must not * contain any "." or ".." segments. Use the * "webmozart/path-util" utility to canonicalize globs * prior to calling this method. * @param int $flags A bitwise combination of the flag constants in this * class. * * @return string The static prefix of the glob. */ public static function getStaticPrefix($glob, $flags = 0) { if (!\_HumbugBoxd02f763d3c56\Webmozart\PathUtil\Path::isAbsolute($glob) && \false === \strpos($glob, '://')) { throw new \InvalidArgumentException(\sprintf('The glob "%s" is not absolute and not a URI.', $glob)); } $prefix = ''; $length = \strlen($glob); for ($i = 0; $i < $length; ++$i) { $c = $glob[$i]; switch ($c) { case '/': $prefix .= '/'; if (isset($glob[$i + 3]) && '**/' === $glob[$i + 1] . $glob[$i + 2] . $glob[$i + 3]) { break 2; } break; case '*': case '?': case '{': case '[': break 2; case '\\': if (isset($glob[$i + 1])) { switch ($glob[$i + 1]) { case '*': case '?': case '{': case '[': case '\\': $prefix .= $glob[$i + 1]; ++$i; break; default: $prefix .= '\\'; } } else { $prefix .= '\\'; } break; default: $prefix .= $c; break; } } return $prefix; } /** * Returns whether the glob contains a dynamic part. * * The glob contains a dynamic part if it contains an unescaped "*" or * "{" character. * * @param string $glob The glob to test. * * @return bool Returns `true` if the glob contains a dynamic part and * `false` otherwise. */ public static function isDynamic($glob) { return \false !== \strpos($glob, '*') || \false !== \strpos($glob, '{') || \false !== \strpos($glob, '?') || \false !== \strpos($glob, '['); } private function __construct() { } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator; use Iterator; use _HumbugBoxd02f763d3c56\Webmozart\Glob\Glob; /** * Filters an iterator by a glob. * * @since 1.0 * * @author Bernhard Schussek * * @see Glob */ class GlobFilterIterator extends \_HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator\RegexFilterIterator { /** * Creates a new iterator. * * @param string $glob The canonical glob. * @param Iterator $innerIterator The filtered iterator. * @param int $mode A bitwise combination of the mode constants. * @param int $flags A bitwise combination of the flag constants * in {@link Glob}. */ public function __construct($glob, \Iterator $innerIterator, $mode = self::FILTER_VALUE, $flags = 0) { parent::__construct(\_HumbugBoxd02f763d3c56\Webmozart\Glob\Glob::toRegEx($glob, $flags), \_HumbugBoxd02f763d3c56\Webmozart\Glob\Glob::getStaticPrefix($glob, $flags), $innerIterator, $mode); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator; use FilterIterator; use Iterator; /** * Filters an iterator by a regular expression. * * @since 1.0 * * @author Bernhard Schussek * * @see Glob */ class RegexFilterIterator extends \FilterIterator { /** * Mode: Filters the values of the inner iterator. */ const FILTER_VALUE = 1; /** * Mode: Filters the keys of the inner iterator. */ const FILTER_KEY = 2; /** * Mode: Return incrementing numbers as keys. */ const CURSOR_AS_KEY = 16; /** * Mode: Return the original keys as keys. */ const KEY_AS_KEY = 32; /** * @var string */ private $regExp; /** * @var string */ private $staticPrefix; /** * @var int */ private $cursor = 0; /** * @var int */ private $mode; /** * Creates a new iterator. * * @param string $regExp The regular expression to filter by. * @param string $staticPrefix The static prefix of the regular * expression. * @param Iterator $innerIterator The filtered iterator. * @param int $mode A bitwise combination of the mode constants. */ public function __construct($regExp, $staticPrefix, \Iterator $innerIterator, $mode = null) { parent::__construct($innerIterator); if (!($mode & (self::FILTER_KEY | self::FILTER_VALUE))) { $mode |= self::FILTER_VALUE; } if (!($mode & (self::CURSOR_AS_KEY | self::KEY_AS_KEY))) { $mode |= self::CURSOR_AS_KEY; } $this->regExp = $regExp; $this->staticPrefix = $staticPrefix; $this->mode = $mode; } /** * Rewind the iterator to the first position. */ public function rewind() { parent::rewind(); $this->cursor = 0; } /** * Returns the current position. * * @return int The current position. */ public function key() { if (!$this->valid()) { return null; } if ($this->mode & self::KEY_AS_KEY) { return parent::key(); } return $this->cursor; } /** * Advances to the next match. * * @see Iterator::next() */ public function next() { if ($this->valid()) { parent::next(); ++$this->cursor; } } /** * Accepts paths matching the glob. * * @return bool Whether the path is accepted. */ public function accept() { $path = $this->mode & self::FILTER_VALUE ? $this->current() : parent::key(); if (0 !== \strpos($path, $this->staticPrefix)) { return \false; } $result = (bool) \preg_match($this->regExp, $path); return $result; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator; use ArrayIterator; use EmptyIterator; use IteratorIterator; use RecursiveIteratorIterator; use _HumbugBoxd02f763d3c56\Webmozart\Glob\Glob; /** * Returns filesystem paths matching a glob. * * @since 1.0 * * @author Bernhard Schussek * * @see Glob */ class GlobIterator extends \IteratorIterator { /** * Creates a new iterator. * * @param string $glob The glob pattern. * @param int $flags A bitwise combination of the flag constants in * {@link Glob}. */ public function __construct($glob, $flags = 0) { $basePath = \_HumbugBoxd02f763d3c56\Webmozart\Glob\Glob::getBasePath($glob, $flags); if (!\_HumbugBoxd02f763d3c56\Webmozart\Glob\Glob::isDynamic($glob) && \file_exists($glob)) { // If the glob is a file path, return that path $innerIterator = new \ArrayIterator(array($glob)); } elseif (\is_dir($basePath)) { // Use the system's much more efficient glob() function where we can if (\false === \strpos($glob, '/**/') && \false === \strpos($glob, '://') && ('\\' !== \DIRECTORY_SEPARATOR || \false === \strpos($glob, '[^'))) { $results = \glob($glob, \GLOB_BRACE); // $results may be empty or false if $glob is invalid if (empty($results)) { // Parse glob and provoke errors if invalid \_HumbugBoxd02f763d3c56\Webmozart\Glob\Glob::toRegEx($glob); // Otherwise return empty result set $innerIterator = new \EmptyIterator(); } else { $innerIterator = new \ArrayIterator($results); } } else { // Otherwise scan the glob's base directory for matches $innerIterator = new \_HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator\GlobFilterIterator($glob, new \RecursiveIteratorIterator(new \_HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator\RecursiveDirectoryIterator($basePath, \_HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator\RecursiveDirectoryIterator::CURRENT_AS_PATHNAME | \_HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator\RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST), \_HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator\GlobFilterIterator::FILTER_VALUE, $flags); } } else { // If the glob's base directory does not exist, return nothing $innerIterator = new \EmptyIterator(); } parent::__construct($innerIterator); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Webmozart\Glob\Iterator; /** * Recursive directory iterator that is working during recursive iteration. * * Recursive iteration is broken on PHP < 5.5.23 and on PHP 5.6 < 5.6.7. * * @since 1.0 * @since 3.0 Removed support for seek(), added \RecursiveDirectoryIterator * base class, adapted API to match \RecursiveDirectoryIterator * @since 3.1 Slashes are normalized to forward slashes on Windows * * @author Bernhard Schussek */ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator { /** * @var bool */ private $normalizeKey; /** * @var bool */ private $normalizeCurrent; /** * {@inheritdoc} */ public function __construct($path, $flags = 0) { parent::__construct($path, $flags); // Normalize slashes on Windows $this->normalizeKey = '\\' === \DIRECTORY_SEPARATOR && !($flags & self::KEY_AS_FILENAME); $this->normalizeCurrent = '\\' === \DIRECTORY_SEPARATOR && $flags & self::CURRENT_AS_PATHNAME; } /** * {@inheritdoc} */ public function getChildren() { return new static($this->getPathname(), $this->getFlags()); } /** * {@inheritdoc} */ public function key() { $key = parent::key(); if ($this->normalizeKey) { $key = \str_replace('\\', '/', $key); } return $key; } /** * {@inheritdoc} */ public function current() { $current = parent::current(); if ($this->normalizeCurrent) { $current = \str_replace('\\', '/', $current); } return $current; } } The MIT License (MIT) Copyright (c) 2014 Bernhard Schussek Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Webmozart\PathUtil; use InvalidArgumentException; use _HumbugBoxd02f763d3c56\Webmozart\Assert\Assert; /** * Contains utility methods for handling URL strings. * * The methods in this class are able to deal with URLs. * * @since 2.3 * * @author Bernhard Schussek * @author Claudio Zizza */ final class Url { /** * Turns a URL into a relative path. * * The result is a canonical path. This class is using functionality of Path class. * * @see Path * * @param string $url A URL to make relative. * @param string $baseUrl A base URL. * * @return string * * @throws InvalidArgumentException If the URL and base URL does * not match. */ public static function makeRelative($url, $baseUrl) { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($url, 'The URL must be a string. Got: %s'); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($baseUrl, 'The base URL must be a string. Got: %s'); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::contains($baseUrl, '://', '%s is not an absolute Url.'); list($baseHost, $basePath) = self::split($baseUrl); if (\false === \strpos($url, '://')) { if (0 === \strpos($url, '/')) { $host = $baseHost; } else { $host = ''; } $path = $url; } else { list($host, $path) = self::split($url); } if ('' !== $host && $host !== $baseHost) { throw new \InvalidArgumentException(\sprintf('The URL "%s" cannot be made relative to "%s" since their host names are different.', $host, $baseHost)); } return \_HumbugBoxd02f763d3c56\Webmozart\PathUtil\Path::makeRelative($path, $basePath); } /** * Splits a URL into its host and the path. * * ```php * list ($root, $path) = Path::split("http://example.com/webmozart") * // => array("http://example.com", "/webmozart") * * list ($root, $path) = Path::split("http://example.com") * // => array("http://example.com", "") * ``` * * @param string $url The URL to split. * * @return string[] An array with the host and the path of the URL. * * @throws InvalidArgumentException If $url is not a URL. */ private static function split($url) { $pos = \strpos($url, '://'); $scheme = \substr($url, 0, $pos + 3); $url = \substr($url, $pos + 3); if (\false !== ($pos = \strpos($url, '/'))) { $host = \substr($url, 0, $pos); $url = \substr($url, $pos); } else { // No path, only host $host = $url; $url = '/'; } // At this point, we have $scheme, $host and $path $root = $scheme . $host; return array($root, $url); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Webmozart\PathUtil; use InvalidArgumentException; use RuntimeException; use _HumbugBoxd02f763d3c56\Webmozart\Assert\Assert; /** * Contains utility methods for handling path strings. * * The methods in this class are able to deal with both UNIX and Windows paths * with both forward and backward slashes. All methods return normalized parts * containing only forward slashes and no excess "." and ".." segments. * * @since 1.0 * * @author Bernhard Schussek * @author Thomas Schulz */ final class Path { /** * The number of buffer entries that triggers a cleanup operation. */ const CLEANUP_THRESHOLD = 1250; /** * The buffer size after the cleanup operation. */ const CLEANUP_SIZE = 1000; /** * Buffers input/output of {@link canonicalize()}. * * @var array */ private static $buffer = array(); /** * The size of the buffer. * * @var int */ private static $bufferSize = 0; /** * Canonicalizes the given path. * * During normalization, all slashes are replaced by forward slashes ("/"). * Furthermore, all "." and ".." segments are removed as far as possible. * ".." segments at the beginning of relative paths are not removed. * * ```php * echo Path::canonicalize("\webmozart\puli\..\css\style.css"); * // => /webmozart/css/style.css * * echo Path::canonicalize("../css/./style.css"); * // => ../css/style.css * ``` * * This method is able to deal with both UNIX and Windows paths. * * @param string $path A path string. * * @return string The canonical path. * * @since 1.0 Added method. * @since 2.0 Method now fails if $path is not a string. * @since 2.1 Added support for `~`. */ public static function canonicalize($path) { if ('' === $path) { return ''; } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($path, 'The path must be a string. Got: %s'); // This method is called by many other methods in this class. Buffer // the canonicalized paths to make up for the severe performance // decrease. if (isset(self::$buffer[$path])) { return self::$buffer[$path]; } // Replace "~" with user's home directory. if ('~' === $path[0]) { $path = static::getHomeDirectory() . \substr($path, 1); } $path = \str_replace('\\', '/', $path); list($root, $pathWithoutRoot) = self::split($path); $parts = \explode('/', $pathWithoutRoot); $canonicalParts = array(); // Collapse "." and "..", if possible foreach ($parts as $part) { if ('.' === $part || '' === $part) { continue; } // Collapse ".." with the previous part, if one exists // Don't collapse ".." if the previous part is also ".." if ('..' === $part && \count($canonicalParts) > 0 && '..' !== $canonicalParts[\count($canonicalParts) - 1]) { \array_pop($canonicalParts); continue; } // Only add ".." prefixes for relative paths if ('..' !== $part || '' === $root) { $canonicalParts[] = $part; } } // Add the root directory again self::$buffer[$path] = $canonicalPath = $root . \implode('/', $canonicalParts); ++self::$bufferSize; // Clean up regularly to prevent memory leaks if (self::$bufferSize > self::CLEANUP_THRESHOLD) { self::$buffer = \array_slice(self::$buffer, -self::CLEANUP_SIZE, null, \true); self::$bufferSize = self::CLEANUP_SIZE; } return $canonicalPath; } /** * Normalizes the given path. * * During normalization, all slashes are replaced by forward slashes ("/"). * Contrary to {@link canonicalize()}, this method does not remove invalid * or dot path segments. Consequently, it is much more efficient and should * be used whenever the given path is known to be a valid, absolute system * path. * * This method is able to deal with both UNIX and Windows paths. * * @param string $path A path string. * * @return string The normalized path. * * @since 2.2 Added method. */ public static function normalize($path) { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($path, 'The path must be a string. Got: %s'); return \str_replace('\\', '/', $path); } /** * Returns the directory part of the path. * * This method is similar to PHP's dirname(), but handles various cases * where dirname() returns a weird result: * * - dirname() does not accept backslashes on UNIX * - dirname("C:/webmozart") returns "C:", not "C:/" * - dirname("C:/") returns ".", not "C:/" * - dirname("C:") returns ".", not "C:/" * - dirname("webmozart") returns ".", not "" * - dirname() does not canonicalize the result * * This method fixes these shortcomings and behaves like dirname() * otherwise. * * The result is a canonical path. * * @param string $path A path string. * * @return string The canonical directory part. Returns the root directory * if the root directory is passed. Returns an empty string * if a relative path is passed that contains no slashes. * Returns an empty string if an empty string is passed. * * @since 1.0 Added method. * @since 2.0 Method now fails if $path is not a string. */ public static function getDirectory($path) { if ('' === $path) { return ''; } $path = static::canonicalize($path); // Maintain scheme if (\false !== ($pos = \strpos($path, '://'))) { $scheme = \substr($path, 0, $pos + 3); $path = \substr($path, $pos + 3); } else { $scheme = ''; } if (\false !== ($pos = \strrpos($path, '/'))) { // Directory equals root directory "/" if (0 === $pos) { return $scheme . '/'; } // Directory equals Windows root "C:/" if (2 === $pos && \ctype_alpha($path[0]) && ':' === $path[1]) { return $scheme . \substr($path, 0, 3); } return $scheme . \substr($path, 0, $pos); } return ''; } /** * Returns canonical path of the user's home directory. * * Supported operating systems: * * - UNIX * - Windows8 and upper * * If your operation system or environment isn't supported, an exception is thrown. * * The result is a canonical path. * * @return string The canonical home directory * * @throws RuntimeException If your operation system or environment isn't supported * * @since 2.1 Added method. */ public static function getHomeDirectory() { // For UNIX support if (\getenv('HOME')) { return static::canonicalize(\getenv('HOME')); } // For >= Windows8 support if (\getenv('HOMEDRIVE') && \getenv('HOMEPATH')) { return static::canonicalize(\getenv('HOMEDRIVE') . \getenv('HOMEPATH')); } throw new \RuntimeException("Your environment or operation system isn't supported"); } /** * Returns the root directory of a path. * * The result is a canonical path. * * @param string $path A path string. * * @return string The canonical root directory. Returns an empty string if * the given path is relative or empty. * * @since 1.0 Added method. * @since 2.0 Method now fails if $path is not a string. */ public static function getRoot($path) { if ('' === $path) { return ''; } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($path, 'The path must be a string. Got: %s'); // Maintain scheme if (\false !== ($pos = \strpos($path, '://'))) { $scheme = \substr($path, 0, $pos + 3); $path = \substr($path, $pos + 3); } else { $scheme = ''; } // UNIX root "/" or "\" (Windows style) if ('/' === $path[0] || '\\' === $path[0]) { return $scheme . '/'; } $length = \strlen($path); // Windows root if ($length > 1 && \ctype_alpha($path[0]) && ':' === $path[1]) { // Special case: "C:" if (2 === $length) { return $scheme . $path . '/'; } // Normal case: "C:/ or "C:\" if ('/' === $path[2] || '\\' === $path[2]) { return $scheme . $path[0] . $path[1] . '/'; } } return ''; } /** * Returns the file name from a file path. * * @param string $path The path string. * * @return string The file name. * * @since 1.1 Added method. * @since 2.0 Method now fails if $path is not a string. */ public static function getFilename($path) { if ('' === $path) { return ''; } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($path, 'The path must be a string. Got: %s'); return \basename($path); } /** * Returns the file name without the extension from a file path. * * @param string $path The path string. * @param string|null $extension If specified, only that extension is cut * off (may contain leading dot). * * @return string The file name without extension. * * @since 1.1 Added method. * @since 2.0 Method now fails if $path or $extension have invalid types. */ public static function getFilenameWithoutExtension($path, $extension = null) { if ('' === $path) { return ''; } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($path, 'The path must be a string. Got: %s'); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::nullOrString($extension, 'The extension must be a string or null. Got: %s'); if (null !== $extension) { // remove extension and trailing dot return \rtrim(\basename($path, $extension), '.'); } return \pathinfo($path, \PATHINFO_FILENAME); } /** * Returns the extension from a file path. * * @param string $path The path string. * @param bool $forceLowerCase Forces the extension to be lower-case * (requires mbstring extension for correct * multi-byte character handling in extension). * * @return string The extension of the file path (without leading dot). * * @since 1.1 Added method. * @since 2.0 Method now fails if $path is not a string. */ public static function getExtension($path, $forceLowerCase = \false) { if ('' === $path) { return ''; } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($path, 'The path must be a string. Got: %s'); $extension = \pathinfo($path, \PATHINFO_EXTENSION); if ($forceLowerCase) { $extension = self::toLower($extension); } return $extension; } /** * Returns whether the path has an extension. * * @param string $path The path string. * @param string|array|null $extensions If null or not provided, checks if * an extension exists, otherwise * checks for the specified extension * or array of extensions (with or * without leading dot). * @param bool $ignoreCase Whether to ignore case-sensitivity * (requires mbstring extension for * correct multi-byte character * handling in the extension). * * @return bool Returns `true` if the path has an (or the specified) * extension and `false` otherwise. * * @since 1.1 Added method. * @since 2.0 Method now fails if $path or $extensions have invalid types. */ public static function hasExtension($path, $extensions = null, $ignoreCase = \false) { if ('' === $path) { return \false; } $extensions = \is_object($extensions) ? array($extensions) : (array) $extensions; \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::allString($extensions, 'The extensions must be strings. Got: %s'); $actualExtension = self::getExtension($path, $ignoreCase); // Only check if path has any extension if (empty($extensions)) { return '' !== $actualExtension; } foreach ($extensions as $key => $extension) { if ($ignoreCase) { $extension = self::toLower($extension); } // remove leading '.' in extensions array $extensions[$key] = \ltrim($extension, '.'); } return \in_array($actualExtension, $extensions); } /** * Changes the extension of a path string. * * @param string $path The path string with filename.ext to change. * @param string $extension New extension (with or without leading dot). * * @return string The path string with new file extension. * * @since 1.1 Added method. * @since 2.0 Method now fails if $path or $extension is not a string. */ public static function changeExtension($path, $extension) { if ('' === $path) { return ''; } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($extension, 'The extension must be a string. Got: %s'); $actualExtension = self::getExtension($path); $extension = \ltrim($extension, '.'); // No extension for paths if ('/' === \substr($path, -1)) { return $path; } // No actual extension in path if (empty($actualExtension)) { return $path . ('.' === \substr($path, -1) ? '' : '.') . $extension; } return \substr($path, 0, -\strlen($actualExtension)) . $extension; } /** * Returns whether a path is absolute. * * @param string $path A path string. * * @return bool Returns true if the path is absolute, false if it is * relative or empty. * * @since 1.0 Added method. * @since 2.0 Method now fails if $path is not a string. */ public static function isAbsolute($path) { if ('' === $path) { return \false; } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($path, 'The path must be a string. Got: %s'); // Strip scheme if (\false !== ($pos = \strpos($path, '://'))) { $path = \substr($path, $pos + 3); } // UNIX root "/" or "\" (Windows style) if ('/' === $path[0] || '\\' === $path[0]) { return \true; } // Windows root if (\strlen($path) > 1 && \ctype_alpha($path[0]) && ':' === $path[1]) { // Special case: "C:" if (2 === \strlen($path)) { return \true; } // Normal case: "C:/ or "C:\" if ('/' === $path[2] || '\\' === $path[2]) { return \true; } } return \false; } /** * Returns whether a path is relative. * * @param string $path A path string. * * @return bool Returns true if the path is relative or empty, false if * it is absolute. * * @since 1.0 Added method. * @since 2.0 Method now fails if $path is not a string. */ public static function isRelative($path) { return !static::isAbsolute($path); } /** * Turns a relative path into an absolute path. * * Usually, the relative path is appended to the given base path. Dot * segments ("." and "..") are removed/collapsed and all slashes turned * into forward slashes. * * ```php * echo Path::makeAbsolute("../style.css", "/webmozart/puli/css"); * // => /webmozart/puli/style.css * ``` * * If an absolute path is passed, that path is returned unless its root * directory is different than the one of the base path. In that case, an * exception is thrown. * * ```php * Path::makeAbsolute("/style.css", "/webmozart/puli/css"); * // => /style.css * * Path::makeAbsolute("C:/style.css", "C:/webmozart/puli/css"); * // => C:/style.css * * Path::makeAbsolute("C:/style.css", "/webmozart/puli/css"); * // InvalidArgumentException * ``` * * If the base path is not an absolute path, an exception is thrown. * * The result is a canonical path. * * @param string $path A path to make absolute. * @param string $basePath An absolute base path. * * @return string An absolute path in canonical form. * * @throws InvalidArgumentException If the base path is not absolute or if * the given path is an absolute path with * a different root than the base path. * * @since 1.0 Added method. * @since 2.0 Method now fails if $path or $basePath is not a string. * @since 2.2.2 Method does not fail anymore of $path and $basePath are * absolute, but on different partitions. */ public static function makeAbsolute($path, $basePath) { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($basePath, 'The base path must be a non-empty string. Got: %s'); if (!static::isAbsolute($basePath)) { throw new \InvalidArgumentException(\sprintf('The base path "%s" is not an absolute path.', $basePath)); } if (static::isAbsolute($path)) { return static::canonicalize($path); } if (\false !== ($pos = \strpos($basePath, '://'))) { $scheme = \substr($basePath, 0, $pos + 3); $basePath = \substr($basePath, $pos + 3); } else { $scheme = ''; } return $scheme . self::canonicalize(\rtrim($basePath, '/\\') . '/' . $path); } /** * Turns a path into a relative path. * * The relative path is created relative to the given base path: * * ```php * echo Path::makeRelative("/webmozart/style.css", "/webmozart/puli"); * // => ../style.css * ``` * * If a relative path is passed and the base path is absolute, the relative * path is returned unchanged: * * ```php * Path::makeRelative("style.css", "/webmozart/puli/css"); * // => style.css * ``` * * If both paths are relative, the relative path is created with the * assumption that both paths are relative to the same directory: * * ```php * Path::makeRelative("style.css", "webmozart/puli/css"); * // => ../../../style.css * ``` * * If both paths are absolute, their root directory must be the same, * otherwise an exception is thrown: * * ```php * Path::makeRelative("C:/webmozart/style.css", "/webmozart/puli"); * // InvalidArgumentException * ``` * * If the passed path is absolute, but the base path is not, an exception * is thrown as well: * * ```php * Path::makeRelative("/webmozart/style.css", "webmozart/puli"); * // InvalidArgumentException * ``` * * If the base path is not an absolute path, an exception is thrown. * * The result is a canonical path. * * @param string $path A path to make relative. * @param string $basePath A base path. * * @return string A relative path in canonical form. * * @throws InvalidArgumentException If the base path is not absolute or if * the given path has a different root * than the base path. * * @since 1.0 Added method. * @since 2.0 Method now fails if $path or $basePath is not a string. */ public static function makeRelative($path, $basePath) { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($basePath, 'The base path must be a string. Got: %s'); $path = static::canonicalize($path); $basePath = static::canonicalize($basePath); list($root, $relativePath) = self::split($path); list($baseRoot, $relativeBasePath) = self::split($basePath); // If the base path is given as absolute path and the path is already // relative, consider it to be relative to the given absolute path // already if ('' === $root && '' !== $baseRoot) { // If base path is already in its root if ('' === $relativeBasePath) { $relativePath = \ltrim($relativePath, './\\'); } return $relativePath; } // If the passed path is absolute, but the base path is not, we // cannot generate a relative path if ('' !== $root && '' === $baseRoot) { throw new \InvalidArgumentException(\sprintf('The absolute path "%s" cannot be made relative to the ' . 'relative path "%s". You should provide an absolute base ' . 'path instead.', $path, $basePath)); } // Fail if the roots of the two paths are different if ($baseRoot && $root !== $baseRoot) { throw new \InvalidArgumentException(\sprintf('The path "%s" cannot be made relative to "%s", because they ' . 'have different roots ("%s" and "%s").', $path, $basePath, $root, $baseRoot)); } if ('' === $relativeBasePath) { return $relativePath; } // Build a "../../" prefix with as many "../" parts as necessary $parts = \explode('/', $relativePath); $baseParts = \explode('/', $relativeBasePath); $dotDotPrefix = ''; // Once we found a non-matching part in the prefix, we need to add // "../" parts for all remaining parts $match = \true; foreach ($baseParts as $i => $basePart) { if ($match && isset($parts[$i]) && $basePart === $parts[$i]) { unset($parts[$i]); continue; } $match = \false; $dotDotPrefix .= '../'; } return \rtrim($dotDotPrefix . \implode('/', $parts), '/'); } /** * Returns whether the given path is on the local filesystem. * * @param string $path A path string. * * @return bool Returns true if the path is local, false for a URL. * * @since 1.0 Added method. * @since 2.0 Method now fails if $path is not a string. */ public static function isLocal($path) { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($path, 'The path must be a string. Got: %s'); return '' !== $path && \false === \strpos($path, '://'); } /** * Returns the longest common base path of a set of paths. * * Dot segments ("." and "..") are removed/collapsed and all slashes turned * into forward slashes. * * ```php * $basePath = Path::getLongestCommonBasePath(array( * '/webmozart/css/style.css', * '/webmozart/css/..' * )); * // => /webmozart * ``` * * The root is returned if no common base path can be found: * * ```php * $basePath = Path::getLongestCommonBasePath(array( * '/webmozart/css/style.css', * '/puli/css/..' * )); * // => / * ``` * * If the paths are located on different Windows partitions, `null` is * returned. * * ```php * $basePath = Path::getLongestCommonBasePath(array( * 'C:/webmozart/css/style.css', * 'D:/webmozart/css/..' * )); * // => null * ``` * * @param array $paths A list of paths. * * @return string|null The longest common base path in canonical form or * `null` if the paths are on different Windows * partitions. * * @since 1.0 Added method. * @since 2.0 Method now fails if $paths are not strings. */ public static function getLongestCommonBasePath(array $paths) { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::allString($paths, 'The paths must be strings. Got: %s'); list($bpRoot, $basePath) = self::split(self::canonicalize(\reset($paths))); for (\next($paths); null !== \key($paths) && '' !== $basePath; \next($paths)) { list($root, $path) = self::split(self::canonicalize(\current($paths))); // If we deal with different roots (e.g. C:/ vs. D:/), it's time // to quit if ($root !== $bpRoot) { return null; } // Make the base path shorter until it fits into path while (\true) { if ('.' === $basePath) { // No more base paths $basePath = ''; // Next path continue 2; } // Prevent false positives for common prefixes // see isBasePath() if (0 === \strpos($path . '/', $basePath . '/')) { // Next path continue 2; } $basePath = \dirname($basePath); } } return $bpRoot . $basePath; } /** * Joins two or more path strings. * * The result is a canonical path. * * @param string[]|string $paths Path parts as parameters or array. * * @return string The joint path. * * @since 2.0 Added method. */ public static function join($paths) { if (!\is_array($paths)) { $paths = \func_get_args(); } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::allString($paths, 'The paths must be strings. Got: %s'); $finalPath = null; $wasScheme = \false; foreach ($paths as $path) { $path = (string) $path; if ('' === $path) { continue; } if (null === $finalPath) { // For first part we keep slashes, like '/top', 'C:\' or 'phar://' $finalPath = $path; $wasScheme = \strpos($path, '://') !== \false; continue; } // Only add slash if previous part didn't end with '/' or '\' if (!\in_array(\substr($finalPath, -1), array('/', '\\'))) { $finalPath .= '/'; } // If first part included a scheme like 'phar://' we allow current part to start with '/', otherwise trim $finalPath .= $wasScheme ? $path : \ltrim($path, '/'); $wasScheme = \false; } if (null === $finalPath) { return ''; } return self::canonicalize($finalPath); } /** * Returns whether a path is a base path of another path. * * Dot segments ("." and "..") are removed/collapsed and all slashes turned * into forward slashes. * * ```php * Path::isBasePath('/webmozart', '/webmozart/css'); * // => true * * Path::isBasePath('/webmozart', '/webmozart'); * // => true * * Path::isBasePath('/webmozart', '/webmozart/..'); * // => false * * Path::isBasePath('/webmozart', '/puli'); * // => false * ``` * * @param string $basePath The base path to test. * @param string $ofPath The other path. * * @return bool Whether the base path is a base path of the other path. * * @since 1.0 Added method. * @since 2.0 Method now fails if $basePath or $ofPath is not a string. */ public static function isBasePath($basePath, $ofPath) { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($basePath, 'The base path must be a string. Got: %s'); $basePath = self::canonicalize($basePath); $ofPath = self::canonicalize($ofPath); // Append slashes to prevent false positives when two paths have // a common prefix, for example /base/foo and /base/foobar. // Don't append a slash for the root "/", because then that root // won't be discovered as common prefix ("//" is not a prefix of // "/foobar/"). return 0 === \strpos($ofPath . '/', \rtrim($basePath, '/') . '/'); } /** * Splits a part into its root directory and the remainder. * * If the path has no root directory, an empty root directory will be * returned. * * If the root directory is a Windows style partition, the resulting root * will always contain a trailing slash. * * list ($root, $path) = Path::split("C:/webmozart") * // => array("C:/", "webmozart") * * list ($root, $path) = Path::split("C:") * // => array("C:/", "") * * @param string $path The canonical path to split. * * @return string[] An array with the root directory and the remaining * relative path. */ private static function split($path) { if ('' === $path) { return array('', ''); } // Remember scheme as part of the root, if any if (\false !== ($pos = \strpos($path, '://'))) { $root = \substr($path, 0, $pos + 3); $path = \substr($path, $pos + 3); } else { $root = ''; } $length = \strlen($path); // Remove and remember root directory if ('/' === $path[0]) { $root .= '/'; $path = $length > 1 ? \substr($path, 1) : ''; } elseif ($length > 1 && \ctype_alpha($path[0]) && ':' === $path[1]) { if (2 === $length) { // Windows special case: "C:" $root .= $path . '/'; $path = ''; } elseif ('/' === $path[2]) { // Windows normal case: "C:/".. $root .= \substr($path, 0, 3); $path = $length > 3 ? \substr($path, 3) : ''; } } return array($root, $path); } /** * Converts string to lower-case (multi-byte safe if mbstring is installed). * * @param string $str The string * * @return string Lower case string */ private static function toLower($str) { if (\function_exists('mb_strtolower')) { return \mb_strtolower($str, \mb_detect_encoding($str)); } return \strtolower($str); } private function __construct() { } } The MIT License (MIT) Copyright (c) 2014 Bernhard Schussek Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allString($value, $message = ''); /** * @psalm-pure * @psalm-assert null|non-empty-string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrStringNotEmpty($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allStringNotEmpty($value, $message = ''); /** * @psalm-pure * @psalm-assert null|int $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrInteger($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allInteger($value, $message = ''); /** * @psalm-pure * @psalm-assert null|numeric $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIntegerish($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIntegerish($value, $message = ''); /** * @psalm-pure * @psalm-assert null|float $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrFloat($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allFloat($value, $message = ''); /** * @psalm-pure * @psalm-assert null|numeric $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNumeric($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allNumeric($value, $message = ''); /** * @psalm-pure * @psalm-assert null|int $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNatural($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allNatural($value, $message = ''); /** * @psalm-pure * @psalm-assert null|bool $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrBoolean($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allBoolean($value, $message = ''); /** * @psalm-pure * @psalm-assert null|scalar $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrScalar($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allScalar($value, $message = ''); /** * @psalm-pure * @psalm-assert null|object $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrObject($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allObject($value, $message = ''); /** * @psalm-pure * @psalm-assert null|resource $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * * @throws InvalidArgumentException */ public static function nullOrResource($value, $type = null, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * * @throws InvalidArgumentException */ public static function allResource($value, $type = null, $message = ''); /** * @psalm-pure * @psalm-assert null|callable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsCallable($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIsCallable($value, $message = ''); /** * @psalm-pure * @psalm-assert null|array $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsArray($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIsArray($value, $message = ''); /** * @psalm-pure * @psalm-assert null|iterable $value * * @deprecated use "isIterable" or "isInstanceOf" instead * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsTraversable($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @deprecated use "isIterable" or "isInstanceOf" instead * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIsTraversable($value, $message = ''); /** * @psalm-pure * @psalm-assert null|array|ArrayAccess $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsArrayAccessible($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIsArrayAccessible($value, $message = ''); /** * @psalm-pure * @psalm-assert null|countable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsCountable($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIsCountable($value, $message = ''); /** * @psalm-pure * @psalm-assert null|iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsIterable($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIsIterable($value, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert null|ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsInstanceOf($value, $class, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function allIsInstanceOf($value, $class, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotInstanceOf($value, $class, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function allNotInstanceOf($value, $class, $message = ''); /** * @psalm-pure * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsInstanceOfAny($value, $classes, $message = ''); /** * @psalm-pure * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * * @throws InvalidArgumentException */ public static function allIsInstanceOfAny($value, $classes, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert null|ExpectedType|class-string $value * * @param null|object|string $value * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsAOf($value, $class, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable> $value * * @param iterable $value * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function allIsAOf($value, $class, $message = ''); /** * @psalm-pure * @psalm-template UnexpectedType of object * @psalm-param class-string $class * * @param null|object|string $value * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsNotA($value, $class, $message = ''); /** * @psalm-pure * @psalm-template UnexpectedType of object * @psalm-param class-string $class * * @param iterable $value * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function allIsNotA($value, $class, $message = ''); /** * @psalm-pure * @psalm-param array $classes * * @param null|object|string $value * @param string[] $classes * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsAnyOf($value, $classes, $message = ''); /** * @psalm-pure * @psalm-param array $classes * * @param iterable $value * @param string[] $classes * @param string $message * * @throws InvalidArgumentException */ public static function allIsAnyOf($value, $classes, $message = ''); /** * @psalm-pure * @psalm-assert empty $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsEmpty($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIsEmpty($value, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotEmpty($value, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allNotEmpty($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allNull($value, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allNotNull($value, $message = ''); /** * @psalm-pure * @psalm-assert null|true $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrTrue($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allTrue($value, $message = ''); /** * @psalm-pure * @psalm-assert null|false $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrFalse($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allFalse($value, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotFalse($value, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allNotFalse($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIp($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIp($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIpv4($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIpv4($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIpv6($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allIpv6($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrEmail($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allEmail($value, $message = ''); /** * @param null|array $values * @param string $message * * @throws InvalidArgumentException */ public static function nullOrUniqueValues($values, $message = ''); /** * @param iterable $values * @param string $message * * @throws InvalidArgumentException */ public static function allUniqueValues($values, $message = ''); /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function nullOrEq($value, $expect, $message = ''); /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function allEq($value, $expect, $message = ''); /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotEq($value, $expect, $message = ''); /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function allNotEq($value, $expect, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function nullOrSame($value, $expect, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function allSame($value, $expect, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotSame($value, $expect, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function allNotSame($value, $expect, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function nullOrGreaterThan($value, $limit, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function allGreaterThan($value, $limit, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function nullOrGreaterThanEq($value, $limit, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function allGreaterThanEq($value, $limit, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function nullOrLessThan($value, $limit, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function allLessThan($value, $limit, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function nullOrLessThanEq($value, $limit, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function allLessThanEq($value, $limit, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $min * @param mixed $max * @param string $message * * @throws InvalidArgumentException */ public static function nullOrRange($value, $min, $max, $message = ''); /** * @psalm-pure * * @param mixed $value * @param mixed $min * @param mixed $max * @param string $message * * @throws InvalidArgumentException */ public static function allRange($value, $min, $max, $message = ''); /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function nullOrOneOf($value, $values, $message = ''); /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function allOneOf($value, $values, $message = ''); /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function nullOrInArray($value, $values, $message = ''); /** * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function allInArray($value, $values, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $subString * @param string $message * * @throws InvalidArgumentException */ public static function nullOrContains($value, $subString, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $subString * @param string $message * * @throws InvalidArgumentException */ public static function allContains($value, $subString, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $subString * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotContains($value, $subString, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $subString * @param string $message * * @throws InvalidArgumentException */ public static function allNotContains($value, $subString, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotWhitespaceOnly($value, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException */ public static function allNotWhitespaceOnly($value, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException */ public static function nullOrStartsWith($value, $prefix, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException */ public static function allStartsWith($value, $prefix, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotStartsWith($value, $prefix, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException */ public static function allNotStartsWith($value, $prefix, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrStartsWithLetter($value, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allStartsWithLetter($value, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException */ public static function nullOrEndsWith($value, $suffix, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException */ public static function allEndsWith($value, $suffix, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotEndsWith($value, $suffix, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException */ public static function allNotEndsWith($value, $suffix, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException */ public static function nullOrRegex($value, $pattern, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException */ public static function allRegex($value, $pattern, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException */ public static function nullOrNotRegex($value, $pattern, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException */ public static function allNotRegex($value, $pattern, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrUnicodeLetters($value, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allUnicodeLetters($value, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrAlpha($value, $message = ''); /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allAlpha($value, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrDigits($value, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException */ public static function allDigits($value, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrAlnum($value, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException */ public static function allAlnum($value, $message = ''); /** * @psalm-pure * @psalm-assert null|lowercase-string $value * * @param null|string $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrLower($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param iterable $value * @param string $message * * @throws InvalidArgumentException */ public static function allLower($value, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrUpper($value, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException */ public static function allUpper($value, $message = ''); /** * @psalm-pure * * @param null|string $value * @param int $length * @param string $message * * @throws InvalidArgumentException */ public static function nullOrLength($value, $length, $message = ''); /** * @psalm-pure * * @param iterable $value * @param int $length * @param string $message * * @throws InvalidArgumentException */ public static function allLength($value, $length, $message = ''); /** * @psalm-pure * * @param null|string $value * @param int|float $min * @param string $message * * @throws InvalidArgumentException */ public static function nullOrMinLength($value, $min, $message = ''); /** * @psalm-pure * * @param iterable $value * @param int|float $min * @param string $message * * @throws InvalidArgumentException */ public static function allMinLength($value, $min, $message = ''); /** * @psalm-pure * * @param null|string $value * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function nullOrMaxLength($value, $max, $message = ''); /** * @psalm-pure * * @param iterable $value * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function allMaxLength($value, $max, $message = ''); /** * @psalm-pure * * @param null|string $value * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function nullOrLengthBetween($value, $min, $max, $message = ''); /** * @psalm-pure * * @param iterable $value * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function allLengthBetween($value, $min, $max, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrFileExists($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allFileExists($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrFile($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allFile($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrDirectory($value, $message = ''); /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allDirectory($value, $message = ''); /** * @param null|string $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrReadable($value, $message = ''); /** * @param iterable $value * @param string $message * * @throws InvalidArgumentException */ public static function allReadable($value, $message = ''); /** * @param null|string $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrWritable($value, $message = ''); /** * @param iterable $value * @param string $message * * @throws InvalidArgumentException */ public static function allWritable($value, $message = ''); /** * @psalm-assert null|class-string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrClassExists($value, $message = ''); /** * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allClassExists($value, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert null|class-string|ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function nullOrSubclassOf($value, $class, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert iterable|ExpectedType> $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function allSubclassOf($value, $class, $message = ''); /** * @psalm-assert null|class-string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrInterfaceExists($value, $message = ''); /** * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allInterfaceExists($value, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $interface * @psalm-assert null|class-string $value * * @param mixed $value * @param mixed $interface * @param string $message * * @throws InvalidArgumentException */ public static function nullOrImplementsInterface($value, $interface, $message = ''); /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $interface * @psalm-assert iterable> $value * * @param mixed $value * @param mixed $interface * @param string $message * * @throws InvalidArgumentException */ public static function allImplementsInterface($value, $interface, $message = ''); /** * @psalm-pure * @psalm-param null|class-string|object $classOrObject * * @param null|string|object $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException */ public static function nullOrPropertyExists($classOrObject, $property, $message = ''); /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException */ public static function allPropertyExists($classOrObject, $property, $message = ''); /** * @psalm-pure * @psalm-param null|class-string|object $classOrObject * * @param null|string|object $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException */ public static function nullOrPropertyNotExists($classOrObject, $property, $message = ''); /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException */ public static function allPropertyNotExists($classOrObject, $property, $message = ''); /** * @psalm-pure * @psalm-param null|class-string|object $classOrObject * * @param null|string|object $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException */ public static function nullOrMethodExists($classOrObject, $method, $message = ''); /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException */ public static function allMethodExists($classOrObject, $method, $message = ''); /** * @psalm-pure * @psalm-param null|class-string|object $classOrObject * * @param null|string|object $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException */ public static function nullOrMethodNotExists($classOrObject, $method, $message = ''); /** * @psalm-pure * @psalm-param iterable $classOrObject * * @param iterable $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException */ public static function allMethodNotExists($classOrObject, $method, $message = ''); /** * @psalm-pure * * @param null|array $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException */ public static function nullOrKeyExists($array, $key, $message = ''); /** * @psalm-pure * * @param iterable $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException */ public static function allKeyExists($array, $key, $message = ''); /** * @psalm-pure * * @param null|array $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException */ public static function nullOrKeyNotExists($array, $key, $message = ''); /** * @psalm-pure * * @param iterable $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException */ public static function allKeyNotExists($array, $key, $message = ''); /** * @psalm-pure * @psalm-assert null|array-key $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrValidArrayKey($value, $message = ''); /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function allValidArrayKey($value, $message = ''); /** * @param null|Countable|array $array * @param int $number * @param string $message * * @throws InvalidArgumentException */ public static function nullOrCount($array, $number, $message = ''); /** * @param iterable $array * @param int $number * @param string $message * * @throws InvalidArgumentException */ public static function allCount($array, $number, $message = ''); /** * @param null|Countable|array $array * @param int|float $min * @param string $message * * @throws InvalidArgumentException */ public static function nullOrMinCount($array, $min, $message = ''); /** * @param iterable $array * @param int|float $min * @param string $message * * @throws InvalidArgumentException */ public static function allMinCount($array, $min, $message = ''); /** * @param null|Countable|array $array * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function nullOrMaxCount($array, $max, $message = ''); /** * @param iterable $array * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function allMaxCount($array, $max, $message = ''); /** * @param null|Countable|array $array * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function nullOrCountBetween($array, $min, $max, $message = ''); /** * @param iterable $array * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function allCountBetween($array, $min, $max, $message = ''); /** * @psalm-pure * @psalm-assert null|list $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsList($array, $message = ''); /** * @psalm-pure * @psalm-assert iterable $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function allIsList($array, $message = ''); /** * @psalm-pure * @psalm-assert null|non-empty-list $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsNonEmptyList($array, $message = ''); /** * @psalm-pure * @psalm-assert iterable $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function allIsNonEmptyList($array, $message = ''); /** * @psalm-pure * @psalm-template T * @psalm-param null|mixed|array $array * @psalm-assert null|array $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsMap($array, $message = ''); /** * @psalm-pure * @psalm-template T * @psalm-param iterable> $array * @psalm-assert iterable> $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function allIsMap($array, $message = ''); /** * @psalm-pure * @psalm-template T * @psalm-param null|mixed|array $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function nullOrIsNonEmptyMap($array, $message = ''); /** * @psalm-pure * @psalm-template T * @psalm-param iterable> $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function allIsNonEmptyMap($array, $message = ''); /** * @psalm-pure * * @param null|string $value * @param string $message * * @throws InvalidArgumentException */ public static function nullOrUuid($value, $message = ''); /** * @psalm-pure * * @param iterable $value * @param string $message * * @throws InvalidArgumentException */ public static function allUuid($value, $message = ''); /** * @psalm-param class-string $class * * @param null|Closure $expression * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function nullOrThrows($expression, $class = 'Exception', $message = ''); /** * @psalm-param class-string $class * * @param iterable $expression * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function allThrows($expression, $class = 'Exception', $message = ''); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Webmozart\Assert; use ArrayAccess; use BadMethodCallException; use Closure; use Countable; use DateTime; use DateTimeImmutable; use Exception; use InvalidArgumentException; use ResourceBundle; use SimpleXMLElement; use Throwable; use Traversable; /** * Efficient assertions to validate the input/output of your methods. * * @mixin Mixin * * @since 1.0 * * @author Bernhard Schussek */ class Assert { /** * @psalm-pure * @psalm-assert string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function string($value, $message = '') { if (!\is_string($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a string. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert non-empty-string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function stringNotEmpty($value, $message = '') { static::string($value, $message); static::notEq($value, '', $message); } /** * @psalm-pure * @psalm-assert int $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function integer($value, $message = '') { if (!\is_int($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an integer. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert numeric $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function integerish($value, $message = '') { if (!\is_numeric($value) || $value != (int) $value) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an integerish value. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert float $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function float($value, $message = '') { if (!\is_float($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a float. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert numeric $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function numeric($value, $message = '') { if (!\is_numeric($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a numeric. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert int $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function natural($value, $message = '') { if (!\is_int($value) || $value < 0) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a non-negative integer. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-assert bool $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function boolean($value, $message = '') { if (!\is_bool($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a boolean. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert scalar $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function scalar($value, $message = '') { if (!\is_scalar($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a scalar. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert object $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function object($value, $message = '') { if (!\is_object($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an object. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert resource $value * * @param mixed $value * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php * @param string $message * * @throws InvalidArgumentException */ public static function resource($value, $type = null, $message = '') { if (!\is_resource($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a resource. Got: %s', static::typeToString($value))); } if ($type && $type !== \get_resource_type($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a resource of type %2$s. Got: %s', static::typeToString($value), $type)); } } /** * @psalm-pure * @psalm-assert callable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isCallable($value, $message = '') { if (!\is_callable($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a callable. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert array $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isArray($value, $message = '') { if (!\is_array($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an array. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert iterable $value * * @deprecated use "isIterable" or "isInstanceOf" instead * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isTraversable($value, $message = '') { @\trigger_error(\sprintf('The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.', __METHOD__), \E_USER_DEPRECATED); if (!\is_array($value) && !$value instanceof \Traversable) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a traversable. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert array|ArrayAccess $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isArrayAccessible($value, $message = '') { if (!\is_array($value) && !$value instanceof \ArrayAccess) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an array accessible. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert countable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isCountable($value, $message = '') { if (!\is_array($value) && !$value instanceof \Countable && !$value instanceof \ResourceBundle && !$value instanceof \SimpleXMLElement) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a countable. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-assert iterable $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isIterable($value, $message = '') { if (!\is_array($value) && !$value instanceof \Traversable) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an iterable. Got: %s', static::typeToString($value))); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function isInstanceOf($value, $class, $message = '') { if (!$value instanceof $class) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of %2$s. Got: %s', static::typeToString($value), $class)); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert !ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function notInstanceOf($value, $class, $message = '') { if ($value instanceof $class) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance other than %2$s. Got: %s', static::typeToString($value), $class)); } } /** * @psalm-pure * @psalm-param array $classes * * @param mixed $value * @param array $classes * @param string $message * * @throws InvalidArgumentException */ public static function isInstanceOfAny($value, array $classes, $message = '') { foreach ($classes as $class) { if ($value instanceof $class) { return; } } static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of any of %2$s. Got: %s', static::typeToString($value), \implode(', ', \array_map(array('static', 'valueToString'), $classes)))); } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert ExpectedType|class-string $value * * @param object|string $value * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function isAOf($value, $class, $message = '') { static::string($class, 'Expected class as a string. Got: %s'); if (!\is_a($value, $class, \is_string($value))) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of this class or to this class among his parents %2$s. Got: %s', static::typeToString($value), $class)); } } /** * @psalm-pure * @psalm-template UnexpectedType of object * @psalm-param class-string $class * @psalm-assert !UnexpectedType $value * @psalm-assert !class-string $value * * @param object|string $value * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function isNotA($value, $class, $message = '') { static::string($class, 'Expected class as a string. Got: %s'); if (\is_a($value, $class, \is_string($value))) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an instance of this class or to this class among his parents other than %2$s. Got: %s', static::typeToString($value), $class)); } } /** * @psalm-pure * @psalm-param array $classes * * @param object|string $value * @param string[] $classes * @param string $message * * @throws InvalidArgumentException */ public static function isAnyOf($value, array $classes, $message = '') { foreach ($classes as $class) { static::string($class, 'Expected class as a string. Got: %s'); if (\is_a($value, $class, \is_string($value))) { return; } } static::reportInvalidArgument(\sprintf($message ?: 'Expected an any of instance of this class or to this class among his parents other than %2$s. Got: %s', static::typeToString($value), \implode(', ', \array_map(array('static', 'valueToString'), $classes)))); } /** * @psalm-pure * @psalm-assert empty $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function isEmpty($value, $message = '') { if (!empty($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an empty value. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-assert !empty $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function notEmpty($value, $message = '') { if (empty($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a non-empty value. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-assert null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function null($value, $message = '') { if (null !== $value) { static::reportInvalidArgument(\sprintf($message ?: 'Expected null. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-assert !null $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function notNull($value, $message = '') { if (null === $value) { static::reportInvalidArgument($message ?: 'Expected a value other than null.'); } } /** * @psalm-pure * @psalm-assert true $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function true($value, $message = '') { if (\true !== $value) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be true. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-assert false $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function false($value, $message = '') { if (\false !== $value) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be false. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-assert !false $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function notFalse($value, $message = '') { if (\false === $value) { static::reportInvalidArgument($message ?: 'Expected a value other than false.'); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function ip($value, $message = '') { if (\false === \filter_var($value, \FILTER_VALIDATE_IP)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be an IP. Got: %s', static::valueToString($value))); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function ipv4($value, $message = '') { if (\false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be an IPv4. Got: %s', static::valueToString($value))); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function ipv6($value, $message = '') { if (\false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be an IPv6. Got: %s', static::valueToString($value))); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function email($value, $message = '') { if (\false === \filter_var($value, \FILTER_VALIDATE_EMAIL)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to be a valid e-mail address. Got: %s', static::valueToString($value))); } } /** * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion. * * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function uniqueValues(array $values, $message = '') { $allValues = \count($values); $uniqueValues = \count(\array_unique($values)); if ($allValues !== $uniqueValues) { $difference = $allValues - $uniqueValues; static::reportInvalidArgument(\sprintf($message ?: 'Expected an array of unique values, but %s of them %s duplicated', $difference, 1 === $difference ? 'is' : 'are')); } } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function eq($value, $expect, $message = '') { if ($expect != $value) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($expect))); } } /** * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function notEq($value, $expect, $message = '') { if ($expect == $value) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a different value than %s.', static::valueToString($expect))); } } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function same($value, $expect, $message = '') { if ($expect !== $value) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value identical to %2$s. Got: %s', static::valueToString($value), static::valueToString($expect))); } } /** * @psalm-pure * * @param mixed $value * @param mixed $expect * @param string $message * * @throws InvalidArgumentException */ public static function notSame($value, $expect, $message = '') { if ($expect === $value) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value not identical to %s.', static::valueToString($expect))); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function greaterThan($value, $limit, $message = '') { if ($value <= $limit) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value greater than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit))); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function greaterThanEq($value, $limit, $message = '') { if ($value < $limit) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value greater than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit))); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function lessThan($value, $limit, $message = '') { if ($value >= $limit) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value less than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit))); } } /** * @psalm-pure * * @param mixed $value * @param mixed $limit * @param string $message * * @throws InvalidArgumentException */ public static function lessThanEq($value, $limit, $message = '') { if ($value > $limit) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value less than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit))); } } /** * Inclusive range, so Assert::(3, 3, 5) passes. * * @psalm-pure * * @param mixed $value * @param mixed $min * @param mixed $max * @param string $message * * @throws InvalidArgumentException */ public static function range($value, $min, $max, $message = '') { if ($value < $min || $value > $max) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value between %2$s and %3$s. Got: %s', static::valueToString($value), static::valueToString($min), static::valueToString($max))); } } /** * A more human-readable alias of Assert::inArray(). * * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function oneOf($value, array $values, $message = '') { static::inArray($value, $values, $message); } /** * Does strict comparison, so Assert::inArray(3, ['3']) does not pass the assertion. * * @psalm-pure * * @param mixed $value * @param array $values * @param string $message * * @throws InvalidArgumentException */ public static function inArray($value, array $values, $message = '') { if (!\in_array($value, $values, \true)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected one of: %2$s. Got: %s', static::valueToString($value), \implode(', ', \array_map(array('static', 'valueToString'), $values)))); } } /** * @psalm-pure * * @param string $value * @param string $subString * @param string $message * * @throws InvalidArgumentException */ public static function contains($value, $subString, $message = '') { if (\false === \strpos($value, $subString)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain %2$s. Got: %s', static::valueToString($value), static::valueToString($subString))); } } /** * @psalm-pure * * @param string $value * @param string $subString * @param string $message * * @throws InvalidArgumentException */ public static function notContains($value, $subString, $message = '') { if (\false !== \strpos($value, $subString)) { static::reportInvalidArgument(\sprintf($message ?: '%2$s was not expected to be contained in a value. Got: %s', static::valueToString($value), static::valueToString($subString))); } } /** * @psalm-pure * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function notWhitespaceOnly($value, $message = '') { if (\preg_match('/^\\s*$/', $value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a non-whitespace string. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * * @param string $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException */ public static function startsWith($value, $prefix, $message = '') { if (0 !== \strpos($value, $prefix)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to start with %2$s. Got: %s', static::valueToString($value), static::valueToString($prefix))); } } /** * @psalm-pure * * @param string $value * @param string $prefix * @param string $message * * @throws InvalidArgumentException */ public static function notStartsWith($value, $prefix, $message = '') { if (0 === \strpos($value, $prefix)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value not to start with %2$s. Got: %s', static::valueToString($value), static::valueToString($prefix))); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function startsWithLetter($value, $message = '') { static::string($value); $valid = isset($value[0]); if ($valid) { $locale = \setlocale(\LC_CTYPE, 0); \setlocale(\LC_CTYPE, 'C'); $valid = \ctype_alpha($value[0]); \setlocale(\LC_CTYPE, $locale); } if (!$valid) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to start with a letter. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * * @param string $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException */ public static function endsWith($value, $suffix, $message = '') { if ($suffix !== \substr($value, -\strlen($suffix))) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to end with %2$s. Got: %s', static::valueToString($value), static::valueToString($suffix))); } } /** * @psalm-pure * * @param string $value * @param string $suffix * @param string $message * * @throws InvalidArgumentException */ public static function notEndsWith($value, $suffix, $message = '') { if ($suffix === \substr($value, -\strlen($suffix))) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value not to end with %2$s. Got: %s', static::valueToString($value), static::valueToString($suffix))); } } /** * @psalm-pure * * @param string $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException */ public static function regex($value, $pattern, $message = '') { if (!\preg_match($pattern, $value)) { static::reportInvalidArgument(\sprintf($message ?: 'The value %s does not match the expected pattern.', static::valueToString($value))); } } /** * @psalm-pure * * @param string $value * @param string $pattern * @param string $message * * @throws InvalidArgumentException */ public static function notRegex($value, $pattern, $message = '') { if (\preg_match($pattern, $value, $matches, \PREG_OFFSET_CAPTURE)) { static::reportInvalidArgument(\sprintf($message ?: 'The value %s matches the pattern %s (at offset %d).', static::valueToString($value), static::valueToString($pattern), $matches[0][1])); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function unicodeLetters($value, $message = '') { static::string($value); if (!\preg_match('/^\\p{L}+$/u', $value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain only Unicode letters. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function alpha($value, $message = '') { static::string($value); $locale = \setlocale(\LC_CTYPE, 0); \setlocale(\LC_CTYPE, 'C'); $valid = !\ctype_alpha($value); \setlocale(\LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain only letters. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function digits($value, $message = '') { $locale = \setlocale(\LC_CTYPE, 0); \setlocale(\LC_CTYPE, 'C'); $valid = !\ctype_digit($value); \setlocale(\LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain digits only. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function alnum($value, $message = '') { $locale = \setlocale(\LC_CTYPE, 0); \setlocale(\LC_CTYPE, 'C'); $valid = !\ctype_alnum($value); \setlocale(\LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain letters and digits only. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-assert lowercase-string $value * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function lower($value, $message = '') { $locale = \setlocale(\LC_CTYPE, 0); \setlocale(\LC_CTYPE, 'C'); $valid = !\ctype_lower($value); \setlocale(\LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain lowercase characters only. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-assert !lowercase-string $value * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function upper($value, $message = '') { $locale = \setlocale(\LC_CTYPE, 0); \setlocale(\LC_CTYPE, 'C'); $valid = !\ctype_upper($value); \setlocale(\LC_CTYPE, $locale); if ($valid) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain uppercase characters only. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * * @param string $value * @param int $length * @param string $message * * @throws InvalidArgumentException */ public static function length($value, $length, $message = '') { if ($length !== static::strlen($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain %2$s characters. Got: %s', static::valueToString($value), $length)); } } /** * Inclusive min. * * @psalm-pure * * @param string $value * @param int|float $min * @param string $message * * @throws InvalidArgumentException */ public static function minLength($value, $min, $message = '') { if (static::strlen($value) < $min) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain at least %2$s characters. Got: %s', static::valueToString($value), $min)); } } /** * Inclusive max. * * @psalm-pure * * @param string $value * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function maxLength($value, $max, $message = '') { if (static::strlen($value) > $max) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain at most %2$s characters. Got: %s', static::valueToString($value), $max)); } } /** * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion. * * @psalm-pure * * @param string $value * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function lengthBetween($value, $min, $max, $message = '') { $length = static::strlen($value); if ($length < $min || $length > $max) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s', static::valueToString($value), $min, $max)); } } /** * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file. * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function fileExists($value, $message = '') { static::string($value); if (!\file_exists($value)) { static::reportInvalidArgument(\sprintf($message ?: 'The file %s does not exist.', static::valueToString($value))); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function file($value, $message = '') { static::fileExists($value, $message); if (!\is_file($value)) { static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not a file.', static::valueToString($value))); } } /** * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function directory($value, $message = '') { static::fileExists($value, $message); if (!\is_dir($value)) { static::reportInvalidArgument(\sprintf($message ?: 'The path %s is no directory.', static::valueToString($value))); } } /** * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function readable($value, $message = '') { if (!\is_readable($value)) { static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not readable.', static::valueToString($value))); } } /** * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function writable($value, $message = '') { if (!\is_writable($value)) { static::reportInvalidArgument(\sprintf($message ?: 'The path %s is not writable.', static::valueToString($value))); } } /** * @psalm-assert class-string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function classExists($value, $message = '') { if (!\class_exists($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an existing class name. Got: %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $class * @psalm-assert class-string|ExpectedType $value * * @param mixed $value * @param string|object $class * @param string $message * * @throws InvalidArgumentException */ public static function subclassOf($value, $class, $message = '') { if (!\is_subclass_of($value, $class)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected a sub-class of %2$s. Got: %s', static::valueToString($value), static::valueToString($class))); } } /** * @psalm-assert class-string $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function interfaceExists($value, $message = '') { if (!\interface_exists($value)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an existing interface name. got %s', static::valueToString($value))); } } /** * @psalm-pure * @psalm-template ExpectedType of object * @psalm-param class-string $interface * @psalm-assert class-string $value * * @param mixed $value * @param mixed $interface * @param string $message * * @throws InvalidArgumentException */ public static function implementsInterface($value, $interface, $message = '') { if (!\in_array($interface, \class_implements($value))) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an implementation of %2$s. Got: %s', static::valueToString($value), static::valueToString($interface))); } } /** * @psalm-pure * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException */ public static function propertyExists($classOrObject, $property, $message = '') { if (!\property_exists($classOrObject, $property)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected the property %s to exist.', static::valueToString($property))); } } /** * @psalm-pure * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $property * @param string $message * * @throws InvalidArgumentException */ public static function propertyNotExists($classOrObject, $property, $message = '') { if (\property_exists($classOrObject, $property)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected the property %s to not exist.', static::valueToString($property))); } } /** * @psalm-pure * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException */ public static function methodExists($classOrObject, $method, $message = '') { if (!(\is_string($classOrObject) || \is_object($classOrObject)) || !\method_exists($classOrObject, $method)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected the method %s to exist.', static::valueToString($method))); } } /** * @psalm-pure * @psalm-param class-string|object $classOrObject * * @param string|object $classOrObject * @param mixed $method * @param string $message * * @throws InvalidArgumentException */ public static function methodNotExists($classOrObject, $method, $message = '') { if ((\is_string($classOrObject) || \is_object($classOrObject)) && \method_exists($classOrObject, $method)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected the method %s to not exist.', static::valueToString($method))); } } /** * @psalm-pure * * @param array $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException */ public static function keyExists($array, $key, $message = '') { if (!(isset($array[$key]) || \array_key_exists($key, $array))) { static::reportInvalidArgument(\sprintf($message ?: 'Expected the key %s to exist.', static::valueToString($key))); } } /** * @psalm-pure * * @param array $array * @param string|int $key * @param string $message * * @throws InvalidArgumentException */ public static function keyNotExists($array, $key, $message = '') { if (isset($array[$key]) || \array_key_exists($key, $array)) { static::reportInvalidArgument(\sprintf($message ?: 'Expected the key %s to not exist.', static::valueToString($key))); } } /** * Checks if a value is a valid array key (int or string). * * @psalm-pure * @psalm-assert array-key $value * * @param mixed $value * @param string $message * * @throws InvalidArgumentException */ public static function validArrayKey($value, $message = '') { if (!(\is_int($value) || \is_string($value))) { static::reportInvalidArgument(\sprintf($message ?: 'Expected string or integer. Got: %s', static::typeToString($value))); } } /** * Does not check if $array is countable, this can generate a warning on php versions after 7.2. * * @param Countable|array $array * @param int $number * @param string $message * * @throws InvalidArgumentException */ public static function count($array, $number, $message = '') { static::eq(\count($array), $number, \sprintf($message ?: 'Expected an array to contain %d elements. Got: %d.', $number, \count($array))); } /** * Does not check if $array is countable, this can generate a warning on php versions after 7.2. * * @param Countable|array $array * @param int|float $min * @param string $message * * @throws InvalidArgumentException */ public static function minCount($array, $min, $message = '') { if (\count($array) < $min) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an array to contain at least %2$d elements. Got: %d', \count($array), $min)); } } /** * Does not check if $array is countable, this can generate a warning on php versions after 7.2. * * @param Countable|array $array * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function maxCount($array, $max, $message = '') { if (\count($array) > $max) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an array to contain at most %2$d elements. Got: %d', \count($array), $max)); } } /** * Does not check if $array is countable, this can generate a warning on php versions after 7.2. * * @param Countable|array $array * @param int|float $min * @param int|float $max * @param string $message * * @throws InvalidArgumentException */ public static function countBetween($array, $min, $max, $message = '') { $count = \count($array); if ($count < $min || $count > $max) { static::reportInvalidArgument(\sprintf($message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d', $count, $min, $max)); } } /** * @psalm-pure * @psalm-assert list $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function isList($array, $message = '') { if (!\is_array($array) || $array !== \array_values($array)) { static::reportInvalidArgument($message ?: 'Expected list - non-associative array.'); } } /** * @psalm-pure * @psalm-assert non-empty-list $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function isNonEmptyList($array, $message = '') { static::isList($array, $message); static::notEmpty($array, $message); } /** * @psalm-pure * @psalm-template T * @psalm-param mixed|array $array * @psalm-assert array $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function isMap($array, $message = '') { if (!\is_array($array) || \array_keys($array) !== \array_filter(\array_keys($array), '\\is_string')) { static::reportInvalidArgument($message ?: 'Expected map - associative array with string keys.'); } } /** * @psalm-pure * @psalm-template T * @psalm-param mixed|array $array * @psalm-assert array $array * @psalm-assert !empty $array * * @param mixed $array * @param string $message * * @throws InvalidArgumentException */ public static function isNonEmptyMap($array, $message = '') { static::isMap($array, $message); static::notEmpty($array, $message); } /** * @psalm-pure * * @param string $value * @param string $message * * @throws InvalidArgumentException */ public static function uuid($value, $message = '') { $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value); // The nil UUID is special form of UUID that is specified to have all // 128 bits set to zero. if ('00000000-0000-0000-0000-000000000000' === $value) { return; } if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) { static::reportInvalidArgument(\sprintf($message ?: 'Value %s is not a valid UUID.', static::valueToString($value))); } } /** * @psalm-param class-string $class * * @param Closure $expression * @param string $class * @param string $message * * @throws InvalidArgumentException */ public static function throws(\Closure $expression, $class = 'Exception', $message = '') { static::string($class); $actual = 'none'; try { $expression(); } catch (\Exception $e) { $actual = \get_class($e); if ($e instanceof $class) { return; } } catch (\Throwable $e) { $actual = \get_class($e); if ($e instanceof $class) { return; } } static::reportInvalidArgument($message ?: \sprintf('Expected to throw "%s", got "%s"', $class, $actual)); } /** * @throws BadMethodCallException */ public static function __callStatic($name, $arguments) { if ('nullOr' === \substr($name, 0, 6)) { if (null !== $arguments[0]) { $method = \lcfirst(\substr($name, 6)); \call_user_func_array(array('static', $method), $arguments); } return; } if ('all' === \substr($name, 0, 3)) { static::isIterable($arguments[0]); $method = \lcfirst(\substr($name, 3)); $args = $arguments; foreach ($arguments[0] as $entry) { $args[0] = $entry; \call_user_func_array(array('static', $method), $args); } return; } throw new \BadMethodCallException('No such method: ' . $name); } /** * @param mixed $value * * @return string */ protected static function valueToString($value) { if (null === $value) { return 'null'; } if (\true === $value) { return 'true'; } if (\false === $value) { return 'false'; } if (\is_array($value)) { return 'array'; } if (\is_object($value)) { if (\method_exists($value, '__toString')) { return \get_class($value) . ': ' . self::valueToString($value->__toString()); } if ($value instanceof \DateTime || $value instanceof \DateTimeImmutable) { return \get_class($value) . ': ' . self::valueToString($value->format('c')); } return \get_class($value); } if (\is_resource($value)) { return 'resource'; } if (\is_string($value)) { return '"' . $value . '"'; } return (string) $value; } /** * @param mixed $value * * @return string */ protected static function typeToString($value) { return \is_object($value) ? \get_class($value) : \gettype($value); } protected static function strlen($value) { if (!\function_exists('mb_detect_encoding')) { return \strlen($value); } if (\false === ($encoding = \mb_detect_encoding($value))) { return \strlen($value); } return \mb_strlen($value, $encoding); } /** * @param string $message * * @throws InvalidArgumentException * * @psalm-pure this method is not supposed to perform side-effects */ protected static function reportInvalidArgument($message) { throw new \InvalidArgumentException($message); } private function __construct() { } } The MIT License (MIT) Copyright (c) 2014 Bernhard Schussek Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::EMERGENCY, $message, $context); } /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param array $context * * @return void */ public function alert($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::ALERT, $message, $context); } /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param array $context * * @return void */ public function critical($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::CRITICAL, $message, $context); } /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param array $context * * @return void */ public function error($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::ERROR, $message, $context); } /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param array $context * * @return void */ public function warning($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::WARNING, $message, $context); } /** * Normal but significant events. * * @param string $message * @param array $context * * @return void */ public function notice($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::NOTICE, $message, $context); } /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param array $context * * @return void */ public function info($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::INFO, $message, $context); } /** * Detailed debug information. * * @param string $message * @param array $context * * @return void */ public function debug($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::DEBUG, $message, $context); } } logger) { }` * blocks. */ class NullLogger extends \_HumbugBoxd02f763d3c56\Psr\Log\AbstractLogger { /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * * @return void * * @throws \Psr\Log\InvalidArgumentException */ public function log($level, $message, array $context = array()) { // noop } } logger = $logger; } } log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::EMERGENCY, $message, $context); } /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param array $context * * @return void */ public function alert($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::ALERT, $message, $context); } /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param array $context * * @return void */ public function critical($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::CRITICAL, $message, $context); } /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param array $context * * @return void */ public function error($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::ERROR, $message, $context); } /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param array $context * * @return void */ public function warning($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::WARNING, $message, $context); } /** * Normal but significant events. * * @param string $message * @param array $context * * @return void */ public function notice($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::NOTICE, $message, $context); } /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param array $context * * @return void */ public function info($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::INFO, $message, $context); } /** * Detailed debug information. * * @param string $message * @param array $context * * @return void */ public function debug($message, array $context = array()) { $this->log(\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::DEBUG, $message, $context); } /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * * @return void * * @throws \Psr\Log\InvalidArgumentException */ public abstract function log($level, $message, array $context = array()); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Polyfill\Php73; /** * @author Gabriel Caruso * @author Ion Bazan * * @internal */ final class Php73 { public static $startAt = 1533462603; /** * @param bool $asNum * * @return array|float|int */ public static function hrtime($asNum = \false) { $ns = \microtime(\false); $s = \substr($ns, 11) - self::$startAt; $ns = 1000000000.0 * (float) $ns; if ($asNum) { $ns += $s * 1000000000.0; return \PHP_INT_SIZE === 4 ? $ns : (int) $ns; } return array($s, (int) $ns); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use _HumbugBoxd02f763d3c56\Symfony\Polyfill\Php73 as p; if (\PHP_VERSION_ID >= 70300) { return; } if (!\function_exists('is_countable')) { function is_countable($var) { return \is_array($var) || $var instanceof \Countable || $var instanceof \ResourceBundle || $var instanceof \_HumbugBoxd02f763d3c56\SimpleXmlElement; } } if (!\function_exists('hrtime')) { require_once __DIR__ . '/Php73.php'; \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Php73\Php73::$startAt = (int) \microtime(\true); function hrtime($asNum = \false) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Php73\Php73::hrtime($asNum); } } if (!\function_exists('array_key_first')) { function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } } } if (!\function_exists('array_key_last')) { function array_key_last(array $array) { \end($array); return \key($array); } } Copyright (c) 2018-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class JsonException extends \Exception { } if (!\class_exists(\JsonException::class, false)) { /* * This file is part of the Symfony package. * * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ \class_alias('_HumbugBoxd02f763d3c56\\JsonException', 'JsonException', \false); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype; /** * Ctype implementation through regex. * * @internal * * @author Gert de Pagter */ final class Ctype { /** * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise. * * @see https://php.net/ctype-alnum * * @param string|int $text * * @return bool */ public static function ctype_alnum($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^A-Za-z0-9]/', $text); } /** * Returns TRUE if every character in text is a letter, FALSE otherwise. * * @see https://php.net/ctype-alpha * * @param string|int $text * * @return bool */ public static function ctype_alpha($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^A-Za-z]/', $text); } /** * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise. * * @see https://php.net/ctype-cntrl * * @param string|int $text * * @return bool */ public static function ctype_cntrl($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^\\x00-\\x1f\\x7f]/', $text); } /** * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise. * * @see https://php.net/ctype-digit * * @param string|int $text * * @return bool */ public static function ctype_digit($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^0-9]/', $text); } /** * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise. * * @see https://php.net/ctype-graph * * @param string|int $text * * @return bool */ public static function ctype_graph($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^!-~]/', $text); } /** * Returns TRUE if every character in text is a lowercase letter. * * @see https://php.net/ctype-lower * * @param string|int $text * * @return bool */ public static function ctype_lower($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^a-z]/', $text); } /** * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all. * * @see https://php.net/ctype-print * * @param string|int $text * * @return bool */ public static function ctype_print($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^ -~]/', $text); } /** * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise. * * @see https://php.net/ctype-punct * * @param string|int $text * * @return bool */ public static function ctype_punct($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^!-\\/\\:-@\\[-`\\{-~]/', $text); } /** * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters. * * @see https://php.net/ctype-space * * @param string|int $text * * @return bool */ public static function ctype_space($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^\\s]/', $text); } /** * Returns TRUE if every character in text is an uppercase letter. * * @see https://php.net/ctype-upper * * @param string|int $text * * @return bool */ public static function ctype_upper($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^A-Z]/', $text); } /** * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise. * * @see https://php.net/ctype-xdigit * * @param string|int $text * * @return bool */ public static function ctype_xdigit($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !\preg_match('/[^A-Fa-f0-9]/', $text); } /** * Converts integers to their char versions according to normal ctype behaviour, if needed. * * If an integer between -128 and 255 inclusive is provided, * it is interpreted as the ASCII value of a single character * (negative values have 256 added in order to allow characters in the Extended ASCII range). * Any other integer is interpreted as a string containing the decimal digits of the integer. * * @param string|int $int * * @return mixed */ private static function convert_int_to_char_for_ctype($int) { if (!\is_int($int)) { return $int; } if ($int < -128 || $int > 255) { return (string) $int; } if ($int < 0) { $int += 256; } return \chr($int); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use _HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype as p; if (!\function_exists('ctype_alnum')) { function ctype_alnum($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_alnum($text); } } if (!\function_exists('ctype_alpha')) { function ctype_alpha($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_alpha($text); } } if (!\function_exists('ctype_cntrl')) { function ctype_cntrl($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_cntrl($text); } } if (!\function_exists('ctype_digit')) { function ctype_digit($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_digit($text); } } if (!\function_exists('ctype_graph')) { function ctype_graph($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_graph($text); } } if (!\function_exists('ctype_lower')) { function ctype_lower($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_lower($text); } } if (!\function_exists('ctype_print')) { function ctype_print($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_print($text); } } if (!\function_exists('ctype_punct')) { function ctype_punct($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_punct($text); } } if (!\function_exists('ctype_space')) { function ctype_space($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_space($text); } } if (!\function_exists('ctype_upper')) { function ctype_upper($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_upper($text); } } if (!\function_exists('ctype_xdigit')) { function ctype_xdigit($text) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Ctype\Ctype::ctype_xdigit($text); } } Copyright (c) 2018-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use _HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Normalizer as p; if (!\function_exists('normalizer_is_normalized')) { function normalizer_is_normalized($s, $form = \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Normalizer\Normalizer::NFC) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Normalizer\Normalizer::isNormalized($s, $form); } } if (!\function_exists('normalizer_normalize')) { function normalizer_normalize($s, $form = \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Normalizer\Normalizer::NFC) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Normalizer\Normalizer::normalize($s, $form); } } Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Normalizer; /** * Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension. * * It has been validated with Unicode 6.3 Normalization Conformance Test. * See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations. * * @author Nicolas Grekas * * @internal */ class Normalizer { const FORM_D = \Normalizer::FORM_D; const FORM_KD = \Normalizer::FORM_KD; const FORM_C = \Normalizer::FORM_C; const FORM_KC = \Normalizer::FORM_KC; const NFD = \Normalizer::NFD; const NFKD = \Normalizer::NFKD; const NFC = \Normalizer::NFC; const NFKC = \Normalizer::NFKC; private static $C; private static $D; private static $KD; private static $cC; private static $ulenMask = array("" => 2, "" => 2, "" => 3, "" => 4); private static $ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T $T && ($T += 0x40); $ulen += 3; } $L = 0xac00 + ($L * 21 + $V) * 28 + $T; $lastUchr = \chr(0xe0 | $L >> 12) . \chr(0x80 | $L >> 6 & 0x3f) . \chr(0x80 | $L & 0x3f); } $i += $ulen; } return $result . $lastUchr . $tail; } private static function decompose($s, $c) { $result = ''; $ASCII = self::$ASCII; $decompMap = self::$D; $combClass = self::$cC; $ulenMask = self::$ulenMask; if ($c) { $compatMap = self::$KD; } $c = array(); $i = 0; $len = \strlen($s); while ($i < $len) { if ($s[$i] < "") { // ASCII chars if ($c) { \ksort($c); $result .= \implode('', $c); $c = array(); } $j = 1 + \strspn($s, $ASCII, $i + 1); $result .= \substr($s, $i, $j); $i += $j; continue; } $ulen = $ulenMask[$s[$i] & ""]; $uchr = \substr($s, $i, $ulen); $i += $ulen; if ($uchr < "가" || "힣" < $uchr) { // Table lookup if ($uchr !== ($j = isset($compatMap[$uchr]) ? $compatMap[$uchr] : (isset($decompMap[$uchr]) ? $decompMap[$uchr] : $uchr))) { $uchr = $j; $j = \strlen($uchr); $ulen = $uchr[0] < "" ? 1 : $ulenMask[$uchr[0] & ""]; if ($ulen != $j) { // Put trailing chars in $s $j -= $ulen; $i -= $j; if (0 > $i) { $s = \str_repeat(' ', -$i) . $s; $len -= $i; $i = 0; } while ($j--) { $s[$i + $j] = $uchr[$ulen + $j]; } $uchr = \substr($uchr, 0, $ulen); } } if (isset($combClass[$uchr])) { // Combining chars, for sorting if (!isset($c[$combClass[$uchr]])) { $c[$combClass[$uchr]] = ''; } $c[$combClass[$uchr]] .= $uchr; continue; } } else { // Hangul chars $uchr = \unpack('C*', $uchr); $j = ($uchr[1] - 224 << 12) + ($uchr[2] - 128 << 6) + $uchr[3] - 0xac80; $uchr = "" . \chr(0x80 + (int) ($j / 588)) . "" . \chr(0xa1 + (int) ($j % 588 / 28)); if ($j %= 28) { $uchr .= $j < 25 ? "" . \chr(0xa7 + $j) : "" . \chr(0x67 + $j); } } if ($c) { \ksort($c); $result .= \implode('', $c); $c = array(); } $result .= $uchr; } if ($c) { \ksort($c); $result .= \implode('', $c); } return $result; } private static function getData($file) { if (\file_exists($file = __DIR__ . '/Resources/unidata/' . $file . '.php')) { return require $file; } return \false; } } 230, '́' => 230, '̂' => 230, '̃' => 230, '̄' => 230, '̅' => 230, '̆' => 230, '̇' => 230, '̈' => 230, '̉' => 230, '̊' => 230, '̋' => 230, '̌' => 230, '̍' => 230, '̎' => 230, '̏' => 230, '̐' => 230, '̑' => 230, '̒' => 230, '̓' => 230, '̔' => 230, '̕' => 232, '̖' => 220, '̗' => 220, '̘' => 220, '̙' => 220, '̚' => 232, '̛' => 216, '̜' => 220, '̝' => 220, '̞' => 220, '̟' => 220, '̠' => 220, '̡' => 202, '̢' => 202, '̣' => 220, '̤' => 220, '̥' => 220, '̦' => 220, '̧' => 202, '̨' => 202, '̩' => 220, '̪' => 220, '̫' => 220, '̬' => 220, '̭' => 220, '̮' => 220, '̯' => 220, '̰' => 220, '̱' => 220, '̲' => 220, '̳' => 220, '̴' => 1, '̵' => 1, '̶' => 1, '̷' => 1, '̸' => 1, '̹' => 220, '̺' => 220, '̻' => 220, '̼' => 220, '̽' => 230, '̾' => 230, '̿' => 230, '̀' => 230, '́' => 230, '͂' => 230, '̓' => 230, '̈́' => 230, 'ͅ' => 240, '͆' => 230, '͇' => 220, '͈' => 220, '͉' => 220, '͊' => 230, '͋' => 230, '͌' => 230, '͍' => 220, '͎' => 220, '͐' => 230, '͑' => 230, '͒' => 230, '͓' => 220, '͔' => 220, '͕' => 220, '͖' => 220, '͗' => 230, '͘' => 232, '͙' => 220, '͚' => 220, '͛' => 230, '͜' => 233, '͝' => 234, '͞' => 234, '͟' => 233, '͠' => 234, '͡' => 234, '͢' => 233, 'ͣ' => 230, 'ͤ' => 230, 'ͥ' => 230, 'ͦ' => 230, 'ͧ' => 230, 'ͨ' => 230, 'ͩ' => 230, 'ͪ' => 230, 'ͫ' => 230, 'ͬ' => 230, 'ͭ' => 230, 'ͮ' => 230, 'ͯ' => 230, '҃' => 230, '҄' => 230, '҅' => 230, '҆' => 230, '҇' => 230, '֑' => 220, '֒' => 230, '֓' => 230, '֔' => 230, '֕' => 230, '֖' => 220, '֗' => 230, '֘' => 230, '֙' => 230, '֚' => 222, '֛' => 220, '֜' => 230, '֝' => 230, '֞' => 230, '֟' => 230, '֠' => 230, '֡' => 230, '֢' => 220, '֣' => 220, '֤' => 220, '֥' => 220, '֦' => 220, '֧' => 220, '֨' => 230, '֩' => 230, '֪' => 220, '֫' => 230, '֬' => 230, '֭' => 222, '֮' => 228, '֯' => 230, 'ְ' => 10, 'ֱ' => 11, 'ֲ' => 12, 'ֳ' => 13, 'ִ' => 14, 'ֵ' => 15, 'ֶ' => 16, 'ַ' => 17, 'ָ' => 18, 'ֹ' => 19, 'ֺ' => 19, 'ֻ' => 20, 'ּ' => 21, 'ֽ' => 22, 'ֿ' => 23, 'ׁ' => 24, 'ׂ' => 25, 'ׄ' => 230, 'ׅ' => 220, 'ׇ' => 18, 'ؐ' => 230, 'ؑ' => 230, 'ؒ' => 230, 'ؓ' => 230, 'ؔ' => 230, 'ؕ' => 230, 'ؖ' => 230, 'ؗ' => 230, 'ؘ' => 30, 'ؙ' => 31, 'ؚ' => 32, 'ً' => 27, 'ٌ' => 28, 'ٍ' => 29, 'َ' => 30, 'ُ' => 31, 'ِ' => 32, 'ّ' => 33, 'ْ' => 34, 'ٓ' => 230, 'ٔ' => 230, 'ٕ' => 220, 'ٖ' => 220, 'ٗ' => 230, '٘' => 230, 'ٙ' => 230, 'ٚ' => 230, 'ٛ' => 230, 'ٜ' => 220, 'ٝ' => 230, 'ٞ' => 230, 'ٟ' => 220, 'ٰ' => 35, 'ۖ' => 230, 'ۗ' => 230, 'ۘ' => 230, 'ۙ' => 230, 'ۚ' => 230, 'ۛ' => 230, 'ۜ' => 230, '۟' => 230, '۠' => 230, 'ۡ' => 230, 'ۢ' => 230, 'ۣ' => 220, 'ۤ' => 230, 'ۧ' => 230, 'ۨ' => 230, '۪' => 220, '۫' => 230, '۬' => 230, 'ۭ' => 220, 'ܑ' => 36, 'ܰ' => 230, 'ܱ' => 220, 'ܲ' => 230, 'ܳ' => 230, 'ܴ' => 220, 'ܵ' => 230, 'ܶ' => 230, 'ܷ' => 220, 'ܸ' => 220, 'ܹ' => 220, 'ܺ' => 230, 'ܻ' => 220, 'ܼ' => 220, 'ܽ' => 230, 'ܾ' => 220, 'ܿ' => 230, '݀' => 230, '݁' => 230, '݂' => 220, '݃' => 230, '݄' => 220, '݅' => 230, '݆' => 220, '݇' => 230, '݈' => 220, '݉' => 230, '݊' => 230, '߫' => 230, '߬' => 230, '߭' => 230, '߮' => 230, '߯' => 230, '߰' => 230, '߱' => 230, '߲' => 220, '߳' => 230, '߽' => 220, 'ࠖ' => 230, 'ࠗ' => 230, '࠘' => 230, '࠙' => 230, 'ࠛ' => 230, 'ࠜ' => 230, 'ࠝ' => 230, 'ࠞ' => 230, 'ࠟ' => 230, 'ࠠ' => 230, 'ࠡ' => 230, 'ࠢ' => 230, 'ࠣ' => 230, 'ࠥ' => 230, 'ࠦ' => 230, 'ࠧ' => 230, 'ࠩ' => 230, 'ࠪ' => 230, 'ࠫ' => 230, 'ࠬ' => 230, '࠭' => 230, '࡙' => 220, '࡚' => 220, '࡛' => 220, '࣓' => 220, 'ࣔ' => 230, 'ࣕ' => 230, 'ࣖ' => 230, 'ࣗ' => 230, 'ࣘ' => 230, 'ࣙ' => 230, 'ࣚ' => 230, 'ࣛ' => 230, 'ࣜ' => 230, 'ࣝ' => 230, 'ࣞ' => 230, 'ࣟ' => 230, '࣠' => 230, '࣡' => 230, 'ࣣ' => 220, 'ࣤ' => 230, 'ࣥ' => 230, 'ࣦ' => 220, 'ࣧ' => 230, 'ࣨ' => 230, 'ࣩ' => 220, '࣪' => 230, '࣫' => 230, '࣬' => 230, '࣭' => 220, '࣮' => 220, '࣯' => 220, 'ࣰ' => 27, 'ࣱ' => 28, 'ࣲ' => 29, 'ࣳ' => 230, 'ࣴ' => 230, 'ࣵ' => 230, 'ࣶ' => 220, 'ࣷ' => 230, 'ࣸ' => 230, 'ࣹ' => 220, 'ࣺ' => 220, 'ࣻ' => 230, 'ࣼ' => 230, 'ࣽ' => 230, 'ࣾ' => 230, 'ࣿ' => 230, '़' => 7, '्' => 9, '॑' => 230, '॒' => 220, '॓' => 230, '॔' => 230, '়' => 7, '্' => 9, '৾' => 230, '਼' => 7, '੍' => 9, '઼' => 7, '્' => 9, '଼' => 7, '୍' => 9, '்' => 9, '్' => 9, 'ౕ' => 84, 'ౖ' => 91, '಼' => 7, '್' => 9, '഻' => 9, '഼' => 9, '്' => 9, '්' => 9, 'ุ' => 103, 'ู' => 103, 'ฺ' => 9, '่' => 107, '้' => 107, '๊' => 107, '๋' => 107, 'ຸ' => 118, 'ູ' => 118, '຺' => 9, '່' => 122, '້' => 122, '໊' => 122, '໋' => 122, '༘' => 220, '༙' => 220, '༵' => 220, '༷' => 220, '༹' => 216, 'ཱ' => 129, 'ི' => 130, 'ུ' => 132, 'ེ' => 130, 'ཻ' => 130, 'ོ' => 130, 'ཽ' => 130, 'ྀ' => 130, 'ྂ' => 230, 'ྃ' => 230, '྄' => 9, '྆' => 230, '྇' => 230, '࿆' => 220, '့' => 7, '္' => 9, '်' => 9, 'ႍ' => 220, '፝' => 230, '፞' => 230, '፟' => 230, '᜔' => 9, '᜴' => 9, '្' => 9, '៝' => 230, 'ᢩ' => 228, '᤹' => 222, '᤺' => 230, '᤻' => 220, 'ᨗ' => 230, 'ᨘ' => 220, '᩠' => 9, '᩵' => 230, '᩶' => 230, '᩷' => 230, '᩸' => 230, '᩹' => 230, '᩺' => 230, '᩻' => 230, '᩼' => 230, '᩿' => 220, '᪰' => 230, '᪱' => 230, '᪲' => 230, '᪳' => 230, '᪴' => 230, '᪵' => 220, '᪶' => 220, '᪷' => 220, '᪸' => 220, '᪹' => 220, '᪺' => 220, '᪻' => 230, '᪼' => 230, '᪽' => 220, 'ᪿ' => 220, 'ᫀ' => 220, '᬴' => 7, '᭄' => 9, '᭫' => 230, '᭬' => 220, '᭭' => 230, '᭮' => 230, '᭯' => 230, '᭰' => 230, '᭱' => 230, '᭲' => 230, '᭳' => 230, '᮪' => 9, '᮫' => 9, '᯦' => 7, '᯲' => 9, '᯳' => 9, '᰷' => 7, '᳐' => 230, '᳑' => 230, '᳒' => 230, '᳔' => 1, '᳕' => 220, '᳖' => 220, '᳗' => 220, '᳘' => 220, '᳙' => 220, '᳚' => 230, '᳛' => 230, '᳜' => 220, '᳝' => 220, '᳞' => 220, '᳟' => 220, '᳠' => 230, '᳢' => 1, '᳣' => 1, '᳤' => 1, '᳥' => 1, '᳦' => 1, '᳧' => 1, '᳨' => 1, '᳭' => 220, '᳴' => 230, '᳸' => 230, '᳹' => 230, '᷀' => 230, '᷁' => 230, '᷂' => 220, '᷃' => 230, '᷄' => 230, '᷅' => 230, '᷆' => 230, '᷇' => 230, '᷈' => 230, '᷉' => 230, '᷊' => 220, '᷋' => 230, '᷌' => 230, '᷍' => 234, '᷎' => 214, '᷏' => 220, '᷐' => 202, '᷑' => 230, '᷒' => 230, 'ᷓ' => 230, 'ᷔ' => 230, 'ᷕ' => 230, 'ᷖ' => 230, 'ᷗ' => 230, 'ᷘ' => 230, 'ᷙ' => 230, 'ᷚ' => 230, 'ᷛ' => 230, 'ᷜ' => 230, 'ᷝ' => 230, 'ᷞ' => 230, 'ᷟ' => 230, 'ᷠ' => 230, 'ᷡ' => 230, 'ᷢ' => 230, 'ᷣ' => 230, 'ᷤ' => 230, 'ᷥ' => 230, 'ᷦ' => 230, 'ᷧ' => 230, 'ᷨ' => 230, 'ᷩ' => 230, 'ᷪ' => 230, 'ᷫ' => 230, 'ᷬ' => 230, 'ᷭ' => 230, 'ᷮ' => 230, 'ᷯ' => 230, 'ᷰ' => 230, 'ᷱ' => 230, 'ᷲ' => 230, 'ᷳ' => 230, 'ᷴ' => 230, '᷵' => 230, '᷶' => 232, '᷷' => 228, '᷸' => 228, '᷹' => 220, '᷻' => 230, '᷼' => 233, '᷽' => 220, '᷾' => 230, '᷿' => 220, '⃐' => 230, '⃑' => 230, '⃒' => 1, '⃓' => 1, '⃔' => 230, '⃕' => 230, '⃖' => 230, '⃗' => 230, '⃘' => 1, '⃙' => 1, '⃚' => 1, '⃛' => 230, '⃜' => 230, '⃡' => 230, '⃥' => 1, '⃦' => 1, '⃧' => 230, '⃨' => 220, '⃩' => 230, '⃪' => 1, '⃫' => 1, '⃬' => 220, '⃭' => 220, '⃮' => 220, '⃯' => 220, '⃰' => 230, '⳯' => 230, '⳰' => 230, '⳱' => 230, '⵿' => 9, 'ⷠ' => 230, 'ⷡ' => 230, 'ⷢ' => 230, 'ⷣ' => 230, 'ⷤ' => 230, 'ⷥ' => 230, 'ⷦ' => 230, 'ⷧ' => 230, 'ⷨ' => 230, 'ⷩ' => 230, 'ⷪ' => 230, 'ⷫ' => 230, 'ⷬ' => 230, 'ⷭ' => 230, 'ⷮ' => 230, 'ⷯ' => 230, 'ⷰ' => 230, 'ⷱ' => 230, 'ⷲ' => 230, 'ⷳ' => 230, 'ⷴ' => 230, 'ⷵ' => 230, 'ⷶ' => 230, 'ⷷ' => 230, 'ⷸ' => 230, 'ⷹ' => 230, 'ⷺ' => 230, 'ⷻ' => 230, 'ⷼ' => 230, 'ⷽ' => 230, 'ⷾ' => 230, 'ⷿ' => 230, '〪' => 218, '〫' => 228, '〬' => 232, '〭' => 222, '〮' => 224, '〯' => 224, '゙' => 8, '゚' => 8, '꙯' => 230, 'ꙴ' => 230, 'ꙵ' => 230, 'ꙶ' => 230, 'ꙷ' => 230, 'ꙸ' => 230, 'ꙹ' => 230, 'ꙺ' => 230, 'ꙻ' => 230, '꙼' => 230, '꙽' => 230, 'ꚞ' => 230, 'ꚟ' => 230, '꛰' => 230, '꛱' => 230, '꠆' => 9, '꠬' => 9, '꣄' => 9, '꣠' => 230, '꣡' => 230, '꣢' => 230, '꣣' => 230, '꣤' => 230, '꣥' => 230, '꣦' => 230, '꣧' => 230, '꣨' => 230, '꣩' => 230, '꣪' => 230, '꣫' => 230, '꣬' => 230, '꣭' => 230, '꣮' => 230, '꣯' => 230, '꣰' => 230, '꣱' => 230, '꤫' => 220, '꤬' => 220, '꤭' => 220, '꥓' => 9, '꦳' => 7, '꧀' => 9, 'ꪰ' => 230, 'ꪲ' => 230, 'ꪳ' => 230, 'ꪴ' => 220, 'ꪷ' => 230, 'ꪸ' => 230, 'ꪾ' => 230, '꪿' => 230, '꫁' => 230, '꫶' => 9, '꯭' => 9, 'ﬞ' => 26, '︠' => 230, '︡' => 230, '︢' => 230, '︣' => 230, '︤' => 230, '︥' => 230, '︦' => 230, '︧' => 220, '︨' => 220, '︩' => 220, '︪' => 220, '︫' => 220, '︬' => 220, '︭' => 220, '︮' => 230, '︯' => 230, '𐇽' => 220, '𐋠' => 220, '𐍶' => 230, '𐍷' => 230, '𐍸' => 230, '𐍹' => 230, '𐍺' => 230, '𐨍' => 220, '𐨏' => 230, '𐨸' => 230, '𐨹' => 1, '𐨺' => 220, '𐨿' => 9, '𐫥' => 230, '𐫦' => 220, '𐴤' => 230, '𐴥' => 230, '𐴦' => 230, '𐴧' => 230, '𐺫' => 230, '𐺬' => 230, '𐽆' => 220, '𐽇' => 220, '𐽈' => 230, '𐽉' => 230, '𐽊' => 230, '𐽋' => 220, '𐽌' => 230, '𐽍' => 220, '𐽎' => 220, '𐽏' => 220, '𐽐' => 220, '𑁆' => 9, '𑁿' => 9, '𑂹' => 9, '𑂺' => 7, '𑄀' => 230, '𑄁' => 230, '𑄂' => 230, '𑄳' => 9, '𑄴' => 9, '𑅳' => 7, '𑇀' => 9, '𑇊' => 7, '𑈵' => 9, '𑈶' => 7, '𑋩' => 7, '𑋪' => 9, '𑌻' => 7, '𑌼' => 7, '𑍍' => 9, '𑍦' => 230, '𑍧' => 230, '𑍨' => 230, '𑍩' => 230, '𑍪' => 230, '𑍫' => 230, '𑍬' => 230, '𑍰' => 230, '𑍱' => 230, '𑍲' => 230, '𑍳' => 230, '𑍴' => 230, '𑑂' => 9, '𑑆' => 7, '𑑞' => 230, '𑓂' => 9, '𑓃' => 7, '𑖿' => 9, '𑗀' => 7, '𑘿' => 9, '𑚶' => 9, '𑚷' => 7, '𑜫' => 9, '𑠹' => 9, '𑠺' => 7, '𑤽' => 9, '𑤾' => 9, '𑥃' => 7, '𑧠' => 9, '𑨴' => 9, '𑩇' => 9, '𑪙' => 9, '𑰿' => 9, '𑵂' => 7, '𑵄' => 9, '𑵅' => 9, '𑶗' => 9, '𖫰' => 1, '𖫱' => 1, '𖫲' => 1, '𖫳' => 1, '𖫴' => 1, '𖬰' => 230, '𖬱' => 230, '𖬲' => 230, '𖬳' => 230, '𖬴' => 230, '𖬵' => 230, '𖬶' => 230, '𖿰' => 6, '𖿱' => 6, '𛲞' => 1, '𝅥' => 216, '𝅦' => 216, '𝅧' => 1, '𝅨' => 1, '𝅩' => 1, '𝅭' => 226, '𝅮' => 216, '𝅯' => 216, '𝅰' => 216, '𝅱' => 216, '𝅲' => 216, '𝅻' => 220, '𝅼' => 220, '𝅽' => 220, '𝅾' => 220, '𝅿' => 220, '𝆀' => 220, '𝆁' => 220, '𝆂' => 220, '𝆅' => 230, '𝆆' => 230, '𝆇' => 230, '𝆈' => 230, '𝆉' => 230, '𝆊' => 220, '𝆋' => 220, '𝆪' => 230, '𝆫' => 230, '𝆬' => 230, '𝆭' => 230, '𝉂' => 230, '𝉃' => 230, '𝉄' => 230, '𞀀' => 230, '𞀁' => 230, '𞀂' => 230, '𞀃' => 230, '𞀄' => 230, '𞀅' => 230, '𞀆' => 230, '𞀈' => 230, '𞀉' => 230, '𞀊' => 230, '𞀋' => 230, '𞀌' => 230, '𞀍' => 230, '𞀎' => 230, '𞀏' => 230, '𞀐' => 230, '𞀑' => 230, '𞀒' => 230, '𞀓' => 230, '𞀔' => 230, '𞀕' => 230, '𞀖' => 230, '𞀗' => 230, '𞀘' => 230, '𞀛' => 230, '𞀜' => 230, '𞀝' => 230, '𞀞' => 230, '𞀟' => 230, '𞀠' => 230, '𞀡' => 230, '𞀣' => 230, '𞀤' => 230, '𞀦' => 230, '𞀧' => 230, '𞀨' => 230, '𞀩' => 230, '𞀪' => 230, '𞄰' => 230, '𞄱' => 230, '𞄲' => 230, '𞄳' => 230, '𞄴' => 230, '𞄵' => 230, '𞄶' => 230, '𞋬' => 230, '𞋭' => 230, '𞋮' => 230, '𞋯' => 230, '𞣐' => 220, '𞣑' => 220, '𞣒' => 220, '𞣓' => 220, '𞣔' => 220, '𞣕' => 220, '𞣖' => 220, '𞥄' => 230, '𞥅' => 230, '𞥆' => 230, '𞥇' => 230, '𞥈' => 230, '𞥉' => 230, '𞥊' => 7); 'À', 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', 'Ü' => 'Ü', 'Ý' => 'Ý', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'ÿ' => 'ÿ', 'Ā' => 'Ā', 'ā' => 'ā', 'Ă' => 'Ă', 'ă' => 'ă', 'Ą' => 'Ą', 'ą' => 'ą', 'Ć' => 'Ć', 'ć' => 'ć', 'Ĉ' => 'Ĉ', 'ĉ' => 'ĉ', 'Ċ' => 'Ċ', 'ċ' => 'ċ', 'Č' => 'Č', 'č' => 'č', 'Ď' => 'Ď', 'ď' => 'ď', 'Ē' => 'Ē', 'ē' => 'ē', 'Ĕ' => 'Ĕ', 'ĕ' => 'ĕ', 'Ė' => 'Ė', 'ė' => 'ė', 'Ę' => 'Ę', 'ę' => 'ę', 'Ě' => 'Ě', 'ě' => 'ě', 'Ĝ' => 'Ĝ', 'ĝ' => 'ĝ', 'Ğ' => 'Ğ', 'ğ' => 'ğ', 'Ġ' => 'Ġ', 'ġ' => 'ġ', 'Ģ' => 'Ģ', 'ģ' => 'ģ', 'Ĥ' => 'Ĥ', 'ĥ' => 'ĥ', 'Ĩ' => 'Ĩ', 'ĩ' => 'ĩ', 'Ī' => 'Ī', 'ī' => 'ī', 'Ĭ' => 'Ĭ', 'ĭ' => 'ĭ', 'Į' => 'Į', 'į' => 'į', 'İ' => 'İ', 'Ĵ' => 'Ĵ', 'ĵ' => 'ĵ', 'Ķ' => 'Ķ', 'ķ' => 'ķ', 'Ĺ' => 'Ĺ', 'ĺ' => 'ĺ', 'Ļ' => 'Ļ', 'ļ' => 'ļ', 'Ľ' => 'Ľ', 'ľ' => 'ľ', 'Ń' => 'Ń', 'ń' => 'ń', 'Ņ' => 'Ņ', 'ņ' => 'ņ', 'Ň' => 'Ň', 'ň' => 'ň', 'Ō' => 'Ō', 'ō' => 'ō', 'Ŏ' => 'Ŏ', 'ŏ' => 'ŏ', 'Ő' => 'Ő', 'ő' => 'ő', 'Ŕ' => 'Ŕ', 'ŕ' => 'ŕ', 'Ŗ' => 'Ŗ', 'ŗ' => 'ŗ', 'Ř' => 'Ř', 'ř' => 'ř', 'Ś' => 'Ś', 'ś' => 'ś', 'Ŝ' => 'Ŝ', 'ŝ' => 'ŝ', 'Ş' => 'Ş', 'ş' => 'ş', 'Š' => 'Š', 'š' => 'š', 'Ţ' => 'Ţ', 'ţ' => 'ţ', 'Ť' => 'Ť', 'ť' => 'ť', 'Ũ' => 'Ũ', 'ũ' => 'ũ', 'Ū' => 'Ū', 'ū' => 'ū', 'Ŭ' => 'Ŭ', 'ŭ' => 'ŭ', 'Ů' => 'Ů', 'ů' => 'ů', 'Ű' => 'Ű', 'ű' => 'ű', 'Ų' => 'Ų', 'ų' => 'ų', 'Ŵ' => 'Ŵ', 'ŵ' => 'ŵ', 'Ŷ' => 'Ŷ', 'ŷ' => 'ŷ', 'Ÿ' => 'Ÿ', 'Ź' => 'Ź', 'ź' => 'ź', 'Ż' => 'Ż', 'ż' => 'ż', 'Ž' => 'Ž', 'ž' => 'ž', 'Ơ' => 'Ơ', 'ơ' => 'ơ', 'Ư' => 'Ư', 'ư' => 'ư', 'Ǎ' => 'Ǎ', 'ǎ' => 'ǎ', 'Ǐ' => 'Ǐ', 'ǐ' => 'ǐ', 'Ǒ' => 'Ǒ', 'ǒ' => 'ǒ', 'Ǔ' => 'Ǔ', 'ǔ' => 'ǔ', 'Ǖ' => 'Ǖ', 'ǖ' => 'ǖ', 'Ǘ' => 'Ǘ', 'ǘ' => 'ǘ', 'Ǚ' => 'Ǚ', 'ǚ' => 'ǚ', 'Ǜ' => 'Ǜ', 'ǜ' => 'ǜ', 'Ǟ' => 'Ǟ', 'ǟ' => 'ǟ', 'Ǡ' => 'Ǡ', 'ǡ' => 'ǡ', 'Ǣ' => 'Ǣ', 'ǣ' => 'ǣ', 'Ǧ' => 'Ǧ', 'ǧ' => 'ǧ', 'Ǩ' => 'Ǩ', 'ǩ' => 'ǩ', 'Ǫ' => 'Ǫ', 'ǫ' => 'ǫ', 'Ǭ' => 'Ǭ', 'ǭ' => 'ǭ', 'Ǯ' => 'Ǯ', 'ǯ' => 'ǯ', 'ǰ' => 'ǰ', 'Ǵ' => 'Ǵ', 'ǵ' => 'ǵ', 'Ǹ' => 'Ǹ', 'ǹ' => 'ǹ', 'Ǻ' => 'Ǻ', 'ǻ' => 'ǻ', 'Ǽ' => 'Ǽ', 'ǽ' => 'ǽ', 'Ǿ' => 'Ǿ', 'ǿ' => 'ǿ', 'Ȁ' => 'Ȁ', 'ȁ' => 'ȁ', 'Ȃ' => 'Ȃ', 'ȃ' => 'ȃ', 'Ȅ' => 'Ȅ', 'ȅ' => 'ȅ', 'Ȇ' => 'Ȇ', 'ȇ' => 'ȇ', 'Ȉ' => 'Ȉ', 'ȉ' => 'ȉ', 'Ȋ' => 'Ȋ', 'ȋ' => 'ȋ', 'Ȍ' => 'Ȍ', 'ȍ' => 'ȍ', 'Ȏ' => 'Ȏ', 'ȏ' => 'ȏ', 'Ȑ' => 'Ȑ', 'ȑ' => 'ȑ', 'Ȓ' => 'Ȓ', 'ȓ' => 'ȓ', 'Ȕ' => 'Ȕ', 'ȕ' => 'ȕ', 'Ȗ' => 'Ȗ', 'ȗ' => 'ȗ', 'Ș' => 'Ș', 'ș' => 'ș', 'Ț' => 'Ț', 'ț' => 'ț', 'Ȟ' => 'Ȟ', 'ȟ' => 'ȟ', 'Ȧ' => 'Ȧ', 'ȧ' => 'ȧ', 'Ȩ' => 'Ȩ', 'ȩ' => 'ȩ', 'Ȫ' => 'Ȫ', 'ȫ' => 'ȫ', 'Ȭ' => 'Ȭ', 'ȭ' => 'ȭ', 'Ȯ' => 'Ȯ', 'ȯ' => 'ȯ', 'Ȱ' => 'Ȱ', 'ȱ' => 'ȱ', 'Ȳ' => 'Ȳ', 'ȳ' => 'ȳ', '΅' => '΅', 'Ά' => 'Ά', 'Έ' => 'Έ', 'Ή' => 'Ή', 'Ί' => 'Ί', 'Ό' => 'Ό', 'Ύ' => 'Ύ', 'Ώ' => 'Ώ', 'ΐ' => 'ΐ', 'Ϊ' => 'Ϊ', 'Ϋ' => 'Ϋ', 'ά' => 'ά', 'έ' => 'έ', 'ή' => 'ή', 'ί' => 'ί', 'ΰ' => 'ΰ', 'ϊ' => 'ϊ', 'ϋ' => 'ϋ', 'ό' => 'ό', 'ύ' => 'ύ', 'ώ' => 'ώ', 'ϓ' => 'ϓ', 'ϔ' => 'ϔ', 'Ѐ' => 'Ѐ', 'Ё' => 'Ё', 'Ѓ' => 'Ѓ', 'Ї' => 'Ї', 'Ќ' => 'Ќ', 'Ѝ' => 'Ѝ', 'Ў' => 'Ў', 'Й' => 'Й', 'й' => 'й', 'ѐ' => 'ѐ', 'ё' => 'ё', 'ѓ' => 'ѓ', 'ї' => 'ї', 'ќ' => 'ќ', 'ѝ' => 'ѝ', 'ў' => 'ў', 'Ѷ' => 'Ѷ', 'ѷ' => 'ѷ', 'Ӂ' => 'Ӂ', 'ӂ' => 'ӂ', 'Ӑ' => 'Ӑ', 'ӑ' => 'ӑ', 'Ӓ' => 'Ӓ', 'ӓ' => 'ӓ', 'Ӗ' => 'Ӗ', 'ӗ' => 'ӗ', 'Ӛ' => 'Ӛ', 'ӛ' => 'ӛ', 'Ӝ' => 'Ӝ', 'ӝ' => 'ӝ', 'Ӟ' => 'Ӟ', 'ӟ' => 'ӟ', 'Ӣ' => 'Ӣ', 'ӣ' => 'ӣ', 'Ӥ' => 'Ӥ', 'ӥ' => 'ӥ', 'Ӧ' => 'Ӧ', 'ӧ' => 'ӧ', 'Ӫ' => 'Ӫ', 'ӫ' => 'ӫ', 'Ӭ' => 'Ӭ', 'ӭ' => 'ӭ', 'Ӯ' => 'Ӯ', 'ӯ' => 'ӯ', 'Ӱ' => 'Ӱ', 'ӱ' => 'ӱ', 'Ӳ' => 'Ӳ', 'ӳ' => 'ӳ', 'Ӵ' => 'Ӵ', 'ӵ' => 'ӵ', 'Ӹ' => 'Ӹ', 'ӹ' => 'ӹ', 'آ' => 'آ', 'أ' => 'أ', 'ؤ' => 'ؤ', 'إ' => 'إ', 'ئ' => 'ئ', 'ۀ' => 'ۀ', 'ۂ' => 'ۂ', 'ۓ' => 'ۓ', 'ऩ' => 'ऩ', 'ऱ' => 'ऱ', 'ऴ' => 'ऴ', 'ো' => 'ো', 'ৌ' => 'ৌ', 'ୈ' => 'ୈ', 'ୋ' => 'ୋ', 'ୌ' => 'ୌ', 'ஔ' => 'ஔ', 'ொ' => 'ொ', 'ோ' => 'ோ', 'ௌ' => 'ௌ', 'ై' => 'ై', 'ೀ' => 'ೀ', 'ೇ' => 'ೇ', 'ೈ' => 'ೈ', 'ೊ' => 'ೊ', 'ೋ' => 'ೋ', 'ൊ' => 'ൊ', 'ോ' => 'ോ', 'ൌ' => 'ൌ', 'ේ' => 'ේ', 'ො' => 'ො', 'ෝ' => 'ෝ', 'ෞ' => 'ෞ', 'ဦ' => 'ဦ', 'ᬆ' => 'ᬆ', 'ᬈ' => 'ᬈ', 'ᬊ' => 'ᬊ', 'ᬌ' => 'ᬌ', 'ᬎ' => 'ᬎ', 'ᬒ' => 'ᬒ', 'ᬻ' => 'ᬻ', 'ᬽ' => 'ᬽ', 'ᭀ' => 'ᭀ', 'ᭁ' => 'ᭁ', 'ᭃ' => 'ᭃ', 'Ḁ' => 'Ḁ', 'ḁ' => 'ḁ', 'Ḃ' => 'Ḃ', 'ḃ' => 'ḃ', 'Ḅ' => 'Ḅ', 'ḅ' => 'ḅ', 'Ḇ' => 'Ḇ', 'ḇ' => 'ḇ', 'Ḉ' => 'Ḉ', 'ḉ' => 'ḉ', 'Ḋ' => 'Ḋ', 'ḋ' => 'ḋ', 'Ḍ' => 'Ḍ', 'ḍ' => 'ḍ', 'Ḏ' => 'Ḏ', 'ḏ' => 'ḏ', 'Ḑ' => 'Ḑ', 'ḑ' => 'ḑ', 'Ḓ' => 'Ḓ', 'ḓ' => 'ḓ', 'Ḕ' => 'Ḕ', 'ḕ' => 'ḕ', 'Ḗ' => 'Ḗ', 'ḗ' => 'ḗ', 'Ḙ' => 'Ḙ', 'ḙ' => 'ḙ', 'Ḛ' => 'Ḛ', 'ḛ' => 'ḛ', 'Ḝ' => 'Ḝ', 'ḝ' => 'ḝ', 'Ḟ' => 'Ḟ', 'ḟ' => 'ḟ', 'Ḡ' => 'Ḡ', 'ḡ' => 'ḡ', 'Ḣ' => 'Ḣ', 'ḣ' => 'ḣ', 'Ḥ' => 'Ḥ', 'ḥ' => 'ḥ', 'Ḧ' => 'Ḧ', 'ḧ' => 'ḧ', 'Ḩ' => 'Ḩ', 'ḩ' => 'ḩ', 'Ḫ' => 'Ḫ', 'ḫ' => 'ḫ', 'Ḭ' => 'Ḭ', 'ḭ' => 'ḭ', 'Ḯ' => 'Ḯ', 'ḯ' => 'ḯ', 'Ḱ' => 'Ḱ', 'ḱ' => 'ḱ', 'Ḳ' => 'Ḳ', 'ḳ' => 'ḳ', 'Ḵ' => 'Ḵ', 'ḵ' => 'ḵ', 'Ḷ' => 'Ḷ', 'ḷ' => 'ḷ', 'Ḹ' => 'Ḹ', 'ḹ' => 'ḹ', 'Ḻ' => 'Ḻ', 'ḻ' => 'ḻ', 'Ḽ' => 'Ḽ', 'ḽ' => 'ḽ', 'Ḿ' => 'Ḿ', 'ḿ' => 'ḿ', 'Ṁ' => 'Ṁ', 'ṁ' => 'ṁ', 'Ṃ' => 'Ṃ', 'ṃ' => 'ṃ', 'Ṅ' => 'Ṅ', 'ṅ' => 'ṅ', 'Ṇ' => 'Ṇ', 'ṇ' => 'ṇ', 'Ṉ' => 'Ṉ', 'ṉ' => 'ṉ', 'Ṋ' => 'Ṋ', 'ṋ' => 'ṋ', 'Ṍ' => 'Ṍ', 'ṍ' => 'ṍ', 'Ṏ' => 'Ṏ', 'ṏ' => 'ṏ', 'Ṑ' => 'Ṑ', 'ṑ' => 'ṑ', 'Ṓ' => 'Ṓ', 'ṓ' => 'ṓ', 'Ṕ' => 'Ṕ', 'ṕ' => 'ṕ', 'Ṗ' => 'Ṗ', 'ṗ' => 'ṗ', 'Ṙ' => 'Ṙ', 'ṙ' => 'ṙ', 'Ṛ' => 'Ṛ', 'ṛ' => 'ṛ', 'Ṝ' => 'Ṝ', 'ṝ' => 'ṝ', 'Ṟ' => 'Ṟ', 'ṟ' => 'ṟ', 'Ṡ' => 'Ṡ', 'ṡ' => 'ṡ', 'Ṣ' => 'Ṣ', 'ṣ' => 'ṣ', 'Ṥ' => 'Ṥ', 'ṥ' => 'ṥ', 'Ṧ' => 'Ṧ', 'ṧ' => 'ṧ', 'Ṩ' => 'Ṩ', 'ṩ' => 'ṩ', 'Ṫ' => 'Ṫ', 'ṫ' => 'ṫ', 'Ṭ' => 'Ṭ', 'ṭ' => 'ṭ', 'Ṯ' => 'Ṯ', 'ṯ' => 'ṯ', 'Ṱ' => 'Ṱ', 'ṱ' => 'ṱ', 'Ṳ' => 'Ṳ', 'ṳ' => 'ṳ', 'Ṵ' => 'Ṵ', 'ṵ' => 'ṵ', 'Ṷ' => 'Ṷ', 'ṷ' => 'ṷ', 'Ṹ' => 'Ṹ', 'ṹ' => 'ṹ', 'Ṻ' => 'Ṻ', 'ṻ' => 'ṻ', 'Ṽ' => 'Ṽ', 'ṽ' => 'ṽ', 'Ṿ' => 'Ṿ', 'ṿ' => 'ṿ', 'Ẁ' => 'Ẁ', 'ẁ' => 'ẁ', 'Ẃ' => 'Ẃ', 'ẃ' => 'ẃ', 'Ẅ' => 'Ẅ', 'ẅ' => 'ẅ', 'Ẇ' => 'Ẇ', 'ẇ' => 'ẇ', 'Ẉ' => 'Ẉ', 'ẉ' => 'ẉ', 'Ẋ' => 'Ẋ', 'ẋ' => 'ẋ', 'Ẍ' => 'Ẍ', 'ẍ' => 'ẍ', 'Ẏ' => 'Ẏ', 'ẏ' => 'ẏ', 'Ẑ' => 'Ẑ', 'ẑ' => 'ẑ', 'Ẓ' => 'Ẓ', 'ẓ' => 'ẓ', 'Ẕ' => 'Ẕ', 'ẕ' => 'ẕ', 'ẖ' => 'ẖ', 'ẗ' => 'ẗ', 'ẘ' => 'ẘ', 'ẙ' => 'ẙ', 'ẛ' => 'ẛ', 'Ạ' => 'Ạ', 'ạ' => 'ạ', 'Ả' => 'Ả', 'ả' => 'ả', 'Ấ' => 'Ấ', 'ấ' => 'ấ', 'Ầ' => 'Ầ', 'ầ' => 'ầ', 'Ẩ' => 'Ẩ', 'ẩ' => 'ẩ', 'Ẫ' => 'Ẫ', 'ẫ' => 'ẫ', 'Ậ' => 'Ậ', 'ậ' => 'ậ', 'Ắ' => 'Ắ', 'ắ' => 'ắ', 'Ằ' => 'Ằ', 'ằ' => 'ằ', 'Ẳ' => 'Ẳ', 'ẳ' => 'ẳ', 'Ẵ' => 'Ẵ', 'ẵ' => 'ẵ', 'Ặ' => 'Ặ', 'ặ' => 'ặ', 'Ẹ' => 'Ẹ', 'ẹ' => 'ẹ', 'Ẻ' => 'Ẻ', 'ẻ' => 'ẻ', 'Ẽ' => 'Ẽ', 'ẽ' => 'ẽ', 'Ế' => 'Ế', 'ế' => 'ế', 'Ề' => 'Ề', 'ề' => 'ề', 'Ể' => 'Ể', 'ể' => 'ể', 'Ễ' => 'Ễ', 'ễ' => 'ễ', 'Ệ' => 'Ệ', 'ệ' => 'ệ', 'Ỉ' => 'Ỉ', 'ỉ' => 'ỉ', 'Ị' => 'Ị', 'ị' => 'ị', 'Ọ' => 'Ọ', 'ọ' => 'ọ', 'Ỏ' => 'Ỏ', 'ỏ' => 'ỏ', 'Ố' => 'Ố', 'ố' => 'ố', 'Ồ' => 'Ồ', 'ồ' => 'ồ', 'Ổ' => 'Ổ', 'ổ' => 'ổ', 'Ỗ' => 'Ỗ', 'ỗ' => 'ỗ', 'Ộ' => 'Ộ', 'ộ' => 'ộ', 'Ớ' => 'Ớ', 'ớ' => 'ớ', 'Ờ' => 'Ờ', 'ờ' => 'ờ', 'Ở' => 'Ở', 'ở' => 'ở', 'Ỡ' => 'Ỡ', 'ỡ' => 'ỡ', 'Ợ' => 'Ợ', 'ợ' => 'ợ', 'Ụ' => 'Ụ', 'ụ' => 'ụ', 'Ủ' => 'Ủ', 'ủ' => 'ủ', 'Ứ' => 'Ứ', 'ứ' => 'ứ', 'Ừ' => 'Ừ', 'ừ' => 'ừ', 'Ử' => 'Ử', 'ử' => 'ử', 'Ữ' => 'Ữ', 'ữ' => 'ữ', 'Ự' => 'Ự', 'ự' => 'ự', 'Ỳ' => 'Ỳ', 'ỳ' => 'ỳ', 'Ỵ' => 'Ỵ', 'ỵ' => 'ỵ', 'Ỷ' => 'Ỷ', 'ỷ' => 'ỷ', 'Ỹ' => 'Ỹ', 'ỹ' => 'ỹ', 'ἀ' => 'ἀ', 'ἁ' => 'ἁ', 'ἂ' => 'ἂ', 'ἃ' => 'ἃ', 'ἄ' => 'ἄ', 'ἅ' => 'ἅ', 'ἆ' => 'ἆ', 'ἇ' => 'ἇ', 'Ἀ' => 'Ἀ', 'Ἁ' => 'Ἁ', 'Ἂ' => 'Ἂ', 'Ἃ' => 'Ἃ', 'Ἄ' => 'Ἄ', 'Ἅ' => 'Ἅ', 'Ἆ' => 'Ἆ', 'Ἇ' => 'Ἇ', 'ἐ' => 'ἐ', 'ἑ' => 'ἑ', 'ἒ' => 'ἒ', 'ἓ' => 'ἓ', 'ἔ' => 'ἔ', 'ἕ' => 'ἕ', 'Ἐ' => 'Ἐ', 'Ἑ' => 'Ἑ', 'Ἒ' => 'Ἒ', 'Ἓ' => 'Ἓ', 'Ἔ' => 'Ἔ', 'Ἕ' => 'Ἕ', 'ἠ' => 'ἠ', 'ἡ' => 'ἡ', 'ἢ' => 'ἢ', 'ἣ' => 'ἣ', 'ἤ' => 'ἤ', 'ἥ' => 'ἥ', 'ἦ' => 'ἦ', 'ἧ' => 'ἧ', 'Ἠ' => 'Ἠ', 'Ἡ' => 'Ἡ', 'Ἢ' => 'Ἢ', 'Ἣ' => 'Ἣ', 'Ἤ' => 'Ἤ', 'Ἥ' => 'Ἥ', 'Ἦ' => 'Ἦ', 'Ἧ' => 'Ἧ', 'ἰ' => 'ἰ', 'ἱ' => 'ἱ', 'ἲ' => 'ἲ', 'ἳ' => 'ἳ', 'ἴ' => 'ἴ', 'ἵ' => 'ἵ', 'ἶ' => 'ἶ', 'ἷ' => 'ἷ', 'Ἰ' => 'Ἰ', 'Ἱ' => 'Ἱ', 'Ἲ' => 'Ἲ', 'Ἳ' => 'Ἳ', 'Ἴ' => 'Ἴ', 'Ἵ' => 'Ἵ', 'Ἶ' => 'Ἶ', 'Ἷ' => 'Ἷ', 'ὀ' => 'ὀ', 'ὁ' => 'ὁ', 'ὂ' => 'ὂ', 'ὃ' => 'ὃ', 'ὄ' => 'ὄ', 'ὅ' => 'ὅ', 'Ὀ' => 'Ὀ', 'Ὁ' => 'Ὁ', 'Ὂ' => 'Ὂ', 'Ὃ' => 'Ὃ', 'Ὄ' => 'Ὄ', 'Ὅ' => 'Ὅ', 'ὐ' => 'ὐ', 'ὑ' => 'ὑ', 'ὒ' => 'ὒ', 'ὓ' => 'ὓ', 'ὔ' => 'ὔ', 'ὕ' => 'ὕ', 'ὖ' => 'ὖ', 'ὗ' => 'ὗ', 'Ὑ' => 'Ὑ', 'Ὓ' => 'Ὓ', 'Ὕ' => 'Ὕ', 'Ὗ' => 'Ὗ', 'ὠ' => 'ὠ', 'ὡ' => 'ὡ', 'ὢ' => 'ὢ', 'ὣ' => 'ὣ', 'ὤ' => 'ὤ', 'ὥ' => 'ὥ', 'ὦ' => 'ὦ', 'ὧ' => 'ὧ', 'Ὠ' => 'Ὠ', 'Ὡ' => 'Ὡ', 'Ὢ' => 'Ὢ', 'Ὣ' => 'Ὣ', 'Ὤ' => 'Ὤ', 'Ὥ' => 'Ὥ', 'Ὦ' => 'Ὦ', 'Ὧ' => 'Ὧ', 'ὰ' => 'ὰ', 'ὲ' => 'ὲ', 'ὴ' => 'ὴ', 'ὶ' => 'ὶ', 'ὸ' => 'ὸ', 'ὺ' => 'ὺ', 'ὼ' => 'ὼ', 'ᾀ' => 'ᾀ', 'ᾁ' => 'ᾁ', 'ᾂ' => 'ᾂ', 'ᾃ' => 'ᾃ', 'ᾄ' => 'ᾄ', 'ᾅ' => 'ᾅ', 'ᾆ' => 'ᾆ', 'ᾇ' => 'ᾇ', 'ᾈ' => 'ᾈ', 'ᾉ' => 'ᾉ', 'ᾊ' => 'ᾊ', 'ᾋ' => 'ᾋ', 'ᾌ' => 'ᾌ', 'ᾍ' => 'ᾍ', 'ᾎ' => 'ᾎ', 'ᾏ' => 'ᾏ', 'ᾐ' => 'ᾐ', 'ᾑ' => 'ᾑ', 'ᾒ' => 'ᾒ', 'ᾓ' => 'ᾓ', 'ᾔ' => 'ᾔ', 'ᾕ' => 'ᾕ', 'ᾖ' => 'ᾖ', 'ᾗ' => 'ᾗ', 'ᾘ' => 'ᾘ', 'ᾙ' => 'ᾙ', 'ᾚ' => 'ᾚ', 'ᾛ' => 'ᾛ', 'ᾜ' => 'ᾜ', 'ᾝ' => 'ᾝ', 'ᾞ' => 'ᾞ', 'ᾟ' => 'ᾟ', 'ᾠ' => 'ᾠ', 'ᾡ' => 'ᾡ', 'ᾢ' => 'ᾢ', 'ᾣ' => 'ᾣ', 'ᾤ' => 'ᾤ', 'ᾥ' => 'ᾥ', 'ᾦ' => 'ᾦ', 'ᾧ' => 'ᾧ', 'ᾨ' => 'ᾨ', 'ᾩ' => 'ᾩ', 'ᾪ' => 'ᾪ', 'ᾫ' => 'ᾫ', 'ᾬ' => 'ᾬ', 'ᾭ' => 'ᾭ', 'ᾮ' => 'ᾮ', 'ᾯ' => 'ᾯ', 'ᾰ' => 'ᾰ', 'ᾱ' => 'ᾱ', 'ᾲ' => 'ᾲ', 'ᾳ' => 'ᾳ', 'ᾴ' => 'ᾴ', 'ᾶ' => 'ᾶ', 'ᾷ' => 'ᾷ', 'Ᾰ' => 'Ᾰ', 'Ᾱ' => 'Ᾱ', 'Ὰ' => 'Ὰ', 'ᾼ' => 'ᾼ', '῁' => '῁', 'ῂ' => 'ῂ', 'ῃ' => 'ῃ', 'ῄ' => 'ῄ', 'ῆ' => 'ῆ', 'ῇ' => 'ῇ', 'Ὲ' => 'Ὲ', 'Ὴ' => 'Ὴ', 'ῌ' => 'ῌ', '῍' => '῍', '῎' => '῎', '῏' => '῏', 'ῐ' => 'ῐ', 'ῑ' => 'ῑ', 'ῒ' => 'ῒ', 'ῖ' => 'ῖ', 'ῗ' => 'ῗ', 'Ῐ' => 'Ῐ', 'Ῑ' => 'Ῑ', 'Ὶ' => 'Ὶ', '῝' => '῝', '῞' => '῞', '῟' => '῟', 'ῠ' => 'ῠ', 'ῡ' => 'ῡ', 'ῢ' => 'ῢ', 'ῤ' => 'ῤ', 'ῥ' => 'ῥ', 'ῦ' => 'ῦ', 'ῧ' => 'ῧ', 'Ῠ' => 'Ῠ', 'Ῡ' => 'Ῡ', 'Ὺ' => 'Ὺ', 'Ῥ' => 'Ῥ', '῭' => '῭', 'ῲ' => 'ῲ', 'ῳ' => 'ῳ', 'ῴ' => 'ῴ', 'ῶ' => 'ῶ', 'ῷ' => 'ῷ', 'Ὸ' => 'Ὸ', 'Ὼ' => 'Ὼ', 'ῼ' => 'ῼ', '↚' => '↚', '↛' => '↛', '↮' => '↮', '⇍' => '⇍', '⇎' => '⇎', '⇏' => '⇏', '∄' => '∄', '∉' => '∉', '∌' => '∌', '∤' => '∤', '∦' => '∦', '≁' => '≁', '≄' => '≄', '≇' => '≇', '≉' => '≉', '≠' => '≠', '≢' => '≢', '≭' => '≭', '≮' => '≮', '≯' => '≯', '≰' => '≰', '≱' => '≱', '≴' => '≴', '≵' => '≵', '≸' => '≸', '≹' => '≹', '⊀' => '⊀', '⊁' => '⊁', '⊄' => '⊄', '⊅' => '⊅', '⊈' => '⊈', '⊉' => '⊉', '⊬' => '⊬', '⊭' => '⊭', '⊮' => '⊮', '⊯' => '⊯', '⋠' => '⋠', '⋡' => '⋡', '⋢' => '⋢', '⋣' => '⋣', '⋪' => '⋪', '⋫' => '⋫', '⋬' => '⋬', '⋭' => '⋭', 'が' => 'が', 'ぎ' => 'ぎ', 'ぐ' => 'ぐ', 'げ' => 'げ', 'ご' => 'ご', 'ざ' => 'ざ', 'じ' => 'じ', 'ず' => 'ず', 'ぜ' => 'ぜ', 'ぞ' => 'ぞ', 'だ' => 'だ', 'ぢ' => 'ぢ', 'づ' => 'づ', 'で' => 'で', 'ど' => 'ど', 'ば' => 'ば', 'ぱ' => 'ぱ', 'び' => 'び', 'ぴ' => 'ぴ', 'ぶ' => 'ぶ', 'ぷ' => 'ぷ', 'べ' => 'べ', 'ぺ' => 'ぺ', 'ぼ' => 'ぼ', 'ぽ' => 'ぽ', 'ゔ' => 'ゔ', 'ゞ' => 'ゞ', 'ガ' => 'ガ', 'ギ' => 'ギ', 'グ' => 'グ', 'ゲ' => 'ゲ', 'ゴ' => 'ゴ', 'ザ' => 'ザ', 'ジ' => 'ジ', 'ズ' => 'ズ', 'ゼ' => 'ゼ', 'ゾ' => 'ゾ', 'ダ' => 'ダ', 'ヂ' => 'ヂ', 'ヅ' => 'ヅ', 'デ' => 'デ', 'ド' => 'ド', 'バ' => 'バ', 'パ' => 'パ', 'ビ' => 'ビ', 'ピ' => 'ピ', 'ブ' => 'ブ', 'プ' => 'プ', 'ベ' => 'ベ', 'ペ' => 'ペ', 'ボ' => 'ボ', 'ポ' => 'ポ', 'ヴ' => 'ヴ', 'ヷ' => 'ヷ', 'ヸ' => 'ヸ', 'ヹ' => 'ヹ', 'ヺ' => 'ヺ', 'ヾ' => 'ヾ', '𑂚' => '𑂚', '𑂜' => '𑂜', '𑂫' => '𑂫', '𑄮' => '𑄮', '𑄯' => '𑄯', '𑍋' => '𑍋', '𑍌' => '𑍌', '𑒻' => '𑒻', '𑒼' => '𑒼', '𑒾' => '𑒾', '𑖺' => '𑖺', '𑖻' => '𑖻', '𑤸' => '𑤸'); 'À', 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', 'Ü' => 'Ü', 'Ý' => 'Ý', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'ÿ' => 'ÿ', 'Ā' => 'Ā', 'ā' => 'ā', 'Ă' => 'Ă', 'ă' => 'ă', 'Ą' => 'Ą', 'ą' => 'ą', 'Ć' => 'Ć', 'ć' => 'ć', 'Ĉ' => 'Ĉ', 'ĉ' => 'ĉ', 'Ċ' => 'Ċ', 'ċ' => 'ċ', 'Č' => 'Č', 'č' => 'č', 'Ď' => 'Ď', 'ď' => 'ď', 'Ē' => 'Ē', 'ē' => 'ē', 'Ĕ' => 'Ĕ', 'ĕ' => 'ĕ', 'Ė' => 'Ė', 'ė' => 'ė', 'Ę' => 'Ę', 'ę' => 'ę', 'Ě' => 'Ě', 'ě' => 'ě', 'Ĝ' => 'Ĝ', 'ĝ' => 'ĝ', 'Ğ' => 'Ğ', 'ğ' => 'ğ', 'Ġ' => 'Ġ', 'ġ' => 'ġ', 'Ģ' => 'Ģ', 'ģ' => 'ģ', 'Ĥ' => 'Ĥ', 'ĥ' => 'ĥ', 'Ĩ' => 'Ĩ', 'ĩ' => 'ĩ', 'Ī' => 'Ī', 'ī' => 'ī', 'Ĭ' => 'Ĭ', 'ĭ' => 'ĭ', 'Į' => 'Į', 'į' => 'į', 'İ' => 'İ', 'Ĵ' => 'Ĵ', 'ĵ' => 'ĵ', 'Ķ' => 'Ķ', 'ķ' => 'ķ', 'Ĺ' => 'Ĺ', 'ĺ' => 'ĺ', 'Ļ' => 'Ļ', 'ļ' => 'ļ', 'Ľ' => 'Ľ', 'ľ' => 'ľ', 'Ń' => 'Ń', 'ń' => 'ń', 'Ņ' => 'Ņ', 'ņ' => 'ņ', 'Ň' => 'Ň', 'ň' => 'ň', 'Ō' => 'Ō', 'ō' => 'ō', 'Ŏ' => 'Ŏ', 'ŏ' => 'ŏ', 'Ő' => 'Ő', 'ő' => 'ő', 'Ŕ' => 'Ŕ', 'ŕ' => 'ŕ', 'Ŗ' => 'Ŗ', 'ŗ' => 'ŗ', 'Ř' => 'Ř', 'ř' => 'ř', 'Ś' => 'Ś', 'ś' => 'ś', 'Ŝ' => 'Ŝ', 'ŝ' => 'ŝ', 'Ş' => 'Ş', 'ş' => 'ş', 'Š' => 'Š', 'š' => 'š', 'Ţ' => 'Ţ', 'ţ' => 'ţ', 'Ť' => 'Ť', 'ť' => 'ť', 'Ũ' => 'Ũ', 'ũ' => 'ũ', 'Ū' => 'Ū', 'ū' => 'ū', 'Ŭ' => 'Ŭ', 'ŭ' => 'ŭ', 'Ů' => 'Ů', 'ů' => 'ů', 'Ű' => 'Ű', 'ű' => 'ű', 'Ų' => 'Ų', 'ų' => 'ų', 'Ŵ' => 'Ŵ', 'ŵ' => 'ŵ', 'Ŷ' => 'Ŷ', 'ŷ' => 'ŷ', 'Ÿ' => 'Ÿ', 'Ź' => 'Ź', 'ź' => 'ź', 'Ż' => 'Ż', 'ż' => 'ż', 'Ž' => 'Ž', 'ž' => 'ž', 'Ơ' => 'Ơ', 'ơ' => 'ơ', 'Ư' => 'Ư', 'ư' => 'ư', 'Ǎ' => 'Ǎ', 'ǎ' => 'ǎ', 'Ǐ' => 'Ǐ', 'ǐ' => 'ǐ', 'Ǒ' => 'Ǒ', 'ǒ' => 'ǒ', 'Ǔ' => 'Ǔ', 'ǔ' => 'ǔ', 'Ǖ' => 'Ǖ', 'ǖ' => 'ǖ', 'Ǘ' => 'Ǘ', 'ǘ' => 'ǘ', 'Ǚ' => 'Ǚ', 'ǚ' => 'ǚ', 'Ǜ' => 'Ǜ', 'ǜ' => 'ǜ', 'Ǟ' => 'Ǟ', 'ǟ' => 'ǟ', 'Ǡ' => 'Ǡ', 'ǡ' => 'ǡ', 'Ǣ' => 'Ǣ', 'ǣ' => 'ǣ', 'Ǧ' => 'Ǧ', 'ǧ' => 'ǧ', 'Ǩ' => 'Ǩ', 'ǩ' => 'ǩ', 'Ǫ' => 'Ǫ', 'ǫ' => 'ǫ', 'Ǭ' => 'Ǭ', 'ǭ' => 'ǭ', 'Ǯ' => 'Ǯ', 'ǯ' => 'ǯ', 'ǰ' => 'ǰ', 'Ǵ' => 'Ǵ', 'ǵ' => 'ǵ', 'Ǹ' => 'Ǹ', 'ǹ' => 'ǹ', 'Ǻ' => 'Ǻ', 'ǻ' => 'ǻ', 'Ǽ' => 'Ǽ', 'ǽ' => 'ǽ', 'Ǿ' => 'Ǿ', 'ǿ' => 'ǿ', 'Ȁ' => 'Ȁ', 'ȁ' => 'ȁ', 'Ȃ' => 'Ȃ', 'ȃ' => 'ȃ', 'Ȅ' => 'Ȅ', 'ȅ' => 'ȅ', 'Ȇ' => 'Ȇ', 'ȇ' => 'ȇ', 'Ȉ' => 'Ȉ', 'ȉ' => 'ȉ', 'Ȋ' => 'Ȋ', 'ȋ' => 'ȋ', 'Ȍ' => 'Ȍ', 'ȍ' => 'ȍ', 'Ȏ' => 'Ȏ', 'ȏ' => 'ȏ', 'Ȑ' => 'Ȑ', 'ȑ' => 'ȑ', 'Ȓ' => 'Ȓ', 'ȓ' => 'ȓ', 'Ȕ' => 'Ȕ', 'ȕ' => 'ȕ', 'Ȗ' => 'Ȗ', 'ȗ' => 'ȗ', 'Ș' => 'Ș', 'ș' => 'ș', 'Ț' => 'Ț', 'ț' => 'ț', 'Ȟ' => 'Ȟ', 'ȟ' => 'ȟ', 'Ȧ' => 'Ȧ', 'ȧ' => 'ȧ', 'Ȩ' => 'Ȩ', 'ȩ' => 'ȩ', 'Ȫ' => 'Ȫ', 'ȫ' => 'ȫ', 'Ȭ' => 'Ȭ', 'ȭ' => 'ȭ', 'Ȯ' => 'Ȯ', 'ȯ' => 'ȯ', 'Ȱ' => 'Ȱ', 'ȱ' => 'ȱ', 'Ȳ' => 'Ȳ', 'ȳ' => 'ȳ', '̀' => '̀', '́' => '́', '̓' => '̓', '̈́' => '̈́', 'ʹ' => 'ʹ', ';' => ';', '΅' => '΅', 'Ά' => 'Ά', '·' => '·', 'Έ' => 'Έ', 'Ή' => 'Ή', 'Ί' => 'Ί', 'Ό' => 'Ό', 'Ύ' => 'Ύ', 'Ώ' => 'Ώ', 'ΐ' => 'ΐ', 'Ϊ' => 'Ϊ', 'Ϋ' => 'Ϋ', 'ά' => 'ά', 'έ' => 'έ', 'ή' => 'ή', 'ί' => 'ί', 'ΰ' => 'ΰ', 'ϊ' => 'ϊ', 'ϋ' => 'ϋ', 'ό' => 'ό', 'ύ' => 'ύ', 'ώ' => 'ώ', 'ϓ' => 'ϓ', 'ϔ' => 'ϔ', 'Ѐ' => 'Ѐ', 'Ё' => 'Ё', 'Ѓ' => 'Ѓ', 'Ї' => 'Ї', 'Ќ' => 'Ќ', 'Ѝ' => 'Ѝ', 'Ў' => 'Ў', 'Й' => 'Й', 'й' => 'й', 'ѐ' => 'ѐ', 'ё' => 'ё', 'ѓ' => 'ѓ', 'ї' => 'ї', 'ќ' => 'ќ', 'ѝ' => 'ѝ', 'ў' => 'ў', 'Ѷ' => 'Ѷ', 'ѷ' => 'ѷ', 'Ӂ' => 'Ӂ', 'ӂ' => 'ӂ', 'Ӑ' => 'Ӑ', 'ӑ' => 'ӑ', 'Ӓ' => 'Ӓ', 'ӓ' => 'ӓ', 'Ӗ' => 'Ӗ', 'ӗ' => 'ӗ', 'Ӛ' => 'Ӛ', 'ӛ' => 'ӛ', 'Ӝ' => 'Ӝ', 'ӝ' => 'ӝ', 'Ӟ' => 'Ӟ', 'ӟ' => 'ӟ', 'Ӣ' => 'Ӣ', 'ӣ' => 'ӣ', 'Ӥ' => 'Ӥ', 'ӥ' => 'ӥ', 'Ӧ' => 'Ӧ', 'ӧ' => 'ӧ', 'Ӫ' => 'Ӫ', 'ӫ' => 'ӫ', 'Ӭ' => 'Ӭ', 'ӭ' => 'ӭ', 'Ӯ' => 'Ӯ', 'ӯ' => 'ӯ', 'Ӱ' => 'Ӱ', 'ӱ' => 'ӱ', 'Ӳ' => 'Ӳ', 'ӳ' => 'ӳ', 'Ӵ' => 'Ӵ', 'ӵ' => 'ӵ', 'Ӹ' => 'Ӹ', 'ӹ' => 'ӹ', 'آ' => 'آ', 'أ' => 'أ', 'ؤ' => 'ؤ', 'إ' => 'إ', 'ئ' => 'ئ', 'ۀ' => 'ۀ', 'ۂ' => 'ۂ', 'ۓ' => 'ۓ', 'ऩ' => 'ऩ', 'ऱ' => 'ऱ', 'ऴ' => 'ऴ', 'क़' => 'क़', 'ख़' => 'ख़', 'ग़' => 'ग़', 'ज़' => 'ज़', 'ड़' => 'ड़', 'ढ़' => 'ढ़', 'फ़' => 'फ़', 'य़' => 'य़', 'ো' => 'ো', 'ৌ' => 'ৌ', 'ড়' => 'ড়', 'ঢ়' => 'ঢ়', 'য়' => 'য়', 'ਲ਼' => 'ਲ਼', 'ਸ਼' => 'ਸ਼', 'ਖ਼' => 'ਖ਼', 'ਗ਼' => 'ਗ਼', 'ਜ਼' => 'ਜ਼', 'ਫ਼' => 'ਫ਼', 'ୈ' => 'ୈ', 'ୋ' => 'ୋ', 'ୌ' => 'ୌ', 'ଡ଼' => 'ଡ଼', 'ଢ଼' => 'ଢ଼', 'ஔ' => 'ஔ', 'ொ' => 'ொ', 'ோ' => 'ோ', 'ௌ' => 'ௌ', 'ై' => 'ై', 'ೀ' => 'ೀ', 'ೇ' => 'ೇ', 'ೈ' => 'ೈ', 'ೊ' => 'ೊ', 'ೋ' => 'ೋ', 'ൊ' => 'ൊ', 'ോ' => 'ോ', 'ൌ' => 'ൌ', 'ේ' => 'ේ', 'ො' => 'ො', 'ෝ' => 'ෝ', 'ෞ' => 'ෞ', 'གྷ' => 'གྷ', 'ཌྷ' => 'ཌྷ', 'དྷ' => 'དྷ', 'བྷ' => 'བྷ', 'ཛྷ' => 'ཛྷ', 'ཀྵ' => 'ཀྵ', 'ཱི' => 'ཱི', 'ཱུ' => 'ཱུ', 'ྲྀ' => 'ྲྀ', 'ླྀ' => 'ླྀ', 'ཱྀ' => 'ཱྀ', 'ྒྷ' => 'ྒྷ', 'ྜྷ' => 'ྜྷ', 'ྡྷ' => 'ྡྷ', 'ྦྷ' => 'ྦྷ', 'ྫྷ' => 'ྫྷ', 'ྐྵ' => 'ྐྵ', 'ဦ' => 'ဦ', 'ᬆ' => 'ᬆ', 'ᬈ' => 'ᬈ', 'ᬊ' => 'ᬊ', 'ᬌ' => 'ᬌ', 'ᬎ' => 'ᬎ', 'ᬒ' => 'ᬒ', 'ᬻ' => 'ᬻ', 'ᬽ' => 'ᬽ', 'ᭀ' => 'ᭀ', 'ᭁ' => 'ᭁ', 'ᭃ' => 'ᭃ', 'Ḁ' => 'Ḁ', 'ḁ' => 'ḁ', 'Ḃ' => 'Ḃ', 'ḃ' => 'ḃ', 'Ḅ' => 'Ḅ', 'ḅ' => 'ḅ', 'Ḇ' => 'Ḇ', 'ḇ' => 'ḇ', 'Ḉ' => 'Ḉ', 'ḉ' => 'ḉ', 'Ḋ' => 'Ḋ', 'ḋ' => 'ḋ', 'Ḍ' => 'Ḍ', 'ḍ' => 'ḍ', 'Ḏ' => 'Ḏ', 'ḏ' => 'ḏ', 'Ḑ' => 'Ḑ', 'ḑ' => 'ḑ', 'Ḓ' => 'Ḓ', 'ḓ' => 'ḓ', 'Ḕ' => 'Ḕ', 'ḕ' => 'ḕ', 'Ḗ' => 'Ḗ', 'ḗ' => 'ḗ', 'Ḙ' => 'Ḙ', 'ḙ' => 'ḙ', 'Ḛ' => 'Ḛ', 'ḛ' => 'ḛ', 'Ḝ' => 'Ḝ', 'ḝ' => 'ḝ', 'Ḟ' => 'Ḟ', 'ḟ' => 'ḟ', 'Ḡ' => 'Ḡ', 'ḡ' => 'ḡ', 'Ḣ' => 'Ḣ', 'ḣ' => 'ḣ', 'Ḥ' => 'Ḥ', 'ḥ' => 'ḥ', 'Ḧ' => 'Ḧ', 'ḧ' => 'ḧ', 'Ḩ' => 'Ḩ', 'ḩ' => 'ḩ', 'Ḫ' => 'Ḫ', 'ḫ' => 'ḫ', 'Ḭ' => 'Ḭ', 'ḭ' => 'ḭ', 'Ḯ' => 'Ḯ', 'ḯ' => 'ḯ', 'Ḱ' => 'Ḱ', 'ḱ' => 'ḱ', 'Ḳ' => 'Ḳ', 'ḳ' => 'ḳ', 'Ḵ' => 'Ḵ', 'ḵ' => 'ḵ', 'Ḷ' => 'Ḷ', 'ḷ' => 'ḷ', 'Ḹ' => 'Ḹ', 'ḹ' => 'ḹ', 'Ḻ' => 'Ḻ', 'ḻ' => 'ḻ', 'Ḽ' => 'Ḽ', 'ḽ' => 'ḽ', 'Ḿ' => 'Ḿ', 'ḿ' => 'ḿ', 'Ṁ' => 'Ṁ', 'ṁ' => 'ṁ', 'Ṃ' => 'Ṃ', 'ṃ' => 'ṃ', 'Ṅ' => 'Ṅ', 'ṅ' => 'ṅ', 'Ṇ' => 'Ṇ', 'ṇ' => 'ṇ', 'Ṉ' => 'Ṉ', 'ṉ' => 'ṉ', 'Ṋ' => 'Ṋ', 'ṋ' => 'ṋ', 'Ṍ' => 'Ṍ', 'ṍ' => 'ṍ', 'Ṏ' => 'Ṏ', 'ṏ' => 'ṏ', 'Ṑ' => 'Ṑ', 'ṑ' => 'ṑ', 'Ṓ' => 'Ṓ', 'ṓ' => 'ṓ', 'Ṕ' => 'Ṕ', 'ṕ' => 'ṕ', 'Ṗ' => 'Ṗ', 'ṗ' => 'ṗ', 'Ṙ' => 'Ṙ', 'ṙ' => 'ṙ', 'Ṛ' => 'Ṛ', 'ṛ' => 'ṛ', 'Ṝ' => 'Ṝ', 'ṝ' => 'ṝ', 'Ṟ' => 'Ṟ', 'ṟ' => 'ṟ', 'Ṡ' => 'Ṡ', 'ṡ' => 'ṡ', 'Ṣ' => 'Ṣ', 'ṣ' => 'ṣ', 'Ṥ' => 'Ṥ', 'ṥ' => 'ṥ', 'Ṧ' => 'Ṧ', 'ṧ' => 'ṧ', 'Ṩ' => 'Ṩ', 'ṩ' => 'ṩ', 'Ṫ' => 'Ṫ', 'ṫ' => 'ṫ', 'Ṭ' => 'Ṭ', 'ṭ' => 'ṭ', 'Ṯ' => 'Ṯ', 'ṯ' => 'ṯ', 'Ṱ' => 'Ṱ', 'ṱ' => 'ṱ', 'Ṳ' => 'Ṳ', 'ṳ' => 'ṳ', 'Ṵ' => 'Ṵ', 'ṵ' => 'ṵ', 'Ṷ' => 'Ṷ', 'ṷ' => 'ṷ', 'Ṹ' => 'Ṹ', 'ṹ' => 'ṹ', 'Ṻ' => 'Ṻ', 'ṻ' => 'ṻ', 'Ṽ' => 'Ṽ', 'ṽ' => 'ṽ', 'Ṿ' => 'Ṿ', 'ṿ' => 'ṿ', 'Ẁ' => 'Ẁ', 'ẁ' => 'ẁ', 'Ẃ' => 'Ẃ', 'ẃ' => 'ẃ', 'Ẅ' => 'Ẅ', 'ẅ' => 'ẅ', 'Ẇ' => 'Ẇ', 'ẇ' => 'ẇ', 'Ẉ' => 'Ẉ', 'ẉ' => 'ẉ', 'Ẋ' => 'Ẋ', 'ẋ' => 'ẋ', 'Ẍ' => 'Ẍ', 'ẍ' => 'ẍ', 'Ẏ' => 'Ẏ', 'ẏ' => 'ẏ', 'Ẑ' => 'Ẑ', 'ẑ' => 'ẑ', 'Ẓ' => 'Ẓ', 'ẓ' => 'ẓ', 'Ẕ' => 'Ẕ', 'ẕ' => 'ẕ', 'ẖ' => 'ẖ', 'ẗ' => 'ẗ', 'ẘ' => 'ẘ', 'ẙ' => 'ẙ', 'ẛ' => 'ẛ', 'Ạ' => 'Ạ', 'ạ' => 'ạ', 'Ả' => 'Ả', 'ả' => 'ả', 'Ấ' => 'Ấ', 'ấ' => 'ấ', 'Ầ' => 'Ầ', 'ầ' => 'ầ', 'Ẩ' => 'Ẩ', 'ẩ' => 'ẩ', 'Ẫ' => 'Ẫ', 'ẫ' => 'ẫ', 'Ậ' => 'Ậ', 'ậ' => 'ậ', 'Ắ' => 'Ắ', 'ắ' => 'ắ', 'Ằ' => 'Ằ', 'ằ' => 'ằ', 'Ẳ' => 'Ẳ', 'ẳ' => 'ẳ', 'Ẵ' => 'Ẵ', 'ẵ' => 'ẵ', 'Ặ' => 'Ặ', 'ặ' => 'ặ', 'Ẹ' => 'Ẹ', 'ẹ' => 'ẹ', 'Ẻ' => 'Ẻ', 'ẻ' => 'ẻ', 'Ẽ' => 'Ẽ', 'ẽ' => 'ẽ', 'Ế' => 'Ế', 'ế' => 'ế', 'Ề' => 'Ề', 'ề' => 'ề', 'Ể' => 'Ể', 'ể' => 'ể', 'Ễ' => 'Ễ', 'ễ' => 'ễ', 'Ệ' => 'Ệ', 'ệ' => 'ệ', 'Ỉ' => 'Ỉ', 'ỉ' => 'ỉ', 'Ị' => 'Ị', 'ị' => 'ị', 'Ọ' => 'Ọ', 'ọ' => 'ọ', 'Ỏ' => 'Ỏ', 'ỏ' => 'ỏ', 'Ố' => 'Ố', 'ố' => 'ố', 'Ồ' => 'Ồ', 'ồ' => 'ồ', 'Ổ' => 'Ổ', 'ổ' => 'ổ', 'Ỗ' => 'Ỗ', 'ỗ' => 'ỗ', 'Ộ' => 'Ộ', 'ộ' => 'ộ', 'Ớ' => 'Ớ', 'ớ' => 'ớ', 'Ờ' => 'Ờ', 'ờ' => 'ờ', 'Ở' => 'Ở', 'ở' => 'ở', 'Ỡ' => 'Ỡ', 'ỡ' => 'ỡ', 'Ợ' => 'Ợ', 'ợ' => 'ợ', 'Ụ' => 'Ụ', 'ụ' => 'ụ', 'Ủ' => 'Ủ', 'ủ' => 'ủ', 'Ứ' => 'Ứ', 'ứ' => 'ứ', 'Ừ' => 'Ừ', 'ừ' => 'ừ', 'Ử' => 'Ử', 'ử' => 'ử', 'Ữ' => 'Ữ', 'ữ' => 'ữ', 'Ự' => 'Ự', 'ự' => 'ự', 'Ỳ' => 'Ỳ', 'ỳ' => 'ỳ', 'Ỵ' => 'Ỵ', 'ỵ' => 'ỵ', 'Ỷ' => 'Ỷ', 'ỷ' => 'ỷ', 'Ỹ' => 'Ỹ', 'ỹ' => 'ỹ', 'ἀ' => 'ἀ', 'ἁ' => 'ἁ', 'ἂ' => 'ἂ', 'ἃ' => 'ἃ', 'ἄ' => 'ἄ', 'ἅ' => 'ἅ', 'ἆ' => 'ἆ', 'ἇ' => 'ἇ', 'Ἀ' => 'Ἀ', 'Ἁ' => 'Ἁ', 'Ἂ' => 'Ἂ', 'Ἃ' => 'Ἃ', 'Ἄ' => 'Ἄ', 'Ἅ' => 'Ἅ', 'Ἆ' => 'Ἆ', 'Ἇ' => 'Ἇ', 'ἐ' => 'ἐ', 'ἑ' => 'ἑ', 'ἒ' => 'ἒ', 'ἓ' => 'ἓ', 'ἔ' => 'ἔ', 'ἕ' => 'ἕ', 'Ἐ' => 'Ἐ', 'Ἑ' => 'Ἑ', 'Ἒ' => 'Ἒ', 'Ἓ' => 'Ἓ', 'Ἔ' => 'Ἔ', 'Ἕ' => 'Ἕ', 'ἠ' => 'ἠ', 'ἡ' => 'ἡ', 'ἢ' => 'ἢ', 'ἣ' => 'ἣ', 'ἤ' => 'ἤ', 'ἥ' => 'ἥ', 'ἦ' => 'ἦ', 'ἧ' => 'ἧ', 'Ἠ' => 'Ἠ', 'Ἡ' => 'Ἡ', 'Ἢ' => 'Ἢ', 'Ἣ' => 'Ἣ', 'Ἤ' => 'Ἤ', 'Ἥ' => 'Ἥ', 'Ἦ' => 'Ἦ', 'Ἧ' => 'Ἧ', 'ἰ' => 'ἰ', 'ἱ' => 'ἱ', 'ἲ' => 'ἲ', 'ἳ' => 'ἳ', 'ἴ' => 'ἴ', 'ἵ' => 'ἵ', 'ἶ' => 'ἶ', 'ἷ' => 'ἷ', 'Ἰ' => 'Ἰ', 'Ἱ' => 'Ἱ', 'Ἲ' => 'Ἲ', 'Ἳ' => 'Ἳ', 'Ἴ' => 'Ἴ', 'Ἵ' => 'Ἵ', 'Ἶ' => 'Ἶ', 'Ἷ' => 'Ἷ', 'ὀ' => 'ὀ', 'ὁ' => 'ὁ', 'ὂ' => 'ὂ', 'ὃ' => 'ὃ', 'ὄ' => 'ὄ', 'ὅ' => 'ὅ', 'Ὀ' => 'Ὀ', 'Ὁ' => 'Ὁ', 'Ὂ' => 'Ὂ', 'Ὃ' => 'Ὃ', 'Ὄ' => 'Ὄ', 'Ὅ' => 'Ὅ', 'ὐ' => 'ὐ', 'ὑ' => 'ὑ', 'ὒ' => 'ὒ', 'ὓ' => 'ὓ', 'ὔ' => 'ὔ', 'ὕ' => 'ὕ', 'ὖ' => 'ὖ', 'ὗ' => 'ὗ', 'Ὑ' => 'Ὑ', 'Ὓ' => 'Ὓ', 'Ὕ' => 'Ὕ', 'Ὗ' => 'Ὗ', 'ὠ' => 'ὠ', 'ὡ' => 'ὡ', 'ὢ' => 'ὢ', 'ὣ' => 'ὣ', 'ὤ' => 'ὤ', 'ὥ' => 'ὥ', 'ὦ' => 'ὦ', 'ὧ' => 'ὧ', 'Ὠ' => 'Ὠ', 'Ὡ' => 'Ὡ', 'Ὢ' => 'Ὢ', 'Ὣ' => 'Ὣ', 'Ὤ' => 'Ὤ', 'Ὥ' => 'Ὥ', 'Ὦ' => 'Ὦ', 'Ὧ' => 'Ὧ', 'ὰ' => 'ὰ', 'ά' => 'ά', 'ὲ' => 'ὲ', 'έ' => 'έ', 'ὴ' => 'ὴ', 'ή' => 'ή', 'ὶ' => 'ὶ', 'ί' => 'ί', 'ὸ' => 'ὸ', 'ό' => 'ό', 'ὺ' => 'ὺ', 'ύ' => 'ύ', 'ὼ' => 'ὼ', 'ώ' => 'ώ', 'ᾀ' => 'ᾀ', 'ᾁ' => 'ᾁ', 'ᾂ' => 'ᾂ', 'ᾃ' => 'ᾃ', 'ᾄ' => 'ᾄ', 'ᾅ' => 'ᾅ', 'ᾆ' => 'ᾆ', 'ᾇ' => 'ᾇ', 'ᾈ' => 'ᾈ', 'ᾉ' => 'ᾉ', 'ᾊ' => 'ᾊ', 'ᾋ' => 'ᾋ', 'ᾌ' => 'ᾌ', 'ᾍ' => 'ᾍ', 'ᾎ' => 'ᾎ', 'ᾏ' => 'ᾏ', 'ᾐ' => 'ᾐ', 'ᾑ' => 'ᾑ', 'ᾒ' => 'ᾒ', 'ᾓ' => 'ᾓ', 'ᾔ' => 'ᾔ', 'ᾕ' => 'ᾕ', 'ᾖ' => 'ᾖ', 'ᾗ' => 'ᾗ', 'ᾘ' => 'ᾘ', 'ᾙ' => 'ᾙ', 'ᾚ' => 'ᾚ', 'ᾛ' => 'ᾛ', 'ᾜ' => 'ᾜ', 'ᾝ' => 'ᾝ', 'ᾞ' => 'ᾞ', 'ᾟ' => 'ᾟ', 'ᾠ' => 'ᾠ', 'ᾡ' => 'ᾡ', 'ᾢ' => 'ᾢ', 'ᾣ' => 'ᾣ', 'ᾤ' => 'ᾤ', 'ᾥ' => 'ᾥ', 'ᾦ' => 'ᾦ', 'ᾧ' => 'ᾧ', 'ᾨ' => 'ᾨ', 'ᾩ' => 'ᾩ', 'ᾪ' => 'ᾪ', 'ᾫ' => 'ᾫ', 'ᾬ' => 'ᾬ', 'ᾭ' => 'ᾭ', 'ᾮ' => 'ᾮ', 'ᾯ' => 'ᾯ', 'ᾰ' => 'ᾰ', 'ᾱ' => 'ᾱ', 'ᾲ' => 'ᾲ', 'ᾳ' => 'ᾳ', 'ᾴ' => 'ᾴ', 'ᾶ' => 'ᾶ', 'ᾷ' => 'ᾷ', 'Ᾰ' => 'Ᾰ', 'Ᾱ' => 'Ᾱ', 'Ὰ' => 'Ὰ', 'Ά' => 'Ά', 'ᾼ' => 'ᾼ', 'ι' => 'ι', '῁' => '῁', 'ῂ' => 'ῂ', 'ῃ' => 'ῃ', 'ῄ' => 'ῄ', 'ῆ' => 'ῆ', 'ῇ' => 'ῇ', 'Ὲ' => 'Ὲ', 'Έ' => 'Έ', 'Ὴ' => 'Ὴ', 'Ή' => 'Ή', 'ῌ' => 'ῌ', '῍' => '῍', '῎' => '῎', '῏' => '῏', 'ῐ' => 'ῐ', 'ῑ' => 'ῑ', 'ῒ' => 'ῒ', 'ΐ' => 'ΐ', 'ῖ' => 'ῖ', 'ῗ' => 'ῗ', 'Ῐ' => 'Ῐ', 'Ῑ' => 'Ῑ', 'Ὶ' => 'Ὶ', 'Ί' => 'Ί', '῝' => '῝', '῞' => '῞', '῟' => '῟', 'ῠ' => 'ῠ', 'ῡ' => 'ῡ', 'ῢ' => 'ῢ', 'ΰ' => 'ΰ', 'ῤ' => 'ῤ', 'ῥ' => 'ῥ', 'ῦ' => 'ῦ', 'ῧ' => 'ῧ', 'Ῠ' => 'Ῠ', 'Ῡ' => 'Ῡ', 'Ὺ' => 'Ὺ', 'Ύ' => 'Ύ', 'Ῥ' => 'Ῥ', '῭' => '῭', '΅' => '΅', '`' => '`', 'ῲ' => 'ῲ', 'ῳ' => 'ῳ', 'ῴ' => 'ῴ', 'ῶ' => 'ῶ', 'ῷ' => 'ῷ', 'Ὸ' => 'Ὸ', 'Ό' => 'Ό', 'Ὼ' => 'Ὼ', 'Ώ' => 'Ώ', 'ῼ' => 'ῼ', '´' => '´', ' ' => ' ', ' ' => ' ', 'Ω' => 'Ω', 'K' => 'K', 'Å' => 'Å', '↚' => '↚', '↛' => '↛', '↮' => '↮', '⇍' => '⇍', '⇎' => '⇎', '⇏' => '⇏', '∄' => '∄', '∉' => '∉', '∌' => '∌', '∤' => '∤', '∦' => '∦', '≁' => '≁', '≄' => '≄', '≇' => '≇', '≉' => '≉', '≠' => '≠', '≢' => '≢', '≭' => '≭', '≮' => '≮', '≯' => '≯', '≰' => '≰', '≱' => '≱', '≴' => '≴', '≵' => '≵', '≸' => '≸', '≹' => '≹', '⊀' => '⊀', '⊁' => '⊁', '⊄' => '⊄', '⊅' => '⊅', '⊈' => '⊈', '⊉' => '⊉', '⊬' => '⊬', '⊭' => '⊭', '⊮' => '⊮', '⊯' => '⊯', '⋠' => '⋠', '⋡' => '⋡', '⋢' => '⋢', '⋣' => '⋣', '⋪' => '⋪', '⋫' => '⋫', '⋬' => '⋬', '⋭' => '⋭', '〈' => '〈', '〉' => '〉', '⫝̸' => '⫝̸', 'が' => 'が', 'ぎ' => 'ぎ', 'ぐ' => 'ぐ', 'げ' => 'げ', 'ご' => 'ご', 'ざ' => 'ざ', 'じ' => 'じ', 'ず' => 'ず', 'ぜ' => 'ぜ', 'ぞ' => 'ぞ', 'だ' => 'だ', 'ぢ' => 'ぢ', 'づ' => 'づ', 'で' => 'で', 'ど' => 'ど', 'ば' => 'ば', 'ぱ' => 'ぱ', 'び' => 'び', 'ぴ' => 'ぴ', 'ぶ' => 'ぶ', 'ぷ' => 'ぷ', 'べ' => 'べ', 'ぺ' => 'ぺ', 'ぼ' => 'ぼ', 'ぽ' => 'ぽ', 'ゔ' => 'ゔ', 'ゞ' => 'ゞ', 'ガ' => 'ガ', 'ギ' => 'ギ', 'グ' => 'グ', 'ゲ' => 'ゲ', 'ゴ' => 'ゴ', 'ザ' => 'ザ', 'ジ' => 'ジ', 'ズ' => 'ズ', 'ゼ' => 'ゼ', 'ゾ' => 'ゾ', 'ダ' => 'ダ', 'ヂ' => 'ヂ', 'ヅ' => 'ヅ', 'デ' => 'デ', 'ド' => 'ド', 'バ' => 'バ', 'パ' => 'パ', 'ビ' => 'ビ', 'ピ' => 'ピ', 'ブ' => 'ブ', 'プ' => 'プ', 'ベ' => 'ベ', 'ペ' => 'ペ', 'ボ' => 'ボ', 'ポ' => 'ポ', 'ヴ' => 'ヴ', 'ヷ' => 'ヷ', 'ヸ' => 'ヸ', 'ヹ' => 'ヹ', 'ヺ' => 'ヺ', 'ヾ' => 'ヾ', '豈' => '豈', '更' => '更', '車' => '車', '賈' => '賈', '滑' => '滑', '串' => '串', '句' => '句', '龜' => '龜', '龜' => '龜', '契' => '契', '金' => '金', '喇' => '喇', '奈' => '奈', '懶' => '懶', '癩' => '癩', '羅' => '羅', '蘿' => '蘿', '螺' => '螺', '裸' => '裸', '邏' => '邏', '樂' => '樂', '洛' => '洛', '烙' => '烙', '珞' => '珞', '落' => '落', '酪' => '酪', '駱' => '駱', '亂' => '亂', '卵' => '卵', '欄' => '欄', '爛' => '爛', '蘭' => '蘭', '鸞' => '鸞', '嵐' => '嵐', '濫' => '濫', '藍' => '藍', '襤' => '襤', '拉' => '拉', '臘' => '臘', '蠟' => '蠟', '廊' => '廊', '朗' => '朗', '浪' => '浪', '狼' => '狼', '郎' => '郎', '來' => '來', '冷' => '冷', '勞' => '勞', '擄' => '擄', '櫓' => '櫓', '爐' => '爐', '盧' => '盧', '老' => '老', '蘆' => '蘆', '虜' => '虜', '路' => '路', '露' => '露', '魯' => '魯', '鷺' => '鷺', '碌' => '碌', '祿' => '祿', '綠' => '綠', '菉' => '菉', '錄' => '錄', '鹿' => '鹿', '論' => '論', '壟' => '壟', '弄' => '弄', '籠' => '籠', '聾' => '聾', '牢' => '牢', '磊' => '磊', '賂' => '賂', '雷' => '雷', '壘' => '壘', '屢' => '屢', '樓' => '樓', '淚' => '淚', '漏' => '漏', '累' => '累', '縷' => '縷', '陋' => '陋', '勒' => '勒', '肋' => '肋', '凜' => '凜', '凌' => '凌', '稜' => '稜', '綾' => '綾', '菱' => '菱', '陵' => '陵', '讀' => '讀', '拏' => '拏', '樂' => '樂', '諾' => '諾', '丹' => '丹', '寧' => '寧', '怒' => '怒', '率' => '率', '異' => '異', '北' => '北', '磻' => '磻', '便' => '便', '復' => '復', '不' => '不', '泌' => '泌', '數' => '數', '索' => '索', '參' => '參', '塞' => '塞', '省' => '省', '葉' => '葉', '說' => '說', '殺' => '殺', '辰' => '辰', '沈' => '沈', '拾' => '拾', '若' => '若', '掠' => '掠', '略' => '略', '亮' => '亮', '兩' => '兩', '凉' => '凉', '梁' => '梁', '糧' => '糧', '良' => '良', '諒' => '諒', '量' => '量', '勵' => '勵', '呂' => '呂', '女' => '女', '廬' => '廬', '旅' => '旅', '濾' => '濾', '礪' => '礪', '閭' => '閭', '驪' => '驪', '麗' => '麗', '黎' => '黎', '力' => '力', '曆' => '曆', '歷' => '歷', '轢' => '轢', '年' => '年', '憐' => '憐', '戀' => '戀', '撚' => '撚', '漣' => '漣', '煉' => '煉', '璉' => '璉', '秊' => '秊', '練' => '練', '聯' => '聯', '輦' => '輦', '蓮' => '蓮', '連' => '連', '鍊' => '鍊', '列' => '列', '劣' => '劣', '咽' => '咽', '烈' => '烈', '裂' => '裂', '說' => '說', '廉' => '廉', '念' => '念', '捻' => '捻', '殮' => '殮', '簾' => '簾', '獵' => '獵', '令' => '令', '囹' => '囹', '寧' => '寧', '嶺' => '嶺', '怜' => '怜', '玲' => '玲', '瑩' => '瑩', '羚' => '羚', '聆' => '聆', '鈴' => '鈴', '零' => '零', '靈' => '靈', '領' => '領', '例' => '例', '禮' => '禮', '醴' => '醴', '隸' => '隸', '惡' => '惡', '了' => '了', '僚' => '僚', '寮' => '寮', '尿' => '尿', '料' => '料', '樂' => '樂', '燎' => '燎', '療' => '療', '蓼' => '蓼', '遼' => '遼', '龍' => '龍', '暈' => '暈', '阮' => '阮', '劉' => '劉', '杻' => '杻', '柳' => '柳', '流' => '流', '溜' => '溜', '琉' => '琉', '留' => '留', '硫' => '硫', '紐' => '紐', '類' => '類', '六' => '六', '戮' => '戮', '陸' => '陸', '倫' => '倫', '崙' => '崙', '淪' => '淪', '輪' => '輪', '律' => '律', '慄' => '慄', '栗' => '栗', '率' => '率', '隆' => '隆', '利' => '利', '吏' => '吏', '履' => '履', '易' => '易', '李' => '李', '梨' => '梨', '泥' => '泥', '理' => '理', '痢' => '痢', '罹' => '罹', '裏' => '裏', '裡' => '裡', '里' => '里', '離' => '離', '匿' => '匿', '溺' => '溺', '吝' => '吝', '燐' => '燐', '璘' => '璘', '藺' => '藺', '隣' => '隣', '鱗' => '鱗', '麟' => '麟', '林' => '林', '淋' => '淋', '臨' => '臨', '立' => '立', '笠' => '笠', '粒' => '粒', '狀' => '狀', '炙' => '炙', '識' => '識', '什' => '什', '茶' => '茶', '刺' => '刺', '切' => '切', '度' => '度', '拓' => '拓', '糖' => '糖', '宅' => '宅', '洞' => '洞', '暴' => '暴', '輻' => '輻', '行' => '行', '降' => '降', '見' => '見', '廓' => '廓', '兀' => '兀', '嗀' => '嗀', '塚' => '塚', '晴' => '晴', '凞' => '凞', '猪' => '猪', '益' => '益', '礼' => '礼', '神' => '神', '祥' => '祥', '福' => '福', '靖' => '靖', '精' => '精', '羽' => '羽', '蘒' => '蘒', '諸' => '諸', '逸' => '逸', '都' => '都', '飯' => '飯', '飼' => '飼', '館' => '館', '鶴' => '鶴', '郞' => '郞', '隷' => '隷', '侮' => '侮', '僧' => '僧', '免' => '免', '勉' => '勉', '勤' => '勤', '卑' => '卑', '喝' => '喝', '嘆' => '嘆', '器' => '器', '塀' => '塀', '墨' => '墨', '層' => '層', '屮' => '屮', '悔' => '悔', '慨' => '慨', '憎' => '憎', '懲' => '懲', '敏' => '敏', '既' => '既', '暑' => '暑', '梅' => '梅', '海' => '海', '渚' => '渚', '漢' => '漢', '煮' => '煮', '爫' => '爫', '琢' => '琢', '碑' => '碑', '社' => '社', '祉' => '祉', '祈' => '祈', '祐' => '祐', '祖' => '祖', '祝' => '祝', '禍' => '禍', '禎' => '禎', '穀' => '穀', '突' => '突', '節' => '節', '練' => '練', '縉' => '縉', '繁' => '繁', '署' => '署', '者' => '者', '臭' => '臭', '艹' => '艹', '艹' => '艹', '著' => '著', '褐' => '褐', '視' => '視', '謁' => '謁', '謹' => '謹', '賓' => '賓', '贈' => '贈', '辶' => '辶', '逸' => '逸', '難' => '難', '響' => '響', '頻' => '頻', '恵' => '恵', '𤋮' => '𤋮', '舘' => '舘', '並' => '並', '况' => '况', '全' => '全', '侀' => '侀', '充' => '充', '冀' => '冀', '勇' => '勇', '勺' => '勺', '喝' => '喝', '啕' => '啕', '喙' => '喙', '嗢' => '嗢', '塚' => '塚', '墳' => '墳', '奄' => '奄', '奔' => '奔', '婢' => '婢', '嬨' => '嬨', '廒' => '廒', '廙' => '廙', '彩' => '彩', '徭' => '徭', '惘' => '惘', '慎' => '慎', '愈' => '愈', '憎' => '憎', '慠' => '慠', '懲' => '懲', '戴' => '戴', '揄' => '揄', '搜' => '搜', '摒' => '摒', '敖' => '敖', '晴' => '晴', '朗' => '朗', '望' => '望', '杖' => '杖', '歹' => '歹', '殺' => '殺', '流' => '流', '滛' => '滛', '滋' => '滋', '漢' => '漢', '瀞' => '瀞', '煮' => '煮', '瞧' => '瞧', '爵' => '爵', '犯' => '犯', '猪' => '猪', '瑱' => '瑱', '甆' => '甆', '画' => '画', '瘝' => '瘝', '瘟' => '瘟', '益' => '益', '盛' => '盛', '直' => '直', '睊' => '睊', '着' => '着', '磌' => '磌', '窱' => '窱', '節' => '節', '类' => '类', '絛' => '絛', '練' => '練', '缾' => '缾', '者' => '者', '荒' => '荒', '華' => '華', '蝹' => '蝹', '襁' => '襁', '覆' => '覆', '視' => '視', '調' => '調', '諸' => '諸', '請' => '請', '謁' => '謁', '諾' => '諾', '諭' => '諭', '謹' => '謹', '變' => '變', '贈' => '贈', '輸' => '輸', '遲' => '遲', '醙' => '醙', '鉶' => '鉶', '陼' => '陼', '難' => '難', '靖' => '靖', '韛' => '韛', '響' => '響', '頋' => '頋', '頻' => '頻', '鬒' => '鬒', '龜' => '龜', '𢡊' => '𢡊', '𢡄' => '𢡄', '𣏕' => '𣏕', '㮝' => '㮝', '䀘' => '䀘', '䀹' => '䀹', '𥉉' => '𥉉', '𥳐' => '𥳐', '𧻓' => '𧻓', '齃' => '齃', '龎' => '龎', 'יִ' => 'יִ', 'ײַ' => 'ײַ', 'שׁ' => 'שׁ', 'שׂ' => 'שׂ', 'שּׁ' => 'שּׁ', 'שּׂ' => 'שּׂ', 'אַ' => 'אַ', 'אָ' => 'אָ', 'אּ' => 'אּ', 'בּ' => 'בּ', 'גּ' => 'גּ', 'דּ' => 'דּ', 'הּ' => 'הּ', 'וּ' => 'וּ', 'זּ' => 'זּ', 'טּ' => 'טּ', 'יּ' => 'יּ', 'ךּ' => 'ךּ', 'כּ' => 'כּ', 'לּ' => 'לּ', 'מּ' => 'מּ', 'נּ' => 'נּ', 'סּ' => 'סּ', 'ףּ' => 'ףּ', 'פּ' => 'פּ', 'צּ' => 'צּ', 'קּ' => 'קּ', 'רּ' => 'רּ', 'שּ' => 'שּ', 'תּ' => 'תּ', 'וֹ' => 'וֹ', 'בֿ' => 'בֿ', 'כֿ' => 'כֿ', 'פֿ' => 'פֿ', '𑂚' => '𑂚', '𑂜' => '𑂜', '𑂫' => '𑂫', '𑄮' => '𑄮', '𑄯' => '𑄯', '𑍋' => '𑍋', '𑍌' => '𑍌', '𑒻' => '𑒻', '𑒼' => '𑒼', '𑒾' => '𑒾', '𑖺' => '𑖺', '𑖻' => '𑖻', '𑤸' => '𑤸', '𝅗𝅥' => '𝅗𝅥', '𝅘𝅥' => '𝅘𝅥', '𝅘𝅥𝅮' => '𝅘𝅥𝅮', '𝅘𝅥𝅯' => '𝅘𝅥𝅯', '𝅘𝅥𝅰' => '𝅘𝅥𝅰', '𝅘𝅥𝅱' => '𝅘𝅥𝅱', '𝅘𝅥𝅲' => '𝅘𝅥𝅲', '𝆹𝅥' => '𝆹𝅥', '𝆺𝅥' => '𝆺𝅥', '𝆹𝅥𝅮' => '𝆹𝅥𝅮', '𝆺𝅥𝅮' => '𝆺𝅥𝅮', '𝆹𝅥𝅯' => '𝆹𝅥𝅯', '𝆺𝅥𝅯' => '𝆺𝅥𝅯', '丽' => '丽', '丸' => '丸', '乁' => '乁', '𠄢' => '𠄢', '你' => '你', '侮' => '侮', '侻' => '侻', '倂' => '倂', '偺' => '偺', '備' => '備', '僧' => '僧', '像' => '像', '㒞' => '㒞', '𠘺' => '𠘺', '免' => '免', '兔' => '兔', '兤' => '兤', '具' => '具', '𠔜' => '𠔜', '㒹' => '㒹', '內' => '內', '再' => '再', '𠕋' => '𠕋', '冗' => '冗', '冤' => '冤', '仌' => '仌', '冬' => '冬', '况' => '况', '𩇟' => '𩇟', '凵' => '凵', '刃' => '刃', '㓟' => '㓟', '刻' => '刻', '剆' => '剆', '割' => '割', '剷' => '剷', '㔕' => '㔕', '勇' => '勇', '勉' => '勉', '勤' => '勤', '勺' => '勺', '包' => '包', '匆' => '匆', '北' => '北', '卉' => '卉', '卑' => '卑', '博' => '博', '即' => '即', '卽' => '卽', '卿' => '卿', '卿' => '卿', '卿' => '卿', '𠨬' => '𠨬', '灰' => '灰', '及' => '及', '叟' => '叟', '𠭣' => '𠭣', '叫' => '叫', '叱' => '叱', '吆' => '吆', '咞' => '咞', '吸' => '吸', '呈' => '呈', '周' => '周', '咢' => '咢', '哶' => '哶', '唐' => '唐', '啓' => '啓', '啣' => '啣', '善' => '善', '善' => '善', '喙' => '喙', '喫' => '喫', '喳' => '喳', '嗂' => '嗂', '圖' => '圖', '嘆' => '嘆', '圗' => '圗', '噑' => '噑', '噴' => '噴', '切' => '切', '壮' => '壮', '城' => '城', '埴' => '埴', '堍' => '堍', '型' => '型', '堲' => '堲', '報' => '報', '墬' => '墬', '𡓤' => '𡓤', '売' => '売', '壷' => '壷', '夆' => '夆', '多' => '多', '夢' => '夢', '奢' => '奢', '𡚨' => '𡚨', '𡛪' => '𡛪', '姬' => '姬', '娛' => '娛', '娧' => '娧', '姘' => '姘', '婦' => '婦', '㛮' => '㛮', '㛼' => '㛼', '嬈' => '嬈', '嬾' => '嬾', '嬾' => '嬾', '𡧈' => '𡧈', '寃' => '寃', '寘' => '寘', '寧' => '寧', '寳' => '寳', '𡬘' => '𡬘', '寿' => '寿', '将' => '将', '当' => '当', '尢' => '尢', '㞁' => '㞁', '屠' => '屠', '屮' => '屮', '峀' => '峀', '岍' => '岍', '𡷤' => '𡷤', '嵃' => '嵃', '𡷦' => '𡷦', '嵮' => '嵮', '嵫' => '嵫', '嵼' => '嵼', '巡' => '巡', '巢' => '巢', '㠯' => '㠯', '巽' => '巽', '帨' => '帨', '帽' => '帽', '幩' => '幩', '㡢' => '㡢', '𢆃' => '𢆃', '㡼' => '㡼', '庰' => '庰', '庳' => '庳', '庶' => '庶', '廊' => '廊', '𪎒' => '𪎒', '廾' => '廾', '𢌱' => '𢌱', '𢌱' => '𢌱', '舁' => '舁', '弢' => '弢', '弢' => '弢', '㣇' => '㣇', '𣊸' => '𣊸', '𦇚' => '𦇚', '形' => '形', '彫' => '彫', '㣣' => '㣣', '徚' => '徚', '忍' => '忍', '志' => '志', '忹' => '忹', '悁' => '悁', '㤺' => '㤺', '㤜' => '㤜', '悔' => '悔', '𢛔' => '𢛔', '惇' => '惇', '慈' => '慈', '慌' => '慌', '慎' => '慎', '慌' => '慌', '慺' => '慺', '憎' => '憎', '憲' => '憲', '憤' => '憤', '憯' => '憯', '懞' => '懞', '懲' => '懲', '懶' => '懶', '成' => '成', '戛' => '戛', '扝' => '扝', '抱' => '抱', '拔' => '拔', '捐' => '捐', '𢬌' => '𢬌', '挽' => '挽', '拼' => '拼', '捨' => '捨', '掃' => '掃', '揤' => '揤', '𢯱' => '𢯱', '搢' => '搢', '揅' => '揅', '掩' => '掩', '㨮' => '㨮', '摩' => '摩', '摾' => '摾', '撝' => '撝', '摷' => '摷', '㩬' => '㩬', '敏' => '敏', '敬' => '敬', '𣀊' => '𣀊', '旣' => '旣', '書' => '書', '晉' => '晉', '㬙' => '㬙', '暑' => '暑', '㬈' => '㬈', '㫤' => '㫤', '冒' => '冒', '冕' => '冕', '最' => '最', '暜' => '暜', '肭' => '肭', '䏙' => '䏙', '朗' => '朗', '望' => '望', '朡' => '朡', '杞' => '杞', '杓' => '杓', '𣏃' => '𣏃', '㭉' => '㭉', '柺' => '柺', '枅' => '枅', '桒' => '桒', '梅' => '梅', '𣑭' => '𣑭', '梎' => '梎', '栟' => '栟', '椔' => '椔', '㮝' => '㮝', '楂' => '楂', '榣' => '榣', '槪' => '槪', '檨' => '檨', '𣚣' => '𣚣', '櫛' => '櫛', '㰘' => '㰘', '次' => '次', '𣢧' => '𣢧', '歔' => '歔', '㱎' => '㱎', '歲' => '歲', '殟' => '殟', '殺' => '殺', '殻' => '殻', '𣪍' => '𣪍', '𡴋' => '𡴋', '𣫺' => '𣫺', '汎' => '汎', '𣲼' => '𣲼', '沿' => '沿', '泍' => '泍', '汧' => '汧', '洖' => '洖', '派' => '派', '海' => '海', '流' => '流', '浩' => '浩', '浸' => '浸', '涅' => '涅', '𣴞' => '𣴞', '洴' => '洴', '港' => '港', '湮' => '湮', '㴳' => '㴳', '滋' => '滋', '滇' => '滇', '𣻑' => '𣻑', '淹' => '淹', '潮' => '潮', '𣽞' => '𣽞', '𣾎' => '𣾎', '濆' => '濆', '瀹' => '瀹', '瀞' => '瀞', '瀛' => '瀛', '㶖' => '㶖', '灊' => '灊', '災' => '災', '灷' => '灷', '炭' => '炭', '𠔥' => '𠔥', '煅' => '煅', '𤉣' => '𤉣', '熜' => '熜', '𤎫' => '𤎫', '爨' => '爨', '爵' => '爵', '牐' => '牐', '𤘈' => '𤘈', '犀' => '犀', '犕' => '犕', '𤜵' => '𤜵', '𤠔' => '𤠔', '獺' => '獺', '王' => '王', '㺬' => '㺬', '玥' => '玥', '㺸' => '㺸', '㺸' => '㺸', '瑇' => '瑇', '瑜' => '瑜', '瑱' => '瑱', '璅' => '璅', '瓊' => '瓊', '㼛' => '㼛', '甤' => '甤', '𤰶' => '𤰶', '甾' => '甾', '𤲒' => '𤲒', '異' => '異', '𢆟' => '𢆟', '瘐' => '瘐', '𤾡' => '𤾡', '𤾸' => '𤾸', '𥁄' => '𥁄', '㿼' => '㿼', '䀈' => '䀈', '直' => '直', '𥃳' => '𥃳', '𥃲' => '𥃲', '𥄙' => '𥄙', '𥄳' => '𥄳', '眞' => '眞', '真' => '真', '真' => '真', '睊' => '睊', '䀹' => '䀹', '瞋' => '瞋', '䁆' => '䁆', '䂖' => '䂖', '𥐝' => '𥐝', '硎' => '硎', '碌' => '碌', '磌' => '磌', '䃣' => '䃣', '𥘦' => '𥘦', '祖' => '祖', '𥚚' => '𥚚', '𥛅' => '𥛅', '福' => '福', '秫' => '秫', '䄯' => '䄯', '穀' => '穀', '穊' => '穊', '穏' => '穏', '𥥼' => '𥥼', '𥪧' => '𥪧', '𥪧' => '𥪧', '竮' => '竮', '䈂' => '䈂', '𥮫' => '𥮫', '篆' => '篆', '築' => '築', '䈧' => '䈧', '𥲀' => '𥲀', '糒' => '糒', '䊠' => '䊠', '糨' => '糨', '糣' => '糣', '紀' => '紀', '𥾆' => '𥾆', '絣' => '絣', '䌁' => '䌁', '緇' => '緇', '縂' => '縂', '繅' => '繅', '䌴' => '䌴', '𦈨' => '𦈨', '𦉇' => '𦉇', '䍙' => '䍙', '𦋙' => '𦋙', '罺' => '罺', '𦌾' => '𦌾', '羕' => '羕', '翺' => '翺', '者' => '者', '𦓚' => '𦓚', '𦔣' => '𦔣', '聠' => '聠', '𦖨' => '𦖨', '聰' => '聰', '𣍟' => '𣍟', '䏕' => '䏕', '育' => '育', '脃' => '脃', '䐋' => '䐋', '脾' => '脾', '媵' => '媵', '𦞧' => '𦞧', '𦞵' => '𦞵', '𣎓' => '𣎓', '𣎜' => '𣎜', '舁' => '舁', '舄' => '舄', '辞' => '辞', '䑫' => '䑫', '芑' => '芑', '芋' => '芋', '芝' => '芝', '劳' => '劳', '花' => '花', '芳' => '芳', '芽' => '芽', '苦' => '苦', '𦬼' => '𦬼', '若' => '若', '茝' => '茝', '荣' => '荣', '莭' => '莭', '茣' => '茣', '莽' => '莽', '菧' => '菧', '著' => '著', '荓' => '荓', '菊' => '菊', '菌' => '菌', '菜' => '菜', '𦰶' => '𦰶', '𦵫' => '𦵫', '𦳕' => '𦳕', '䔫' => '䔫', '蓱' => '蓱', '蓳' => '蓳', '蔖' => '蔖', '𧏊' => '𧏊', '蕤' => '蕤', '𦼬' => '𦼬', '䕝' => '䕝', '䕡' => '䕡', '𦾱' => '𦾱', '𧃒' => '𧃒', '䕫' => '䕫', '虐' => '虐', '虜' => '虜', '虧' => '虧', '虩' => '虩', '蚩' => '蚩', '蚈' => '蚈', '蜎' => '蜎', '蛢' => '蛢', '蝹' => '蝹', '蜨' => '蜨', '蝫' => '蝫', '螆' => '螆', '䗗' => '䗗', '蟡' => '蟡', '蠁' => '蠁', '䗹' => '䗹', '衠' => '衠', '衣' => '衣', '𧙧' => '𧙧', '裗' => '裗', '裞' => '裞', '䘵' => '䘵', '裺' => '裺', '㒻' => '㒻', '𧢮' => '𧢮', '𧥦' => '𧥦', '䚾' => '䚾', '䛇' => '䛇', '誠' => '誠', '諭' => '諭', '變' => '變', '豕' => '豕', '𧲨' => '𧲨', '貫' => '貫', '賁' => '賁', '贛' => '贛', '起' => '起', '𧼯' => '𧼯', '𠠄' => '𠠄', '跋' => '跋', '趼' => '趼', '跰' => '跰', '𠣞' => '𠣞', '軔' => '軔', '輸' => '輸', '𨗒' => '𨗒', '𨗭' => '𨗭', '邔' => '邔', '郱' => '郱', '鄑' => '鄑', '𨜮' => '𨜮', '鄛' => '鄛', '鈸' => '鈸', '鋗' => '鋗', '鋘' => '鋘', '鉼' => '鉼', '鏹' => '鏹', '鐕' => '鐕', '𨯺' => '𨯺', '開' => '開', '䦕' => '䦕', '閷' => '閷', '𨵷' => '𨵷', '䧦' => '䧦', '雃' => '雃', '嶲' => '嶲', '霣' => '霣', '𩅅' => '𩅅', '𩈚' => '𩈚', '䩮' => '䩮', '䩶' => '䩶', '韠' => '韠', '𩐊' => '𩐊', '䪲' => '䪲', '𩒖' => '𩒖', '頋' => '頋', '頋' => '頋', '頩' => '頩', '𩖶' => '𩖶', '飢' => '飢', '䬳' => '䬳', '餩' => '餩', '馧' => '馧', '駂' => '駂', '駾' => '駾', '䯎' => '䯎', '𩬰' => '𩬰', '鬒' => '鬒', '鱀' => '鱀', '鳽' => '鳽', '䳎' => '䳎', '䳭' => '䳭', '鵧' => '鵧', '𪃎' => '𪃎', '䳸' => '䳸', '𪄅' => '𪄅', '𪈎' => '𪈎', '𪊑' => '𪊑', '麻' => '麻', '䵖' => '䵖', '黹' => '黹', '黾' => '黾', '鼅' => '鼅', '鼏' => '鼏', '鼖' => '鼖', '鼻' => '鼻', '𪘀' => '𪘀'); ' ', '¨' => ' ̈', 'ª' => 'a', '¯' => ' ̄', '²' => '2', '³' => '3', '´' => ' ́', 'µ' => 'μ', '¸' => ' ̧', '¹' => '1', 'º' => 'o', '¼' => '1⁄4', '½' => '1⁄2', '¾' => '3⁄4', 'IJ' => 'IJ', 'ij' => 'ij', 'Ŀ' => 'L·', 'ŀ' => 'l·', 'ʼn' => 'ʼn', 'ſ' => 's', 'DŽ' => 'DŽ', 'Dž' => 'Dž', 'dž' => 'dž', 'LJ' => 'LJ', 'Lj' => 'Lj', 'lj' => 'lj', 'NJ' => 'NJ', 'Nj' => 'Nj', 'nj' => 'nj', 'DZ' => 'DZ', 'Dz' => 'Dz', 'dz' => 'dz', 'ʰ' => 'h', 'ʱ' => 'ɦ', 'ʲ' => 'j', 'ʳ' => 'r', 'ʴ' => 'ɹ', 'ʵ' => 'ɻ', 'ʶ' => 'ʁ', 'ʷ' => 'w', 'ʸ' => 'y', '˘' => ' ̆', '˙' => ' ̇', '˚' => ' ̊', '˛' => ' ̨', '˜' => ' ̃', '˝' => ' ̋', 'ˠ' => 'ɣ', 'ˡ' => 'l', 'ˢ' => 's', 'ˣ' => 'x', 'ˤ' => 'ʕ', 'ͺ' => ' ͅ', '΄' => ' ́', '΅' => ' ̈́', 'ϐ' => 'β', 'ϑ' => 'θ', 'ϒ' => 'Υ', 'ϓ' => 'Ύ', 'ϔ' => 'Ϋ', 'ϕ' => 'φ', 'ϖ' => 'π', 'ϰ' => 'κ', 'ϱ' => 'ρ', 'ϲ' => 'ς', 'ϴ' => 'Θ', 'ϵ' => 'ε', 'Ϲ' => 'Σ', 'և' => 'եւ', 'ٵ' => 'اٴ', 'ٶ' => 'وٴ', 'ٷ' => 'ۇٴ', 'ٸ' => 'يٴ', 'ำ' => 'ํา', 'ຳ' => 'ໍາ', 'ໜ' => 'ຫນ', 'ໝ' => 'ຫມ', '༌' => '་', 'ཷ' => 'ྲཱྀ', 'ཹ' => 'ླཱྀ', 'ჼ' => 'ნ', 'ᴬ' => 'A', 'ᴭ' => 'Æ', 'ᴮ' => 'B', 'ᴰ' => 'D', 'ᴱ' => 'E', 'ᴲ' => 'Ǝ', 'ᴳ' => 'G', 'ᴴ' => 'H', 'ᴵ' => 'I', 'ᴶ' => 'J', 'ᴷ' => 'K', 'ᴸ' => 'L', 'ᴹ' => 'M', 'ᴺ' => 'N', 'ᴼ' => 'O', 'ᴽ' => 'Ȣ', 'ᴾ' => 'P', 'ᴿ' => 'R', 'ᵀ' => 'T', 'ᵁ' => 'U', 'ᵂ' => 'W', 'ᵃ' => 'a', 'ᵄ' => 'ɐ', 'ᵅ' => 'ɑ', 'ᵆ' => 'ᴂ', 'ᵇ' => 'b', 'ᵈ' => 'd', 'ᵉ' => 'e', 'ᵊ' => 'ə', 'ᵋ' => 'ɛ', 'ᵌ' => 'ɜ', 'ᵍ' => 'g', 'ᵏ' => 'k', 'ᵐ' => 'm', 'ᵑ' => 'ŋ', 'ᵒ' => 'o', 'ᵓ' => 'ɔ', 'ᵔ' => 'ᴖ', 'ᵕ' => 'ᴗ', 'ᵖ' => 'p', 'ᵗ' => 't', 'ᵘ' => 'u', 'ᵙ' => 'ᴝ', 'ᵚ' => 'ɯ', 'ᵛ' => 'v', 'ᵜ' => 'ᴥ', 'ᵝ' => 'β', 'ᵞ' => 'γ', 'ᵟ' => 'δ', 'ᵠ' => 'φ', 'ᵡ' => 'χ', 'ᵢ' => 'i', 'ᵣ' => 'r', 'ᵤ' => 'u', 'ᵥ' => 'v', 'ᵦ' => 'β', 'ᵧ' => 'γ', 'ᵨ' => 'ρ', 'ᵩ' => 'φ', 'ᵪ' => 'χ', 'ᵸ' => 'н', 'ᶛ' => 'ɒ', 'ᶜ' => 'c', 'ᶝ' => 'ɕ', 'ᶞ' => 'ð', 'ᶟ' => 'ɜ', 'ᶠ' => 'f', 'ᶡ' => 'ɟ', 'ᶢ' => 'ɡ', 'ᶣ' => 'ɥ', 'ᶤ' => 'ɨ', 'ᶥ' => 'ɩ', 'ᶦ' => 'ɪ', 'ᶧ' => 'ᵻ', 'ᶨ' => 'ʝ', 'ᶩ' => 'ɭ', 'ᶪ' => 'ᶅ', 'ᶫ' => 'ʟ', 'ᶬ' => 'ɱ', 'ᶭ' => 'ɰ', 'ᶮ' => 'ɲ', 'ᶯ' => 'ɳ', 'ᶰ' => 'ɴ', 'ᶱ' => 'ɵ', 'ᶲ' => 'ɸ', 'ᶳ' => 'ʂ', 'ᶴ' => 'ʃ', 'ᶵ' => 'ƫ', 'ᶶ' => 'ʉ', 'ᶷ' => 'ʊ', 'ᶸ' => 'ᴜ', 'ᶹ' => 'ʋ', 'ᶺ' => 'ʌ', 'ᶻ' => 'z', 'ᶼ' => 'ʐ', 'ᶽ' => 'ʑ', 'ᶾ' => 'ʒ', 'ᶿ' => 'θ', 'ẚ' => 'aʾ', 'ẛ' => 'ṡ', '᾽' => ' ̓', '᾿' => ' ̓', '῀' => ' ͂', '῁' => ' ̈͂', '῍' => ' ̓̀', '῎' => ' ̓́', '῏' => ' ̓͂', '῝' => ' ̔̀', '῞' => ' ̔́', '῟' => ' ̔͂', '῭' => ' ̈̀', '΅' => ' ̈́', '´' => ' ́', '῾' => ' ̔', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '‑' => '‐', '‗' => ' ̳', '․' => '.', '‥' => '..', '…' => '...', ' ' => ' ', '″' => '′′', '‴' => '′′′', '‶' => '‵‵', '‷' => '‵‵‵', '‼' => '!!', '‾' => ' ̅', '⁇' => '??', '⁈' => '?!', '⁉' => '!?', '⁗' => '′′′′', ' ' => ' ', '⁰' => '0', 'ⁱ' => 'i', '⁴' => '4', '⁵' => '5', '⁶' => '6', '⁷' => '7', '⁸' => '8', '⁹' => '9', '⁺' => '+', '⁻' => '−', '⁼' => '=', '⁽' => '(', '⁾' => ')', 'ⁿ' => 'n', '₀' => '0', '₁' => '1', '₂' => '2', '₃' => '3', '₄' => '4', '₅' => '5', '₆' => '6', '₇' => '7', '₈' => '8', '₉' => '9', '₊' => '+', '₋' => '−', '₌' => '=', '₍' => '(', '₎' => ')', 'ₐ' => 'a', 'ₑ' => 'e', 'ₒ' => 'o', 'ₓ' => 'x', 'ₔ' => 'ə', 'ₕ' => 'h', 'ₖ' => 'k', 'ₗ' => 'l', 'ₘ' => 'm', 'ₙ' => 'n', 'ₚ' => 'p', 'ₛ' => 's', 'ₜ' => 't', '₨' => 'Rs', '℀' => 'a/c', '℁' => 'a/s', 'ℂ' => 'C', '℃' => '°C', '℅' => 'c/o', '℆' => 'c/u', 'ℇ' => 'Ɛ', '℉' => '°F', 'ℊ' => 'g', 'ℋ' => 'H', 'ℌ' => 'H', 'ℍ' => 'H', 'ℎ' => 'h', 'ℏ' => 'ħ', 'ℐ' => 'I', 'ℑ' => 'I', 'ℒ' => 'L', 'ℓ' => 'l', 'ℕ' => 'N', '№' => 'No', 'ℙ' => 'P', 'ℚ' => 'Q', 'ℛ' => 'R', 'ℜ' => 'R', 'ℝ' => 'R', '℠' => 'SM', '℡' => 'TEL', '™' => 'TM', 'ℤ' => 'Z', 'ℨ' => 'Z', 'ℬ' => 'B', 'ℭ' => 'C', 'ℯ' => 'e', 'ℰ' => 'E', 'ℱ' => 'F', 'ℳ' => 'M', 'ℴ' => 'o', 'ℵ' => 'א', 'ℶ' => 'ב', 'ℷ' => 'ג', 'ℸ' => 'ד', 'ℹ' => 'i', '℻' => 'FAX', 'ℼ' => 'π', 'ℽ' => 'γ', 'ℾ' => 'Γ', 'ℿ' => 'Π', '⅀' => '∑', 'ⅅ' => 'D', 'ⅆ' => 'd', 'ⅇ' => 'e', 'ⅈ' => 'i', 'ⅉ' => 'j', '⅐' => '1⁄7', '⅑' => '1⁄9', '⅒' => '1⁄10', '⅓' => '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⁄', 'Ⅰ' => 'I', 'Ⅱ' => 'II', 'Ⅲ' => 'III', 'Ⅳ' => 'IV', 'Ⅴ' => 'V', 'Ⅵ' => 'VI', 'Ⅶ' => 'VII', 'Ⅷ' => 'VIII', 'Ⅸ' => 'IX', 'Ⅹ' => 'X', 'Ⅺ' => 'XI', 'Ⅻ' => 'XII', 'Ⅼ' => 'L', 'Ⅽ' => 'C', 'Ⅾ' => 'D', 'Ⅿ' => 'M', 'ⅰ' => 'i', 'ⅱ' => 'ii', 'ⅲ' => 'iii', 'ⅳ' => 'iv', 'ⅴ' => 'v', 'ⅵ' => 'vi', 'ⅶ' => 'vii', 'ⅷ' => 'viii', 'ⅸ' => 'ix', 'ⅹ' => 'x', 'ⅺ' => 'xi', 'ⅻ' => 'xii', 'ⅼ' => 'l', 'ⅽ' => 'c', 'ⅾ' => 'd', 'ⅿ' => 'm', '↉' => '0⁄3', '∬' => '∫∫', '∭' => '∫∫∫', '∯' => '∮∮', '∰' => '∮∮∮', '①' => '1', '②' => '2', '③' => '3', '④' => '4', '⑤' => '5', '⑥' => '6', '⑦' => '7', '⑧' => '8', '⑨' => '9', '⑩' => '10', '⑪' => '11', '⑫' => '12', '⑬' => '13', '⑭' => '14', '⑮' => '15', '⑯' => '16', '⑰' => '17', '⑱' => '18', '⑲' => '19', '⑳' => '20', '⑴' => '(1)', '⑵' => '(2)', '⑶' => '(3)', '⑷' => '(4)', '⑸' => '(5)', '⑹' => '(6)', '⑺' => '(7)', '⑻' => '(8)', '⑼' => '(9)', '⑽' => '(10)', '⑾' => '(11)', '⑿' => '(12)', '⒀' => '(13)', '⒁' => '(14)', '⒂' => '(15)', '⒃' => '(16)', '⒄' => '(17)', '⒅' => '(18)', '⒆' => '(19)', '⒇' => '(20)', '⒈' => '1.', '⒉' => '2.', '⒊' => '3.', '⒋' => '4.', '⒌' => '5.', '⒍' => '6.', '⒎' => '7.', '⒏' => '8.', '⒐' => '9.', '⒑' => '10.', '⒒' => '11.', '⒓' => '12.', '⒔' => '13.', '⒕' => '14.', '⒖' => '15.', '⒗' => '16.', '⒘' => '17.', '⒙' => '18.', '⒚' => '19.', '⒛' => '20.', '⒜' => '(a)', '⒝' => '(b)', '⒞' => '(c)', '⒟' => '(d)', '⒠' => '(e)', '⒡' => '(f)', '⒢' => '(g)', '⒣' => '(h)', '⒤' => '(i)', '⒥' => '(j)', '⒦' => '(k)', '⒧' => '(l)', '⒨' => '(m)', '⒩' => '(n)', '⒪' => '(o)', '⒫' => '(p)', '⒬' => '(q)', '⒭' => '(r)', '⒮' => '(s)', '⒯' => '(t)', '⒰' => '(u)', '⒱' => '(v)', '⒲' => '(w)', '⒳' => '(x)', '⒴' => '(y)', '⒵' => '(z)', 'Ⓐ' => 'A', 'Ⓑ' => 'B', 'Ⓒ' => 'C', 'Ⓓ' => 'D', 'Ⓔ' => 'E', 'Ⓕ' => 'F', 'Ⓖ' => 'G', 'Ⓗ' => 'H', 'Ⓘ' => 'I', 'Ⓙ' => 'J', 'Ⓚ' => 'K', 'Ⓛ' => 'L', 'Ⓜ' => 'M', 'Ⓝ' => 'N', 'Ⓞ' => 'O', 'Ⓟ' => 'P', 'Ⓠ' => 'Q', 'Ⓡ' => 'R', 'Ⓢ' => 'S', 'Ⓣ' => 'T', 'Ⓤ' => 'U', 'Ⓥ' => 'V', 'Ⓦ' => 'W', 'Ⓧ' => 'X', 'Ⓨ' => 'Y', 'Ⓩ' => 'Z', 'ⓐ' => 'a', 'ⓑ' => 'b', 'ⓒ' => 'c', 'ⓓ' => 'd', 'ⓔ' => 'e', 'ⓕ' => 'f', 'ⓖ' => 'g', 'ⓗ' => 'h', 'ⓘ' => 'i', 'ⓙ' => 'j', 'ⓚ' => 'k', 'ⓛ' => 'l', 'ⓜ' => 'm', 'ⓝ' => 'n', 'ⓞ' => 'o', 'ⓟ' => 'p', 'ⓠ' => 'q', 'ⓡ' => 'r', 'ⓢ' => 's', 'ⓣ' => 't', 'ⓤ' => 'u', 'ⓥ' => 'v', 'ⓦ' => 'w', 'ⓧ' => 'x', 'ⓨ' => 'y', 'ⓩ' => 'z', '⓪' => '0', '⨌' => '∫∫∫∫', '⩴' => '::=', '⩵' => '==', '⩶' => '===', 'ⱼ' => 'j', 'ⱽ' => 'V', 'ⵯ' => 'ⵡ', '⺟' => '母', '⻳' => '龟', '⼀' => '一', '⼁' => '丨', '⼂' => '丶', '⼃' => '丿', '⼄' => '乙', '⼅' => '亅', '⼆' => '二', '⼇' => '亠', '⼈' => '人', '⼉' => '儿', '⼊' => '入', '⼋' => '八', '⼌' => '冂', '⼍' => '冖', '⼎' => '冫', '⼏' => '几', '⼐' => '凵', '⼑' => '刀', '⼒' => '力', '⼓' => '勹', '⼔' => '匕', '⼕' => '匚', '⼖' => '匸', '⼗' => '十', '⼘' => '卜', '⼙' => '卩', '⼚' => '厂', '⼛' => '厶', '⼜' => '又', '⼝' => '口', '⼞' => '囗', '⼟' => '土', '⼠' => '士', '⼡' => '夂', '⼢' => '夊', '⼣' => '夕', '⼤' => '大', '⼥' => '女', '⼦' => '子', '⼧' => '宀', '⼨' => '寸', '⼩' => '小', '⼪' => '尢', '⼫' => '尸', '⼬' => '屮', '⼭' => '山', '⼮' => '巛', '⼯' => '工', '⼰' => '己', '⼱' => '巾', '⼲' => '干', '⼳' => '幺', '⼴' => '广', '⼵' => '廴', '⼶' => '廾', '⼷' => '弋', '⼸' => '弓', '⼹' => '彐', '⼺' => '彡', '⼻' => '彳', '⼼' => '心', '⼽' => '戈', '⼾' => '戶', '⼿' => '手', '⽀' => '支', '⽁' => '攴', '⽂' => '文', '⽃' => '斗', '⽄' => '斤', '⽅' => '方', '⽆' => '无', '⽇' => '日', '⽈' => '曰', '⽉' => '月', '⽊' => '木', '⽋' => '欠', '⽌' => '止', '⽍' => '歹', '⽎' => '殳', '⽏' => '毋', '⽐' => '比', '⽑' => '毛', '⽒' => '氏', '⽓' => '气', '⽔' => '水', '⽕' => '火', '⽖' => '爪', '⽗' => '父', '⽘' => '爻', '⽙' => '爿', '⽚' => '片', '⽛' => '牙', '⽜' => '牛', '⽝' => '犬', '⽞' => '玄', '⽟' => '玉', '⽠' => '瓜', '⽡' => '瓦', '⽢' => '甘', '⽣' => '生', '⽤' => '用', '⽥' => '田', '⽦' => '疋', '⽧' => '疒', '⽨' => '癶', '⽩' => '白', '⽪' => '皮', '⽫' => '皿', '⽬' => '目', '⽭' => '矛', '⽮' => '矢', '⽯' => '石', '⽰' => '示', '⽱' => '禸', '⽲' => '禾', '⽳' => '穴', '⽴' => '立', '⽵' => '竹', '⽶' => '米', '⽷' => '糸', '⽸' => '缶', '⽹' => '网', '⽺' => '羊', '⽻' => '羽', '⽼' => '老', '⽽' => '而', '⽾' => '耒', '⽿' => '耳', '⾀' => '聿', '⾁' => '肉', '⾂' => '臣', '⾃' => '自', '⾄' => '至', '⾅' => '臼', '⾆' => '舌', '⾇' => '舛', '⾈' => '舟', '⾉' => '艮', '⾊' => '色', '⾋' => '艸', '⾌' => '虍', '⾍' => '虫', '⾎' => '血', '⾏' => '行', '⾐' => '衣', '⾑' => '襾', '⾒' => '見', '⾓' => '角', '⾔' => '言', '⾕' => '谷', '⾖' => '豆', '⾗' => '豕', '⾘' => '豸', '⾙' => '貝', '⾚' => '赤', '⾛' => '走', '⾜' => '足', '⾝' => '身', '⾞' => '車', '⾟' => '辛', '⾠' => '辰', '⾡' => '辵', '⾢' => '邑', '⾣' => '酉', '⾤' => '釆', '⾥' => '里', '⾦' => '金', '⾧' => '長', '⾨' => '門', '⾩' => '阜', '⾪' => '隶', '⾫' => '隹', '⾬' => '雨', '⾭' => '靑', '⾮' => '非', '⾯' => '面', '⾰' => '革', '⾱' => '韋', '⾲' => '韭', '⾳' => '音', '⾴' => '頁', '⾵' => '風', '⾶' => '飛', '⾷' => '食', '⾸' => '首', '⾹' => '香', '⾺' => '馬', '⾻' => '骨', '⾼' => '高', '⾽' => '髟', '⾾' => '鬥', '⾿' => '鬯', '⿀' => '鬲', '⿁' => '鬼', '⿂' => '魚', '⿃' => '鳥', '⿄' => '鹵', '⿅' => '鹿', '⿆' => '麥', '⿇' => '麻', '⿈' => '黃', '⿉' => '黍', '⿊' => '黑', '⿋' => '黹', '⿌' => '黽', '⿍' => '鼎', '⿎' => '鼓', '⿏' => '鼠', '⿐' => '鼻', '⿑' => '齊', '⿒' => '齒', '⿓' => '龍', '⿔' => '龜', '⿕' => '龠', ' ' => ' ', '〶' => '〒', '〸' => '十', '〹' => '卄', '〺' => '卅', '゛' => ' ゙', '゜' => ' ゚', 'ゟ' => 'より', 'ヿ' => 'コト', 'ㄱ' => 'ᄀ', 'ㄲ' => 'ᄁ', 'ㄳ' => 'ᆪ', 'ㄴ' => 'ᄂ', 'ㄵ' => 'ᆬ', 'ㄶ' => 'ᆭ', 'ㄷ' => 'ᄃ', 'ㄸ' => 'ᄄ', 'ㄹ' => 'ᄅ', 'ㄺ' => 'ᆰ', 'ㄻ' => 'ᆱ', 'ㄼ' => 'ᆲ', 'ㄽ' => 'ᆳ', 'ㄾ' => 'ᆴ', 'ㄿ' => 'ᆵ', 'ㅀ' => 'ᄚ', 'ㅁ' => 'ᄆ', 'ㅂ' => 'ᄇ', 'ㅃ' => 'ᄈ', 'ㅄ' => 'ᄡ', 'ㅅ' => 'ᄉ', 'ㅆ' => 'ᄊ', 'ㅇ' => 'ᄋ', 'ㅈ' => 'ᄌ', 'ㅉ' => 'ᄍ', 'ㅊ' => 'ᄎ', 'ㅋ' => 'ᄏ', 'ㅌ' => 'ᄐ', 'ㅍ' => 'ᄑ', 'ㅎ' => 'ᄒ', 'ㅏ' => 'ᅡ', 'ㅐ' => 'ᅢ', 'ㅑ' => 'ᅣ', 'ㅒ' => 'ᅤ', 'ㅓ' => 'ᅥ', 'ㅔ' => 'ᅦ', 'ㅕ' => 'ᅧ', 'ㅖ' => 'ᅨ', 'ㅗ' => 'ᅩ', 'ㅘ' => 'ᅪ', 'ㅙ' => 'ᅫ', 'ㅚ' => 'ᅬ', 'ㅛ' => 'ᅭ', 'ㅜ' => 'ᅮ', 'ㅝ' => 'ᅯ', 'ㅞ' => 'ᅰ', 'ㅟ' => 'ᅱ', 'ㅠ' => 'ᅲ', 'ㅡ' => 'ᅳ', 'ㅢ' => 'ᅴ', 'ㅣ' => 'ᅵ', 'ㅤ' => 'ᅠ', 'ㅥ' => 'ᄔ', 'ㅦ' => 'ᄕ', 'ㅧ' => 'ᇇ', 'ㅨ' => 'ᇈ', 'ㅩ' => 'ᇌ', 'ㅪ' => 'ᇎ', 'ㅫ' => 'ᇓ', 'ㅬ' => 'ᇗ', 'ㅭ' => 'ᇙ', 'ㅮ' => 'ᄜ', 'ㅯ' => 'ᇝ', 'ㅰ' => 'ᇟ', 'ㅱ' => 'ᄝ', 'ㅲ' => 'ᄞ', 'ㅳ' => 'ᄠ', 'ㅴ' => 'ᄢ', 'ㅵ' => 'ᄣ', 'ㅶ' => 'ᄧ', 'ㅷ' => 'ᄩ', 'ㅸ' => 'ᄫ', 'ㅹ' => 'ᄬ', 'ㅺ' => 'ᄭ', 'ㅻ' => 'ᄮ', 'ㅼ' => 'ᄯ', 'ㅽ' => 'ᄲ', 'ㅾ' => 'ᄶ', 'ㅿ' => 'ᅀ', 'ㆀ' => 'ᅇ', 'ㆁ' => 'ᅌ', 'ㆂ' => 'ᇱ', 'ㆃ' => 'ᇲ', 'ㆄ' => 'ᅗ', 'ㆅ' => 'ᅘ', 'ㆆ' => 'ᅙ', 'ㆇ' => 'ᆄ', 'ㆈ' => 'ᆅ', 'ㆉ' => 'ᆈ', 'ㆊ' => 'ᆑ', 'ㆋ' => 'ᆒ', 'ㆌ' => 'ᆔ', 'ㆍ' => 'ᆞ', 'ㆎ' => 'ᆡ', '㆒' => '一', '㆓' => '二', '㆔' => '三', '㆕' => '四', '㆖' => '上', '㆗' => '中', '㆘' => '下', '㆙' => '甲', '㆚' => '乙', '㆛' => '丙', '㆜' => '丁', '㆝' => '天', '㆞' => '地', '㆟' => '人', '㈀' => '(ᄀ)', '㈁' => '(ᄂ)', '㈂' => '(ᄃ)', '㈃' => '(ᄅ)', '㈄' => '(ᄆ)', '㈅' => '(ᄇ)', '㈆' => '(ᄉ)', '㈇' => '(ᄋ)', '㈈' => '(ᄌ)', '㈉' => '(ᄎ)', '㈊' => '(ᄏ)', '㈋' => '(ᄐ)', '㈌' => '(ᄑ)', '㈍' => '(ᄒ)', '㈎' => '(가)', '㈏' => '(나)', '㈐' => '(다)', '㈑' => '(라)', '㈒' => '(마)', '㈓' => '(바)', '㈔' => '(사)', '㈕' => '(아)', '㈖' => '(자)', '㈗' => '(차)', '㈘' => '(카)', '㈙' => '(타)', '㈚' => '(파)', '㈛' => '(하)', '㈜' => '(주)', '㈝' => '(오전)', '㈞' => '(오후)', '㈠' => '(一)', '㈡' => '(二)', '㈢' => '(三)', '㈣' => '(四)', '㈤' => '(五)', '㈥' => '(六)', '㈦' => '(七)', '㈧' => '(八)', '㈨' => '(九)', '㈩' => '(十)', '㈪' => '(月)', '㈫' => '(火)', '㈬' => '(水)', '㈭' => '(木)', '㈮' => '(金)', '㈯' => '(土)', '㈰' => '(日)', '㈱' => '(株)', '㈲' => '(有)', '㈳' => '(社)', '㈴' => '(名)', '㈵' => '(特)', '㈶' => '(財)', '㈷' => '(祝)', '㈸' => '(労)', '㈹' => '(代)', '㈺' => '(呼)', '㈻' => '(学)', '㈼' => '(監)', '㈽' => '(企)', '㈾' => '(資)', '㈿' => '(協)', '㉀' => '(祭)', '㉁' => '(休)', '㉂' => '(自)', '㉃' => '(至)', '㉄' => '問', '㉅' => '幼', '㉆' => '文', '㉇' => '箏', '㉐' => 'PTE', '㉑' => '21', '㉒' => '22', '㉓' => '23', '㉔' => '24', '㉕' => '25', '㉖' => '26', '㉗' => '27', '㉘' => '28', '㉙' => '29', '㉚' => '30', '㉛' => '31', '㉜' => '32', '㉝' => '33', '㉞' => '34', '㉟' => '35', '㉠' => 'ᄀ', '㉡' => 'ᄂ', '㉢' => 'ᄃ', '㉣' => 'ᄅ', '㉤' => 'ᄆ', '㉥' => 'ᄇ', '㉦' => 'ᄉ', '㉧' => 'ᄋ', '㉨' => 'ᄌ', '㉩' => 'ᄎ', '㉪' => 'ᄏ', '㉫' => 'ᄐ', '㉬' => 'ᄑ', '㉭' => 'ᄒ', '㉮' => '가', '㉯' => '나', '㉰' => '다', '㉱' => '라', '㉲' => '마', '㉳' => '바', '㉴' => '사', '㉵' => '아', '㉶' => '자', '㉷' => '차', '㉸' => '카', '㉹' => '타', '㉺' => '파', '㉻' => '하', '㉼' => '참고', '㉽' => '주의', '㉾' => '우', '㊀' => '一', '㊁' => '二', '㊂' => '三', '㊃' => '四', '㊄' => '五', '㊅' => '六', '㊆' => '七', '㊇' => '八', '㊈' => '九', '㊉' => '十', '㊊' => '月', '㊋' => '火', '㊌' => '水', '㊍' => '木', '㊎' => '金', '㊏' => '土', '㊐' => '日', '㊑' => '株', '㊒' => '有', '㊓' => '社', '㊔' => '名', '㊕' => '特', '㊖' => '財', '㊗' => '祝', '㊘' => '労', '㊙' => '秘', '㊚' => '男', '㊛' => '女', '㊜' => '適', '㊝' => '優', '㊞' => '印', '㊟' => '注', '㊠' => '項', '㊡' => '休', '㊢' => '写', '㊣' => '正', '㊤' => '上', '㊥' => '中', '㊦' => '下', '㊧' => '左', '㊨' => '右', '㊩' => '医', '㊪' => '宗', '㊫' => '学', '㊬' => '監', '㊭' => '企', '㊮' => '資', '㊯' => '協', '㊰' => '夜', '㊱' => '36', '㊲' => '37', '㊳' => '38', '㊴' => '39', '㊵' => '40', '㊶' => '41', '㊷' => '42', '㊸' => '43', '㊹' => '44', '㊺' => '45', '㊻' => '46', '㊼' => '47', '㊽' => '48', '㊾' => '49', '㊿' => '50', '㋀' => '1月', '㋁' => '2月', '㋂' => '3月', '㋃' => '4月', '㋄' => '5月', '㋅' => '6月', '㋆' => '7月', '㋇' => '8月', '㋈' => '9月', '㋉' => '10月', '㋊' => '11月', '㋋' => '12月', '㋌' => 'Hg', '㋍' => 'erg', '㋎' => 'eV', '㋏' => 'LTD', '㋐' => 'ア', '㋑' => 'イ', '㋒' => 'ウ', '㋓' => 'エ', '㋔' => 'オ', '㋕' => 'カ', '㋖' => 'キ', '㋗' => 'ク', '㋘' => 'ケ', '㋙' => 'コ', '㋚' => 'サ', '㋛' => 'シ', '㋜' => 'ス', '㋝' => 'セ', '㋞' => 'ソ', '㋟' => 'タ', '㋠' => 'チ', '㋡' => 'ツ', '㋢' => 'テ', '㋣' => 'ト', '㋤' => 'ナ', '㋥' => 'ニ', '㋦' => 'ヌ', '㋧' => 'ネ', '㋨' => 'ノ', '㋩' => 'ハ', '㋪' => 'ヒ', '㋫' => 'フ', '㋬' => 'ヘ', '㋭' => 'ホ', '㋮' => 'マ', '㋯' => 'ミ', '㋰' => 'ム', '㋱' => 'メ', '㋲' => 'モ', '㋳' => 'ヤ', '㋴' => 'ユ', '㋵' => 'ヨ', '㋶' => 'ラ', '㋷' => 'リ', '㋸' => 'ル', '㋹' => 'レ', '㋺' => 'ロ', '㋻' => 'ワ', '㋼' => 'ヰ', '㋽' => 'ヱ', '㋾' => 'ヲ', '㋿' => '令和', '㌀' => 'アパート', '㌁' => 'アルファ', '㌂' => 'アンペア', '㌃' => 'アール', '㌄' => 'イニング', '㌅' => 'インチ', '㌆' => 'ウォン', '㌇' => 'エスクード', '㌈' => 'エーカー', '㌉' => 'オンス', '㌊' => 'オーム', '㌋' => 'カイリ', '㌌' => 'カラット', '㌍' => 'カロリー', '㌎' => 'ガロン', '㌏' => 'ガンマ', '㌐' => 'ギガ', '㌑' => 'ギニー', '㌒' => 'キュリー', '㌓' => 'ギルダー', '㌔' => 'キロ', '㌕' => 'キログラム', '㌖' => 'キロメートル', '㌗' => 'キロワット', '㌘' => 'グラム', '㌙' => 'グラムトン', '㌚' => 'クルゼイロ', '㌛' => 'クローネ', '㌜' => 'ケース', '㌝' => 'コルナ', '㌞' => 'コーポ', '㌟' => 'サイクル', '㌠' => 'サンチーム', '㌡' => 'シリング', '㌢' => 'センチ', '㌣' => 'セント', '㌤' => 'ダース', '㌥' => 'デシ', '㌦' => 'ドル', '㌧' => 'トン', '㌨' => 'ナノ', '㌩' => 'ノット', '㌪' => 'ハイツ', '㌫' => 'パーセント', '㌬' => 'パーツ', '㌭' => 'バーレル', '㌮' => 'ピアストル', '㌯' => 'ピクル', '㌰' => 'ピコ', '㌱' => 'ビル', '㌲' => 'ファラッド', '㌳' => 'フィート', '㌴' => 'ブッシェル', '㌵' => 'フラン', '㌶' => 'ヘクタール', '㌷' => 'ペソ', '㌸' => 'ペニヒ', '㌹' => 'ヘルツ', '㌺' => 'ペンス', '㌻' => 'ページ', '㌼' => 'ベータ', '㌽' => 'ポイント', '㌾' => 'ボルト', '㌿' => 'ホン', '㍀' => 'ポンド', '㍁' => 'ホール', '㍂' => 'ホーン', '㍃' => 'マイクロ', '㍄' => 'マイル', '㍅' => 'マッハ', '㍆' => 'マルク', '㍇' => 'マンション', '㍈' => 'ミクロン', '㍉' => 'ミリ', '㍊' => 'ミリバール', '㍋' => 'メガ', '㍌' => 'メガトン', '㍍' => 'メートル', '㍎' => 'ヤード', '㍏' => 'ヤール', '㍐' => 'ユアン', '㍑' => 'リットル', '㍒' => 'リラ', '㍓' => 'ルピー', '㍔' => 'ルーブル', '㍕' => 'レム', '㍖' => 'レントゲン', '㍗' => 'ワット', '㍘' => '0点', '㍙' => '1点', '㍚' => '2点', '㍛' => '3点', '㍜' => '4点', '㍝' => '5点', '㍞' => '6点', '㍟' => '7点', '㍠' => '8点', '㍡' => '9点', '㍢' => '10点', '㍣' => '11点', '㍤' => '12点', '㍥' => '13点', '㍦' => '14点', '㍧' => '15点', '㍨' => '16点', '㍩' => '17点', '㍪' => '18点', '㍫' => '19点', '㍬' => '20点', '㍭' => '21点', '㍮' => '22点', '㍯' => '23点', '㍰' => '24点', '㍱' => 'hPa', '㍲' => 'da', '㍳' => 'AU', '㍴' => 'bar', '㍵' => 'oV', '㍶' => 'pc', '㍷' => 'dm', '㍸' => 'dm2', '㍹' => 'dm3', '㍺' => 'IU', '㍻' => '平成', '㍼' => '昭和', '㍽' => '大正', '㍾' => '明治', '㍿' => '株式会社', '㎀' => 'pA', '㎁' => 'nA', '㎂' => 'μA', '㎃' => 'mA', '㎄' => 'kA', '㎅' => 'KB', '㎆' => 'MB', '㎇' => 'GB', '㎈' => 'cal', '㎉' => 'kcal', '㎊' => 'pF', '㎋' => 'nF', '㎌' => 'μF', '㎍' => 'μg', '㎎' => 'mg', '㎏' => 'kg', '㎐' => 'Hz', '㎑' => 'kHz', '㎒' => 'MHz', '㎓' => 'GHz', '㎔' => 'THz', '㎕' => 'μl', '㎖' => 'ml', '㎗' => 'dl', '㎘' => 'kl', '㎙' => 'fm', '㎚' => 'nm', '㎛' => 'μm', '㎜' => 'mm', '㎝' => 'cm', '㎞' => 'km', '㎟' => 'mm2', '㎠' => 'cm2', '㎡' => 'm2', '㎢' => 'km2', '㎣' => 'mm3', '㎤' => 'cm3', '㎥' => 'm3', '㎦' => 'km3', '㎧' => 'm∕s', '㎨' => 'm∕s2', '㎩' => 'Pa', '㎪' => 'kPa', '㎫' => 'MPa', '㎬' => 'GPa', '㎭' => 'rad', '㎮' => 'rad∕s', '㎯' => 'rad∕s2', '㎰' => 'ps', '㎱' => 'ns', '㎲' => 'μs', '㎳' => 'ms', '㎴' => 'pV', '㎵' => 'nV', '㎶' => 'μV', '㎷' => 'mV', '㎸' => 'kV', '㎹' => 'MV', '㎺' => 'pW', '㎻' => 'nW', '㎼' => 'μW', '㎽' => 'mW', '㎾' => 'kW', '㎿' => 'MW', '㏀' => 'kΩ', '㏁' => 'MΩ', '㏂' => 'a.m.', '㏃' => 'Bq', '㏄' => 'cc', '㏅' => 'cd', '㏆' => 'C∕kg', '㏇' => 'Co.', '㏈' => 'dB', '㏉' => 'Gy', '㏊' => 'ha', '㏋' => 'HP', '㏌' => 'in', '㏍' => 'KK', '㏎' => 'KM', '㏏' => 'kt', '㏐' => 'lm', '㏑' => 'ln', '㏒' => 'log', '㏓' => 'lx', '㏔' => 'mb', '㏕' => 'mil', '㏖' => 'mol', '㏗' => 'PH', '㏘' => 'p.m.', '㏙' => 'PPM', '㏚' => 'PR', '㏛' => 'sr', '㏜' => 'Sv', '㏝' => 'Wb', '㏞' => 'V∕m', '㏟' => 'A∕m', '㏠' => '1日', '㏡' => '2日', '㏢' => '3日', '㏣' => '4日', '㏤' => '5日', '㏥' => '6日', '㏦' => '7日', '㏧' => '8日', '㏨' => '9日', '㏩' => '10日', '㏪' => '11日', '㏫' => '12日', '㏬' => '13日', '㏭' => '14日', '㏮' => '15日', '㏯' => '16日', '㏰' => '17日', '㏱' => '18日', '㏲' => '19日', '㏳' => '20日', '㏴' => '21日', '㏵' => '22日', '㏶' => '23日', '㏷' => '24日', '㏸' => '25日', '㏹' => '26日', '㏺' => '27日', '㏻' => '28日', '㏼' => '29日', '㏽' => '30日', '㏾' => '31日', '㏿' => 'gal', 'ꚜ' => 'ъ', 'ꚝ' => 'ь', 'ꝰ' => 'ꝯ', 'ꟸ' => 'Ħ', 'ꟹ' => 'œ', 'ꭜ' => 'ꜧ', 'ꭝ' => 'ꬷ', 'ꭞ' => 'ɫ', 'ꭟ' => 'ꭒ', 'ꭩ' => 'ʍ', 'ff' => 'ff', 'fi' => 'fi', 'fl' => 'fl', 'ffi' => 'ffi', 'ffl' => 'ffl', 'ſt' => 'st', 'st' => 'st', 'ﬓ' => 'մն', 'ﬔ' => 'մե', 'ﬕ' => 'մի', 'ﬖ' => 'վն', 'ﬗ' => 'մխ', 'ﬠ' => 'ע', 'ﬡ' => 'א', 'ﬢ' => 'ד', 'ﬣ' => 'ה', 'ﬤ' => 'כ', 'ﬥ' => 'ל', 'ﬦ' => 'ם', 'ﬧ' => 'ר', 'ﬨ' => 'ת', '﬩' => '+', 'ﭏ' => 'אל', 'ﭐ' => 'ٱ', 'ﭑ' => 'ٱ', 'ﭒ' => 'ٻ', 'ﭓ' => 'ٻ', 'ﭔ' => 'ٻ', 'ﭕ' => 'ٻ', 'ﭖ' => 'پ', 'ﭗ' => 'پ', 'ﭘ' => 'پ', 'ﭙ' => 'پ', 'ﭚ' => 'ڀ', 'ﭛ' => 'ڀ', 'ﭜ' => 'ڀ', 'ﭝ' => 'ڀ', 'ﭞ' => 'ٺ', 'ﭟ' => 'ٺ', 'ﭠ' => 'ٺ', 'ﭡ' => 'ٺ', 'ﭢ' => 'ٿ', 'ﭣ' => 'ٿ', 'ﭤ' => 'ٿ', 'ﭥ' => 'ٿ', 'ﭦ' => 'ٹ', 'ﭧ' => 'ٹ', 'ﭨ' => 'ٹ', 'ﭩ' => 'ٹ', 'ﭪ' => 'ڤ', 'ﭫ' => 'ڤ', 'ﭬ' => 'ڤ', 'ﭭ' => 'ڤ', 'ﭮ' => 'ڦ', 'ﭯ' => 'ڦ', 'ﭰ' => 'ڦ', 'ﭱ' => 'ڦ', 'ﭲ' => 'ڄ', 'ﭳ' => 'ڄ', 'ﭴ' => 'ڄ', 'ﭵ' => 'ڄ', 'ﭶ' => 'ڃ', 'ﭷ' => 'ڃ', 'ﭸ' => 'ڃ', 'ﭹ' => 'ڃ', 'ﭺ' => 'چ', 'ﭻ' => 'چ', 'ﭼ' => 'چ', 'ﭽ' => 'چ', 'ﭾ' => 'ڇ', 'ﭿ' => 'ڇ', 'ﮀ' => 'ڇ', 'ﮁ' => 'ڇ', 'ﮂ' => 'ڍ', 'ﮃ' => 'ڍ', 'ﮄ' => 'ڌ', 'ﮅ' => 'ڌ', 'ﮆ' => 'ڎ', 'ﮇ' => 'ڎ', 'ﮈ' => 'ڈ', 'ﮉ' => 'ڈ', 'ﮊ' => 'ژ', 'ﮋ' => 'ژ', 'ﮌ' => 'ڑ', 'ﮍ' => 'ڑ', 'ﮎ' => 'ک', 'ﮏ' => 'ک', 'ﮐ' => 'ک', 'ﮑ' => 'ک', 'ﮒ' => 'گ', 'ﮓ' => 'گ', 'ﮔ' => 'گ', 'ﮕ' => 'گ', 'ﮖ' => 'ڳ', 'ﮗ' => 'ڳ', 'ﮘ' => 'ڳ', 'ﮙ' => 'ڳ', 'ﮚ' => 'ڱ', 'ﮛ' => 'ڱ', 'ﮜ' => 'ڱ', 'ﮝ' => 'ڱ', 'ﮞ' => 'ں', 'ﮟ' => 'ں', 'ﮠ' => 'ڻ', 'ﮡ' => 'ڻ', 'ﮢ' => 'ڻ', 'ﮣ' => 'ڻ', 'ﮤ' => 'ۀ', 'ﮥ' => 'ۀ', 'ﮦ' => 'ہ', 'ﮧ' => 'ہ', 'ﮨ' => 'ہ', 'ﮩ' => 'ہ', 'ﮪ' => 'ھ', 'ﮫ' => 'ھ', 'ﮬ' => 'ھ', 'ﮭ' => 'ھ', 'ﮮ' => 'ے', 'ﮯ' => 'ے', 'ﮰ' => 'ۓ', 'ﮱ' => 'ۓ', 'ﯓ' => 'ڭ', 'ﯔ' => 'ڭ', 'ﯕ' => 'ڭ', 'ﯖ' => 'ڭ', 'ﯗ' => 'ۇ', 'ﯘ' => 'ۇ', 'ﯙ' => 'ۆ', 'ﯚ' => 'ۆ', 'ﯛ' => 'ۈ', 'ﯜ' => 'ۈ', 'ﯝ' => 'ۇٴ', 'ﯞ' => 'ۋ', 'ﯟ' => 'ۋ', 'ﯠ' => 'ۅ', 'ﯡ' => 'ۅ', 'ﯢ' => 'ۉ', 'ﯣ' => 'ۉ', 'ﯤ' => 'ې', 'ﯥ' => 'ې', 'ﯦ' => 'ې', 'ﯧ' => 'ې', 'ﯨ' => 'ى', 'ﯩ' => 'ى', 'ﯪ' => 'ئا', 'ﯫ' => 'ئا', 'ﯬ' => 'ئە', 'ﯭ' => 'ئە', 'ﯮ' => 'ئو', 'ﯯ' => 'ئو', 'ﯰ' => 'ئۇ', 'ﯱ' => 'ئۇ', 'ﯲ' => 'ئۆ', 'ﯳ' => 'ئۆ', 'ﯴ' => 'ئۈ', 'ﯵ' => 'ئۈ', 'ﯶ' => 'ئې', 'ﯷ' => 'ئې', 'ﯸ' => 'ئې', 'ﯹ' => 'ئى', 'ﯺ' => 'ئى', 'ﯻ' => 'ئى', 'ﯼ' => 'ی', 'ﯽ' => 'ی', 'ﯾ' => 'ی', 'ﯿ' => 'ی', 'ﰀ' => 'ئج', 'ﰁ' => 'ئح', 'ﰂ' => 'ئم', 'ﰃ' => 'ئى', 'ﰄ' => 'ئي', 'ﰅ' => 'بج', 'ﰆ' => 'بح', 'ﰇ' => 'بخ', 'ﰈ' => 'بم', 'ﰉ' => 'بى', 'ﰊ' => 'بي', 'ﰋ' => 'تج', 'ﰌ' => 'تح', 'ﰍ' => 'تخ', 'ﰎ' => 'تم', 'ﰏ' => 'تى', 'ﰐ' => 'تي', 'ﰑ' => 'ثج', 'ﰒ' => 'ثم', 'ﰓ' => 'ثى', 'ﰔ' => 'ثي', 'ﰕ' => 'جح', 'ﰖ' => 'جم', 'ﰗ' => 'حج', 'ﰘ' => 'حم', 'ﰙ' => 'خج', 'ﰚ' => 'خح', 'ﰛ' => 'خم', 'ﰜ' => 'سج', 'ﰝ' => 'سح', 'ﰞ' => 'سخ', 'ﰟ' => 'سم', 'ﰠ' => 'صح', 'ﰡ' => 'صم', 'ﰢ' => 'ضج', 'ﰣ' => 'ضح', 'ﰤ' => 'ضخ', 'ﰥ' => 'ضم', 'ﰦ' => 'طح', 'ﰧ' => 'طم', 'ﰨ' => 'ظم', 'ﰩ' => 'عج', 'ﰪ' => 'عم', 'ﰫ' => 'غج', 'ﰬ' => 'غم', 'ﰭ' => 'فج', 'ﰮ' => 'فح', 'ﰯ' => 'فخ', 'ﰰ' => 'فم', 'ﰱ' => 'فى', 'ﰲ' => 'في', 'ﰳ' => 'قح', 'ﰴ' => 'قم', 'ﰵ' => 'قى', 'ﰶ' => 'قي', 'ﰷ' => 'كا', 'ﰸ' => 'كج', 'ﰹ' => 'كح', 'ﰺ' => 'كخ', 'ﰻ' => 'كل', 'ﰼ' => 'كم', 'ﰽ' => 'كى', 'ﰾ' => 'كي', 'ﰿ' => 'لج', 'ﱀ' => 'لح', 'ﱁ' => 'لخ', 'ﱂ' => 'لم', 'ﱃ' => 'لى', 'ﱄ' => 'لي', 'ﱅ' => 'مج', 'ﱆ' => 'مح', 'ﱇ' => 'مخ', 'ﱈ' => 'مم', 'ﱉ' => 'مى', 'ﱊ' => 'مي', 'ﱋ' => 'نج', 'ﱌ' => 'نح', 'ﱍ' => 'نخ', 'ﱎ' => 'نم', 'ﱏ' => 'نى', 'ﱐ' => 'ني', 'ﱑ' => 'هج', 'ﱒ' => 'هم', 'ﱓ' => 'هى', 'ﱔ' => 'هي', 'ﱕ' => 'يج', 'ﱖ' => 'يح', 'ﱗ' => 'يخ', 'ﱘ' => 'يم', 'ﱙ' => 'يى', 'ﱚ' => 'يي', 'ﱛ' => 'ذٰ', 'ﱜ' => 'رٰ', 'ﱝ' => 'ىٰ', 'ﱞ' => ' ٌّ', 'ﱟ' => ' ٍّ', 'ﱠ' => ' َّ', 'ﱡ' => ' ُّ', 'ﱢ' => ' ِّ', 'ﱣ' => ' ّٰ', 'ﱤ' => 'ئر', 'ﱥ' => 'ئز', 'ﱦ' => 'ئم', 'ﱧ' => 'ئن', 'ﱨ' => 'ئى', 'ﱩ' => 'ئي', 'ﱪ' => 'بر', 'ﱫ' => 'بز', 'ﱬ' => 'بم', 'ﱭ' => 'بن', 'ﱮ' => 'بى', 'ﱯ' => 'بي', 'ﱰ' => 'تر', 'ﱱ' => 'تز', 'ﱲ' => 'تم', 'ﱳ' => 'تن', 'ﱴ' => 'تى', 'ﱵ' => 'تي', 'ﱶ' => 'ثر', 'ﱷ' => 'ثز', 'ﱸ' => 'ثم', 'ﱹ' => 'ثن', 'ﱺ' => 'ثى', 'ﱻ' => 'ثي', 'ﱼ' => 'فى', 'ﱽ' => 'في', 'ﱾ' => 'قى', 'ﱿ' => 'قي', 'ﲀ' => 'كا', 'ﲁ' => 'كل', 'ﲂ' => 'كم', 'ﲃ' => 'كى', 'ﲄ' => 'كي', 'ﲅ' => 'لم', 'ﲆ' => 'لى', 'ﲇ' => 'لي', 'ﲈ' => 'ما', 'ﲉ' => 'مم', 'ﲊ' => 'نر', 'ﲋ' => 'نز', 'ﲌ' => 'نم', 'ﲍ' => 'نن', 'ﲎ' => 'نى', 'ﲏ' => 'ني', 'ﲐ' => 'ىٰ', 'ﲑ' => 'ير', 'ﲒ' => 'يز', 'ﲓ' => 'يم', 'ﲔ' => 'ين', 'ﲕ' => 'يى', 'ﲖ' => 'يي', 'ﲗ' => 'ئج', 'ﲘ' => 'ئح', 'ﲙ' => 'ئخ', 'ﲚ' => 'ئم', 'ﲛ' => 'ئه', 'ﲜ' => 'بج', 'ﲝ' => 'بح', 'ﲞ' => 'بخ', 'ﲟ' => 'بم', 'ﲠ' => 'به', 'ﲡ' => 'تج', 'ﲢ' => 'تح', 'ﲣ' => 'تخ', 'ﲤ' => 'تم', 'ﲥ' => 'ته', 'ﲦ' => 'ثم', 'ﲧ' => 'جح', 'ﲨ' => 'جم', 'ﲩ' => 'حج', 'ﲪ' => 'حم', 'ﲫ' => 'خج', 'ﲬ' => 'خم', 'ﲭ' => 'سج', 'ﲮ' => 'سح', 'ﲯ' => 'سخ', 'ﲰ' => 'سم', 'ﲱ' => 'صح', 'ﲲ' => 'صخ', 'ﲳ' => 'صم', 'ﲴ' => 'ضج', 'ﲵ' => 'ضح', 'ﲶ' => 'ضخ', 'ﲷ' => 'ضم', 'ﲸ' => 'طح', 'ﲹ' => 'ظم', 'ﲺ' => 'عج', 'ﲻ' => 'عم', 'ﲼ' => 'غج', 'ﲽ' => 'غم', 'ﲾ' => 'فج', 'ﲿ' => 'فح', 'ﳀ' => 'فخ', 'ﳁ' => 'فم', 'ﳂ' => 'قح', 'ﳃ' => 'قم', 'ﳄ' => 'كج', 'ﳅ' => 'كح', 'ﳆ' => 'كخ', 'ﳇ' => 'كل', 'ﳈ' => 'كم', 'ﳉ' => 'لج', 'ﳊ' => 'لح', 'ﳋ' => 'لخ', 'ﳌ' => 'لم', 'ﳍ' => 'له', 'ﳎ' => 'مج', 'ﳏ' => 'مح', 'ﳐ' => 'مخ', 'ﳑ' => 'مم', 'ﳒ' => 'نج', 'ﳓ' => 'نح', 'ﳔ' => 'نخ', 'ﳕ' => 'نم', 'ﳖ' => 'نه', 'ﳗ' => 'هج', 'ﳘ' => 'هم', 'ﳙ' => 'هٰ', 'ﳚ' => 'يج', 'ﳛ' => 'يح', 'ﳜ' => 'يخ', 'ﳝ' => 'يم', 'ﳞ' => 'يه', 'ﳟ' => 'ئم', 'ﳠ' => 'ئه', 'ﳡ' => 'بم', 'ﳢ' => 'به', 'ﳣ' => 'تم', 'ﳤ' => 'ته', 'ﳥ' => 'ثم', 'ﳦ' => 'ثه', 'ﳧ' => 'سم', 'ﳨ' => 'سه', 'ﳩ' => 'شم', 'ﳪ' => 'شه', 'ﳫ' => 'كل', 'ﳬ' => 'كم', 'ﳭ' => 'لم', 'ﳮ' => 'نم', 'ﳯ' => 'نه', 'ﳰ' => 'يم', 'ﳱ' => 'يه', 'ﳲ' => 'ـَّ', 'ﳳ' => 'ـُّ', 'ﳴ' => 'ـِّ', 'ﳵ' => 'طى', 'ﳶ' => 'طي', 'ﳷ' => 'عى', 'ﳸ' => 'عي', 'ﳹ' => 'غى', 'ﳺ' => 'غي', 'ﳻ' => 'سى', 'ﳼ' => 'سي', 'ﳽ' => 'شى', 'ﳾ' => 'شي', 'ﳿ' => 'حى', 'ﴀ' => 'حي', 'ﴁ' => 'جى', 'ﴂ' => 'جي', 'ﴃ' => 'خى', 'ﴄ' => 'خي', 'ﴅ' => 'صى', 'ﴆ' => 'صي', 'ﴇ' => 'ضى', 'ﴈ' => 'ضي', 'ﴉ' => 'شج', 'ﴊ' => 'شح', 'ﴋ' => 'شخ', 'ﴌ' => 'شم', 'ﴍ' => 'شر', 'ﴎ' => 'سر', 'ﴏ' => 'صر', 'ﴐ' => 'ضر', 'ﴑ' => 'طى', 'ﴒ' => 'طي', 'ﴓ' => 'عى', 'ﴔ' => 'عي', 'ﴕ' => 'غى', 'ﴖ' => 'غي', 'ﴗ' => 'سى', 'ﴘ' => 'سي', 'ﴙ' => 'شى', 'ﴚ' => 'شي', 'ﴛ' => 'حى', 'ﴜ' => 'حي', 'ﴝ' => 'جى', 'ﴞ' => 'جي', 'ﴟ' => 'خى', 'ﴠ' => 'خي', 'ﴡ' => 'صى', 'ﴢ' => 'صي', 'ﴣ' => 'ضى', 'ﴤ' => 'ضي', 'ﴥ' => 'شج', 'ﴦ' => 'شح', 'ﴧ' => 'شخ', 'ﴨ' => 'شم', 'ﴩ' => 'شر', 'ﴪ' => 'سر', 'ﴫ' => 'صر', 'ﴬ' => 'ضر', 'ﴭ' => 'شج', 'ﴮ' => 'شح', 'ﴯ' => 'شخ', 'ﴰ' => 'شم', 'ﴱ' => 'سه', 'ﴲ' => 'شه', 'ﴳ' => 'طم', 'ﴴ' => 'سج', 'ﴵ' => 'سح', 'ﴶ' => 'سخ', 'ﴷ' => 'شج', 'ﴸ' => 'شح', 'ﴹ' => 'شخ', 'ﴺ' => 'طم', 'ﴻ' => 'ظم', 'ﴼ' => 'اً', 'ﴽ' => 'اً', 'ﵐ' => 'تجم', 'ﵑ' => 'تحج', 'ﵒ' => 'تحج', 'ﵓ' => 'تحم', 'ﵔ' => 'تخم', 'ﵕ' => 'تمج', 'ﵖ' => 'تمح', 'ﵗ' => 'تمخ', 'ﵘ' => 'جمح', 'ﵙ' => 'جمح', 'ﵚ' => 'حمي', 'ﵛ' => 'حمى', 'ﵜ' => 'سحج', 'ﵝ' => 'سجح', 'ﵞ' => 'سجى', 'ﵟ' => 'سمح', 'ﵠ' => 'سمح', 'ﵡ' => 'سمج', 'ﵢ' => 'سمم', 'ﵣ' => 'سمم', 'ﵤ' => 'صحح', 'ﵥ' => 'صحح', 'ﵦ' => 'صمم', 'ﵧ' => 'شحم', 'ﵨ' => 'شحم', 'ﵩ' => 'شجي', 'ﵪ' => 'شمخ', 'ﵫ' => 'شمخ', 'ﵬ' => 'شمم', 'ﵭ' => 'شمم', 'ﵮ' => 'ضحى', 'ﵯ' => 'ضخم', 'ﵰ' => 'ضخم', 'ﵱ' => 'طمح', 'ﵲ' => 'طمح', 'ﵳ' => 'طمم', 'ﵴ' => 'طمي', 'ﵵ' => 'عجم', 'ﵶ' => 'عمم', 'ﵷ' => 'عمم', 'ﵸ' => 'عمى', 'ﵹ' => 'غمم', 'ﵺ' => 'غمي', 'ﵻ' => 'غمى', 'ﵼ' => 'فخم', 'ﵽ' => 'فخم', 'ﵾ' => 'قمح', 'ﵿ' => 'قمم', 'ﶀ' => 'لحم', 'ﶁ' => 'لحي', 'ﶂ' => 'لحى', 'ﶃ' => 'لجج', 'ﶄ' => 'لجج', 'ﶅ' => 'لخم', 'ﶆ' => 'لخم', 'ﶇ' => 'لمح', 'ﶈ' => 'لمح', 'ﶉ' => 'محج', 'ﶊ' => 'محم', 'ﶋ' => 'محي', 'ﶌ' => 'مجح', 'ﶍ' => 'مجم', 'ﶎ' => 'مخج', 'ﶏ' => 'مخم', 'ﶒ' => 'مجخ', 'ﶓ' => 'همج', 'ﶔ' => 'همم', 'ﶕ' => 'نحم', 'ﶖ' => 'نحى', 'ﶗ' => 'نجم', 'ﶘ' => 'نجم', 'ﶙ' => 'نجى', 'ﶚ' => 'نمي', 'ﶛ' => 'نمى', 'ﶜ' => 'يمم', 'ﶝ' => 'يمم', 'ﶞ' => 'بخي', 'ﶟ' => 'تجي', 'ﶠ' => 'تجى', 'ﶡ' => 'تخي', 'ﶢ' => 'تخى', 'ﶣ' => 'تمي', 'ﶤ' => 'تمى', 'ﶥ' => 'جمي', 'ﶦ' => 'جحى', 'ﶧ' => 'جمى', 'ﶨ' => 'سخى', 'ﶩ' => 'صحي', 'ﶪ' => 'شحي', 'ﶫ' => 'ضحي', 'ﶬ' => 'لجي', 'ﶭ' => 'لمي', 'ﶮ' => 'يحي', 'ﶯ' => 'يجي', 'ﶰ' => 'يمي', 'ﶱ' => 'ممي', 'ﶲ' => 'قمي', 'ﶳ' => 'نحي', 'ﶴ' => 'قمح', 'ﶵ' => 'لحم', 'ﶶ' => 'عمي', 'ﶷ' => 'كمي', 'ﶸ' => 'نجح', 'ﶹ' => 'مخي', 'ﶺ' => 'لجم', 'ﶻ' => 'كمم', 'ﶼ' => 'لجم', 'ﶽ' => 'نجح', 'ﶾ' => 'جحي', 'ﶿ' => 'حجي', 'ﷀ' => 'مجي', 'ﷁ' => 'فمي', 'ﷂ' => 'بحي', 'ﷃ' => 'كمم', 'ﷄ' => 'عجم', 'ﷅ' => 'صمم', 'ﷆ' => 'سخي', 'ﷇ' => 'نجي', 'ﷰ' => 'صلے', 'ﷱ' => 'قلے', 'ﷲ' => 'الله', 'ﷳ' => 'اكبر', 'ﷴ' => 'محمد', 'ﷵ' => 'صلعم', 'ﷶ' => 'رسول', 'ﷷ' => 'عليه', 'ﷸ' => 'وسلم', 'ﷹ' => 'صلى', 'ﷺ' => 'صلى الله عليه وسلم', 'ﷻ' => 'جل جلاله', '﷼' => 'ریال', '︐' => ',', '︑' => '、', '︒' => '。', '︓' => ':', '︔' => ';', '︕' => '!', '︖' => '?', '︗' => '〖', '︘' => '〗', '︙' => '...', '︰' => '..', '︱' => '—', '︲' => '–', '︳' => '_', '︴' => '_', '︵' => '(', '︶' => ')', '︷' => '{', '︸' => '}', '︹' => '〔', '︺' => '〕', '︻' => '【', '︼' => '】', '︽' => '《', '︾' => '》', '︿' => '〈', '﹀' => '〉', '﹁' => '「', '﹂' => '」', '﹃' => '『', '﹄' => '』', '﹇' => '[', '﹈' => ']', '﹉' => ' ̅', '﹊' => ' ̅', '﹋' => ' ̅', '﹌' => ' ̅', '﹍' => '_', '﹎' => '_', '﹏' => '_', '﹐' => ',', '﹑' => '、', '﹒' => '.', '﹔' => ';', '﹕' => ':', '﹖' => '?', '﹗' => '!', '﹘' => '—', '﹙' => '(', '﹚' => ')', '﹛' => '{', '﹜' => '}', '﹝' => '〔', '﹞' => '〕', '﹟' => '#', '﹠' => '&', '﹡' => '*', '﹢' => '+', '﹣' => '-', '﹤' => '<', '﹥' => '>', '﹦' => '=', '﹨' => '\\', '﹩' => '$', '﹪' => '%', '﹫' => '@', 'ﹰ' => ' ً', 'ﹱ' => 'ـً', 'ﹲ' => ' ٌ', 'ﹴ' => ' ٍ', 'ﹶ' => ' َ', 'ﹷ' => 'ـَ', 'ﹸ' => ' ُ', 'ﹹ' => 'ـُ', 'ﹺ' => ' ِ', 'ﹻ' => 'ـِ', 'ﹼ' => ' ّ', 'ﹽ' => 'ـّ', 'ﹾ' => ' ْ', 'ﹿ' => 'ـْ', 'ﺀ' => 'ء', 'ﺁ' => 'آ', 'ﺂ' => 'آ', 'ﺃ' => 'أ', 'ﺄ' => 'أ', 'ﺅ' => 'ؤ', 'ﺆ' => 'ؤ', 'ﺇ' => 'إ', 'ﺈ' => 'إ', 'ﺉ' => 'ئ', 'ﺊ' => 'ئ', 'ﺋ' => 'ئ', 'ﺌ' => 'ئ', 'ﺍ' => 'ا', 'ﺎ' => 'ا', 'ﺏ' => 'ب', 'ﺐ' => 'ب', 'ﺑ' => 'ب', 'ﺒ' => 'ب', 'ﺓ' => 'ة', 'ﺔ' => 'ة', 'ﺕ' => 'ت', 'ﺖ' => 'ت', 'ﺗ' => 'ت', 'ﺘ' => 'ت', 'ﺙ' => 'ث', 'ﺚ' => 'ث', 'ﺛ' => 'ث', 'ﺜ' => 'ث', 'ﺝ' => 'ج', 'ﺞ' => 'ج', 'ﺟ' => 'ج', 'ﺠ' => 'ج', 'ﺡ' => 'ح', 'ﺢ' => 'ح', 'ﺣ' => 'ح', 'ﺤ' => 'ح', 'ﺥ' => 'خ', 'ﺦ' => 'خ', 'ﺧ' => 'خ', 'ﺨ' => 'خ', 'ﺩ' => 'د', 'ﺪ' => 'د', 'ﺫ' => 'ذ', 'ﺬ' => 'ذ', 'ﺭ' => 'ر', 'ﺮ' => 'ر', 'ﺯ' => 'ز', 'ﺰ' => 'ز', 'ﺱ' => 'س', 'ﺲ' => 'س', 'ﺳ' => 'س', 'ﺴ' => 'س', 'ﺵ' => 'ش', 'ﺶ' => 'ش', 'ﺷ' => 'ش', 'ﺸ' => 'ش', 'ﺹ' => 'ص', 'ﺺ' => 'ص', 'ﺻ' => 'ص', 'ﺼ' => 'ص', 'ﺽ' => 'ض', 'ﺾ' => 'ض', 'ﺿ' => 'ض', 'ﻀ' => 'ض', 'ﻁ' => 'ط', 'ﻂ' => 'ط', 'ﻃ' => 'ط', 'ﻄ' => 'ط', 'ﻅ' => 'ظ', 'ﻆ' => 'ظ', 'ﻇ' => 'ظ', 'ﻈ' => 'ظ', 'ﻉ' => 'ع', 'ﻊ' => 'ع', 'ﻋ' => 'ع', 'ﻌ' => 'ع', 'ﻍ' => 'غ', 'ﻎ' => 'غ', 'ﻏ' => 'غ', 'ﻐ' => 'غ', 'ﻑ' => 'ف', 'ﻒ' => 'ف', 'ﻓ' => 'ف', 'ﻔ' => 'ف', 'ﻕ' => 'ق', 'ﻖ' => 'ق', 'ﻗ' => 'ق', 'ﻘ' => 'ق', 'ﻙ' => 'ك', 'ﻚ' => 'ك', 'ﻛ' => 'ك', 'ﻜ' => 'ك', 'ﻝ' => 'ل', 'ﻞ' => 'ل', 'ﻟ' => 'ل', 'ﻠ' => 'ل', 'ﻡ' => 'م', 'ﻢ' => 'م', 'ﻣ' => 'م', 'ﻤ' => 'م', 'ﻥ' => 'ن', 'ﻦ' => 'ن', 'ﻧ' => 'ن', 'ﻨ' => 'ن', 'ﻩ' => 'ه', 'ﻪ' => 'ه', 'ﻫ' => 'ه', 'ﻬ' => 'ه', 'ﻭ' => 'و', 'ﻮ' => 'و', 'ﻯ' => 'ى', 'ﻰ' => 'ى', 'ﻱ' => 'ي', 'ﻲ' => 'ي', 'ﻳ' => 'ي', 'ﻴ' => 'ي', 'ﻵ' => 'لآ', 'ﻶ' => 'لآ', 'ﻷ' => 'لأ', 'ﻸ' => 'لأ', 'ﻹ' => 'لإ', 'ﻺ' => 'لإ', 'ﻻ' => 'لا', 'ﻼ' => 'لا', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', ''' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '⦅' => '⦅', '⦆' => '⦆', '。' => '。', '「' => '「', '」' => '」', '、' => '、', '・' => '・', 'ヲ' => 'ヲ', 'ァ' => 'ァ', 'ィ' => 'ィ', 'ゥ' => 'ゥ', 'ェ' => 'ェ', 'ォ' => 'ォ', 'ャ' => 'ャ', 'ュ' => 'ュ', 'ョ' => 'ョ', 'ッ' => 'ッ', 'ー' => 'ー', 'ア' => 'ア', 'イ' => 'イ', 'ウ' => 'ウ', 'エ' => 'エ', 'オ' => 'オ', 'カ' => 'カ', 'キ' => 'キ', 'ク' => 'ク', 'ケ' => 'ケ', 'コ' => 'コ', 'サ' => 'サ', 'シ' => 'シ', 'ス' => 'ス', 'セ' => 'セ', 'ソ' => 'ソ', 'タ' => 'タ', 'チ' => 'チ', 'ツ' => 'ツ', 'テ' => 'テ', 'ト' => 'ト', 'ナ' => 'ナ', 'ニ' => 'ニ', 'ヌ' => 'ヌ', 'ネ' => 'ネ', 'ノ' => 'ノ', 'ハ' => 'ハ', 'ヒ' => 'ヒ', 'フ' => 'フ', 'ヘ' => 'ヘ', 'ホ' => 'ホ', 'マ' => 'マ', 'ミ' => 'ミ', 'ム' => 'ム', 'メ' => 'メ', 'モ' => 'モ', 'ヤ' => 'ヤ', 'ユ' => 'ユ', 'ヨ' => 'ヨ', 'ラ' => 'ラ', 'リ' => 'リ', 'ル' => 'ル', 'レ' => 'レ', 'ロ' => 'ロ', 'ワ' => 'ワ', 'ン' => 'ン', '゙' => '゙', '゚' => '゚', 'ᅠ' => 'ᅠ', 'ᄀ' => 'ᄀ', 'ᄁ' => 'ᄁ', 'ᆪ' => 'ᆪ', 'ᄂ' => 'ᄂ', 'ᆬ' => 'ᆬ', 'ᆭ' => 'ᆭ', 'ᄃ' => 'ᄃ', 'ᄄ' => 'ᄄ', 'ᄅ' => 'ᄅ', 'ᆰ' => 'ᆰ', 'ᆱ' => 'ᆱ', 'ᆲ' => 'ᆲ', 'ᆳ' => 'ᆳ', 'ᆴ' => 'ᆴ', 'ᆵ' => 'ᆵ', 'ᄚ' => 'ᄚ', 'ᄆ' => 'ᄆ', 'ᄇ' => 'ᄇ', 'ᄈ' => 'ᄈ', 'ᄡ' => 'ᄡ', 'ᄉ' => 'ᄉ', 'ᄊ' => 'ᄊ', 'ᄋ' => 'ᄋ', 'ᄌ' => 'ᄌ', 'ᄍ' => 'ᄍ', 'ᄎ' => 'ᄎ', 'ᄏ' => 'ᄏ', 'ᄐ' => 'ᄐ', 'ᄑ' => 'ᄑ', 'ᄒ' => 'ᄒ', 'ᅡ' => 'ᅡ', 'ᅢ' => 'ᅢ', 'ᅣ' => 'ᅣ', 'ᅤ' => 'ᅤ', 'ᅥ' => 'ᅥ', 'ᅦ' => 'ᅦ', 'ᅧ' => 'ᅧ', 'ᅨ' => 'ᅨ', 'ᅩ' => 'ᅩ', 'ᅪ' => 'ᅪ', 'ᅫ' => 'ᅫ', 'ᅬ' => 'ᅬ', 'ᅭ' => 'ᅭ', 'ᅮ' => 'ᅮ', 'ᅯ' => 'ᅯ', 'ᅰ' => 'ᅰ', 'ᅱ' => 'ᅱ', 'ᅲ' => 'ᅲ', 'ᅳ' => 'ᅳ', 'ᅴ' => 'ᅴ', 'ᅵ' => 'ᅵ', '¢' => '¢', '£' => '£', '¬' => '¬', ' ̄' => ' ̄', '¦' => '¦', '¥' => '¥', '₩' => '₩', '│' => '│', '←' => '←', '↑' => '↑', '→' => '→', '↓' => '↓', '■' => '■', '○' => '○', '𝐀' => 'A', '𝐁' => 'B', '𝐂' => 'C', '𝐃' => 'D', '𝐄' => 'E', '𝐅' => 'F', '𝐆' => 'G', '𝐇' => 'H', '𝐈' => 'I', '𝐉' => 'J', '𝐊' => 'K', '𝐋' => 'L', '𝐌' => 'M', '𝐍' => 'N', '𝐎' => 'O', '𝐏' => 'P', '𝐐' => 'Q', '𝐑' => 'R', '𝐒' => 'S', '𝐓' => 'T', '𝐔' => 'U', '𝐕' => 'V', '𝐖' => 'W', '𝐗' => 'X', '𝐘' => 'Y', '𝐙' => 'Z', '𝐚' => 'a', '𝐛' => 'b', '𝐜' => 'c', '𝐝' => 'd', '𝐞' => 'e', '𝐟' => 'f', '𝐠' => 'g', '𝐡' => 'h', '𝐢' => 'i', '𝐣' => 'j', '𝐤' => 'k', '𝐥' => 'l', '𝐦' => 'm', '𝐧' => 'n', '𝐨' => 'o', '𝐩' => 'p', '𝐪' => 'q', '𝐫' => 'r', '𝐬' => 's', '𝐭' => 't', '𝐮' => 'u', '𝐯' => 'v', '𝐰' => 'w', '𝐱' => 'x', '𝐲' => 'y', '𝐳' => 'z', '𝐴' => 'A', '𝐵' => 'B', '𝐶' => 'C', '𝐷' => 'D', '𝐸' => 'E', '𝐹' => 'F', '𝐺' => 'G', '𝐻' => 'H', '𝐼' => 'I', '𝐽' => 'J', '𝐾' => 'K', '𝐿' => 'L', '𝑀' => 'M', '𝑁' => 'N', '𝑂' => 'O', '𝑃' => 'P', '𝑄' => 'Q', '𝑅' => 'R', '𝑆' => 'S', '𝑇' => 'T', '𝑈' => 'U', '𝑉' => 'V', '𝑊' => 'W', '𝑋' => 'X', '𝑌' => 'Y', '𝑍' => 'Z', '𝑎' => 'a', '𝑏' => 'b', '𝑐' => 'c', '𝑑' => 'd', '𝑒' => 'e', '𝑓' => 'f', '𝑔' => 'g', '𝑖' => 'i', '𝑗' => 'j', '𝑘' => 'k', '𝑙' => 'l', '𝑚' => 'm', '𝑛' => 'n', '𝑜' => 'o', '𝑝' => 'p', '𝑞' => 'q', '𝑟' => 'r', '𝑠' => 's', '𝑡' => 't', '𝑢' => 'u', '𝑣' => 'v', '𝑤' => 'w', '𝑥' => 'x', '𝑦' => 'y', '𝑧' => 'z', '𝑨' => 'A', '𝑩' => 'B', '𝑪' => 'C', '𝑫' => 'D', '𝑬' => 'E', '𝑭' => 'F', '𝑮' => 'G', '𝑯' => 'H', '𝑰' => 'I', '𝑱' => 'J', '𝑲' => 'K', '𝑳' => 'L', '𝑴' => 'M', '𝑵' => 'N', '𝑶' => 'O', '𝑷' => 'P', '𝑸' => 'Q', '𝑹' => 'R', '𝑺' => 'S', '𝑻' => 'T', '𝑼' => 'U', '𝑽' => 'V', '𝑾' => 'W', '𝑿' => 'X', '𝒀' => 'Y', '𝒁' => 'Z', '𝒂' => 'a', '𝒃' => 'b', '𝒄' => 'c', '𝒅' => 'd', '𝒆' => 'e', '𝒇' => 'f', '𝒈' => 'g', '𝒉' => 'h', '𝒊' => 'i', '𝒋' => 'j', '𝒌' => 'k', '𝒍' => 'l', '𝒎' => 'm', '𝒏' => 'n', '𝒐' => 'o', '𝒑' => 'p', '𝒒' => 'q', '𝒓' => 'r', '𝒔' => 's', '𝒕' => 't', '𝒖' => 'u', '𝒗' => 'v', '𝒘' => 'w', '𝒙' => 'x', '𝒚' => 'y', '𝒛' => 'z', '𝒜' => 'A', '𝒞' => 'C', '𝒟' => 'D', '𝒢' => 'G', '𝒥' => 'J', '𝒦' => 'K', '𝒩' => 'N', '𝒪' => 'O', '𝒫' => 'P', '𝒬' => 'Q', '𝒮' => 'S', '𝒯' => 'T', '𝒰' => 'U', '𝒱' => 'V', '𝒲' => 'W', '𝒳' => 'X', '𝒴' => 'Y', '𝒵' => 'Z', '𝒶' => 'a', '𝒷' => 'b', '𝒸' => 'c', '𝒹' => 'd', '𝒻' => 'f', '𝒽' => 'h', '𝒾' => 'i', '𝒿' => 'j', '𝓀' => 'k', '𝓁' => 'l', '𝓂' => 'm', '𝓃' => 'n', '𝓅' => 'p', '𝓆' => 'q', '𝓇' => 'r', '𝓈' => 's', '𝓉' => 't', '𝓊' => 'u', '𝓋' => 'v', '𝓌' => 'w', '𝓍' => 'x', '𝓎' => 'y', '𝓏' => 'z', '𝓐' => 'A', '𝓑' => 'B', '𝓒' => 'C', '𝓓' => 'D', '𝓔' => 'E', '𝓕' => 'F', '𝓖' => 'G', '𝓗' => 'H', '𝓘' => 'I', '𝓙' => 'J', '𝓚' => 'K', '𝓛' => 'L', '𝓜' => 'M', '𝓝' => 'N', '𝓞' => 'O', '𝓟' => 'P', '𝓠' => 'Q', '𝓡' => 'R', '𝓢' => 'S', '𝓣' => 'T', '𝓤' => 'U', '𝓥' => 'V', '𝓦' => 'W', '𝓧' => 'X', '𝓨' => 'Y', '𝓩' => 'Z', '𝓪' => 'a', '𝓫' => 'b', '𝓬' => 'c', '𝓭' => 'd', '𝓮' => 'e', '𝓯' => 'f', '𝓰' => 'g', '𝓱' => 'h', '𝓲' => 'i', '𝓳' => 'j', '𝓴' => 'k', '𝓵' => 'l', '𝓶' => 'm', '𝓷' => 'n', '𝓸' => 'o', '𝓹' => 'p', '𝓺' => 'q', '𝓻' => 'r', '𝓼' => 's', '𝓽' => 't', '𝓾' => 'u', '𝓿' => 'v', '𝔀' => 'w', '𝔁' => 'x', '𝔂' => 'y', '𝔃' => 'z', '𝔄' => 'A', '𝔅' => 'B', '𝔇' => 'D', '𝔈' => 'E', '𝔉' => 'F', '𝔊' => 'G', '𝔍' => 'J', '𝔎' => 'K', '𝔏' => 'L', '𝔐' => 'M', '𝔑' => 'N', '𝔒' => 'O', '𝔓' => 'P', '𝔔' => 'Q', '𝔖' => 'S', '𝔗' => 'T', '𝔘' => 'U', '𝔙' => 'V', '𝔚' => 'W', '𝔛' => 'X', '𝔜' => 'Y', '𝔞' => 'a', '𝔟' => 'b', '𝔠' => 'c', '𝔡' => 'd', '𝔢' => 'e', '𝔣' => 'f', '𝔤' => 'g', '𝔥' => 'h', '𝔦' => 'i', '𝔧' => 'j', '𝔨' => 'k', '𝔩' => 'l', '𝔪' => 'm', '𝔫' => 'n', '𝔬' => 'o', '𝔭' => 'p', '𝔮' => 'q', '𝔯' => 'r', '𝔰' => 's', '𝔱' => 't', '𝔲' => 'u', '𝔳' => 'v', '𝔴' => 'w', '𝔵' => 'x', '𝔶' => 'y', '𝔷' => 'z', '𝔸' => 'A', '𝔹' => 'B', '𝔻' => 'D', '𝔼' => 'E', '𝔽' => 'F', '𝔾' => 'G', '𝕀' => 'I', '𝕁' => 'J', '𝕂' => 'K', '𝕃' => 'L', '𝕄' => 'M', '𝕆' => 'O', '𝕊' => 'S', '𝕋' => 'T', '𝕌' => 'U', '𝕍' => 'V', '𝕎' => 'W', '𝕏' => 'X', '𝕐' => 'Y', '𝕒' => 'a', '𝕓' => 'b', '𝕔' => 'c', '𝕕' => 'd', '𝕖' => 'e', '𝕗' => 'f', '𝕘' => 'g', '𝕙' => 'h', '𝕚' => 'i', '𝕛' => 'j', '𝕜' => 'k', '𝕝' => 'l', '𝕞' => 'm', '𝕟' => 'n', '𝕠' => 'o', '𝕡' => 'p', '𝕢' => 'q', '𝕣' => 'r', '𝕤' => 's', '𝕥' => 't', '𝕦' => 'u', '𝕧' => 'v', '𝕨' => 'w', '𝕩' => 'x', '𝕪' => 'y', '𝕫' => 'z', '𝕬' => 'A', '𝕭' => 'B', '𝕮' => 'C', '𝕯' => 'D', '𝕰' => 'E', '𝕱' => 'F', '𝕲' => 'G', '𝕳' => 'H', '𝕴' => 'I', '𝕵' => 'J', '𝕶' => 'K', '𝕷' => 'L', '𝕸' => 'M', '𝕹' => 'N', '𝕺' => 'O', '𝕻' => 'P', '𝕼' => 'Q', '𝕽' => 'R', '𝕾' => 'S', '𝕿' => 'T', '𝖀' => 'U', '𝖁' => 'V', '𝖂' => 'W', '𝖃' => 'X', '𝖄' => 'Y', '𝖅' => 'Z', '𝖆' => 'a', '𝖇' => 'b', '𝖈' => 'c', '𝖉' => 'd', '𝖊' => 'e', '𝖋' => 'f', '𝖌' => 'g', '𝖍' => 'h', '𝖎' => 'i', '𝖏' => 'j', '𝖐' => 'k', '𝖑' => 'l', '𝖒' => 'm', '𝖓' => 'n', '𝖔' => 'o', '𝖕' => 'p', '𝖖' => 'q', '𝖗' => 'r', '𝖘' => 's', '𝖙' => 't', '𝖚' => 'u', '𝖛' => 'v', '𝖜' => 'w', '𝖝' => 'x', '𝖞' => 'y', '𝖟' => 'z', '𝖠' => 'A', '𝖡' => 'B', '𝖢' => 'C', '𝖣' => 'D', '𝖤' => 'E', '𝖥' => 'F', '𝖦' => 'G', '𝖧' => 'H', '𝖨' => 'I', '𝖩' => 'J', '𝖪' => 'K', '𝖫' => 'L', '𝖬' => 'M', '𝖭' => 'N', '𝖮' => 'O', '𝖯' => 'P', '𝖰' => 'Q', '𝖱' => 'R', '𝖲' => 'S', '𝖳' => 'T', '𝖴' => 'U', '𝖵' => 'V', '𝖶' => 'W', '𝖷' => 'X', '𝖸' => 'Y', '𝖹' => 'Z', '𝖺' => 'a', '𝖻' => 'b', '𝖼' => 'c', '𝖽' => 'd', '𝖾' => 'e', '𝖿' => 'f', '𝗀' => 'g', '𝗁' => 'h', '𝗂' => 'i', '𝗃' => 'j', '𝗄' => 'k', '𝗅' => 'l', '𝗆' => 'm', '𝗇' => 'n', '𝗈' => 'o', '𝗉' => 'p', '𝗊' => 'q', '𝗋' => 'r', '𝗌' => 's', '𝗍' => 't', '𝗎' => 'u', '𝗏' => 'v', '𝗐' => 'w', '𝗑' => 'x', '𝗒' => 'y', '𝗓' => 'z', '𝗔' => 'A', '𝗕' => 'B', '𝗖' => 'C', '𝗗' => 'D', '𝗘' => 'E', '𝗙' => 'F', '𝗚' => 'G', '𝗛' => 'H', '𝗜' => 'I', '𝗝' => 'J', '𝗞' => 'K', '𝗟' => 'L', '𝗠' => 'M', '𝗡' => 'N', '𝗢' => 'O', '𝗣' => 'P', '𝗤' => 'Q', '𝗥' => 'R', '𝗦' => 'S', '𝗧' => 'T', '𝗨' => 'U', '𝗩' => 'V', '𝗪' => 'W', '𝗫' => 'X', '𝗬' => 'Y', '𝗭' => 'Z', '𝗮' => 'a', '𝗯' => 'b', '𝗰' => 'c', '𝗱' => 'd', '𝗲' => 'e', '𝗳' => 'f', '𝗴' => 'g', '𝗵' => 'h', '𝗶' => 'i', '𝗷' => 'j', '𝗸' => 'k', '𝗹' => 'l', '𝗺' => 'm', '𝗻' => 'n', '𝗼' => 'o', '𝗽' => 'p', '𝗾' => 'q', '𝗿' => 'r', '𝘀' => 's', '𝘁' => 't', '𝘂' => 'u', '𝘃' => 'v', '𝘄' => 'w', '𝘅' => 'x', '𝘆' => 'y', '𝘇' => 'z', '𝘈' => 'A', '𝘉' => 'B', '𝘊' => 'C', '𝘋' => 'D', '𝘌' => 'E', '𝘍' => 'F', '𝘎' => 'G', '𝘏' => 'H', '𝘐' => 'I', '𝘑' => 'J', '𝘒' => 'K', '𝘓' => 'L', '𝘔' => 'M', '𝘕' => 'N', '𝘖' => 'O', '𝘗' => 'P', '𝘘' => 'Q', '𝘙' => 'R', '𝘚' => 'S', '𝘛' => 'T', '𝘜' => 'U', '𝘝' => 'V', '𝘞' => 'W', '𝘟' => 'X', '𝘠' => 'Y', '𝘡' => 'Z', '𝘢' => 'a', '𝘣' => 'b', '𝘤' => 'c', '𝘥' => 'd', '𝘦' => 'e', '𝘧' => 'f', '𝘨' => 'g', '𝘩' => 'h', '𝘪' => 'i', '𝘫' => 'j', '𝘬' => 'k', '𝘭' => 'l', '𝘮' => 'm', '𝘯' => 'n', '𝘰' => 'o', '𝘱' => 'p', '𝘲' => 'q', '𝘳' => 'r', '𝘴' => 's', '𝘵' => 't', '𝘶' => 'u', '𝘷' => 'v', '𝘸' => 'w', '𝘹' => 'x', '𝘺' => 'y', '𝘻' => 'z', '𝘼' => 'A', '𝘽' => 'B', '𝘾' => 'C', '𝘿' => 'D', '𝙀' => 'E', '𝙁' => 'F', '𝙂' => 'G', '𝙃' => 'H', '𝙄' => 'I', '𝙅' => 'J', '𝙆' => 'K', '𝙇' => 'L', '𝙈' => 'M', '𝙉' => 'N', '𝙊' => 'O', '𝙋' => 'P', '𝙌' => 'Q', '𝙍' => 'R', '𝙎' => 'S', '𝙏' => 'T', '𝙐' => 'U', '𝙑' => 'V', '𝙒' => 'W', '𝙓' => 'X', '𝙔' => 'Y', '𝙕' => 'Z', '𝙖' => 'a', '𝙗' => 'b', '𝙘' => 'c', '𝙙' => 'd', '𝙚' => 'e', '𝙛' => 'f', '𝙜' => 'g', '𝙝' => 'h', '𝙞' => 'i', '𝙟' => 'j', '𝙠' => 'k', '𝙡' => 'l', '𝙢' => 'm', '𝙣' => 'n', '𝙤' => 'o', '𝙥' => 'p', '𝙦' => 'q', '𝙧' => 'r', '𝙨' => 's', '𝙩' => 't', '𝙪' => 'u', '𝙫' => 'v', '𝙬' => 'w', '𝙭' => 'x', '𝙮' => 'y', '𝙯' => 'z', '𝙰' => 'A', '𝙱' => 'B', '𝙲' => 'C', '𝙳' => 'D', '𝙴' => 'E', '𝙵' => 'F', '𝙶' => 'G', '𝙷' => 'H', '𝙸' => 'I', '𝙹' => 'J', '𝙺' => 'K', '𝙻' => 'L', '𝙼' => 'M', '𝙽' => 'N', '𝙾' => 'O', '𝙿' => 'P', '𝚀' => 'Q', '𝚁' => 'R', '𝚂' => 'S', '𝚃' => 'T', '𝚄' => 'U', '𝚅' => 'V', '𝚆' => 'W', '𝚇' => 'X', '𝚈' => 'Y', '𝚉' => 'Z', '𝚊' => 'a', '𝚋' => 'b', '𝚌' => 'c', '𝚍' => 'd', '𝚎' => 'e', '𝚏' => 'f', '𝚐' => 'g', '𝚑' => 'h', '𝚒' => 'i', '𝚓' => 'j', '𝚔' => 'k', '𝚕' => 'l', '𝚖' => 'm', '𝚗' => 'n', '𝚘' => 'o', '𝚙' => 'p', '𝚚' => 'q', '𝚛' => 'r', '𝚜' => 's', '𝚝' => 't', '𝚞' => 'u', '𝚟' => 'v', '𝚠' => 'w', '𝚡' => 'x', '𝚢' => 'y', '𝚣' => 'z', '𝚤' => 'ı', '𝚥' => 'ȷ', '𝚨' => 'Α', '𝚩' => 'Β', '𝚪' => 'Γ', '𝚫' => 'Δ', '𝚬' => 'Ε', '𝚭' => 'Ζ', '𝚮' => 'Η', '𝚯' => 'Θ', '𝚰' => 'Ι', '𝚱' => 'Κ', '𝚲' => 'Λ', '𝚳' => 'Μ', '𝚴' => 'Ν', '𝚵' => 'Ξ', '𝚶' => 'Ο', '𝚷' => 'Π', '𝚸' => 'Ρ', '𝚹' => 'Θ', '𝚺' => 'Σ', '𝚻' => 'Τ', '𝚼' => 'Υ', '𝚽' => 'Φ', '𝚾' => 'Χ', '𝚿' => 'Ψ', '𝛀' => 'Ω', '𝛁' => '∇', '𝛂' => 'α', '𝛃' => 'β', '𝛄' => 'γ', '𝛅' => 'δ', '𝛆' => 'ε', '𝛇' => 'ζ', '𝛈' => 'η', '𝛉' => 'θ', '𝛊' => 'ι', '𝛋' => 'κ', '𝛌' => 'λ', '𝛍' => 'μ', '𝛎' => 'ν', '𝛏' => 'ξ', '𝛐' => 'ο', '𝛑' => 'π', '𝛒' => 'ρ', '𝛓' => 'ς', '𝛔' => 'σ', '𝛕' => 'τ', '𝛖' => 'υ', '𝛗' => 'φ', '𝛘' => 'χ', '𝛙' => 'ψ', '𝛚' => 'ω', '𝛛' => '∂', '𝛜' => 'ε', '𝛝' => 'θ', '𝛞' => 'κ', '𝛟' => 'φ', '𝛠' => 'ρ', '𝛡' => 'π', '𝛢' => 'Α', '𝛣' => 'Β', '𝛤' => 'Γ', '𝛥' => 'Δ', '𝛦' => 'Ε', '𝛧' => 'Ζ', '𝛨' => 'Η', '𝛩' => 'Θ', '𝛪' => 'Ι', '𝛫' => 'Κ', '𝛬' => 'Λ', '𝛭' => 'Μ', '𝛮' => 'Ν', '𝛯' => 'Ξ', '𝛰' => 'Ο', '𝛱' => 'Π', '𝛲' => 'Ρ', '𝛳' => 'Θ', '𝛴' => 'Σ', '𝛵' => 'Τ', '𝛶' => 'Υ', '𝛷' => 'Φ', '𝛸' => 'Χ', '𝛹' => 'Ψ', '𝛺' => 'Ω', '𝛻' => '∇', '𝛼' => 'α', '𝛽' => 'β', '𝛾' => 'γ', '𝛿' => 'δ', '𝜀' => 'ε', '𝜁' => 'ζ', '𝜂' => 'η', '𝜃' => 'θ', '𝜄' => 'ι', '𝜅' => 'κ', '𝜆' => 'λ', '𝜇' => 'μ', '𝜈' => 'ν', '𝜉' => 'ξ', '𝜊' => 'ο', '𝜋' => 'π', '𝜌' => 'ρ', '𝜍' => 'ς', '𝜎' => 'σ', '𝜏' => 'τ', '𝜐' => 'υ', '𝜑' => 'φ', '𝜒' => 'χ', '𝜓' => 'ψ', '𝜔' => 'ω', '𝜕' => '∂', '𝜖' => 'ε', '𝜗' => 'θ', '𝜘' => 'κ', '𝜙' => 'φ', '𝜚' => 'ρ', '𝜛' => 'π', '𝜜' => 'Α', '𝜝' => 'Β', '𝜞' => 'Γ', '𝜟' => 'Δ', '𝜠' => 'Ε', '𝜡' => 'Ζ', '𝜢' => 'Η', '𝜣' => 'Θ', '𝜤' => 'Ι', '𝜥' => 'Κ', '𝜦' => 'Λ', '𝜧' => 'Μ', '𝜨' => 'Ν', '𝜩' => 'Ξ', '𝜪' => 'Ο', '𝜫' => 'Π', '𝜬' => 'Ρ', '𝜭' => 'Θ', '𝜮' => 'Σ', '𝜯' => 'Τ', '𝜰' => 'Υ', '𝜱' => 'Φ', '𝜲' => 'Χ', '𝜳' => 'Ψ', '𝜴' => 'Ω', '𝜵' => '∇', '𝜶' => 'α', '𝜷' => 'β', '𝜸' => 'γ', '𝜹' => 'δ', '𝜺' => 'ε', '𝜻' => 'ζ', '𝜼' => 'η', '𝜽' => 'θ', '𝜾' => 'ι', '𝜿' => 'κ', '𝝀' => 'λ', '𝝁' => 'μ', '𝝂' => 'ν', '𝝃' => 'ξ', '𝝄' => 'ο', '𝝅' => 'π', '𝝆' => 'ρ', '𝝇' => 'ς', '𝝈' => 'σ', '𝝉' => 'τ', '𝝊' => 'υ', '𝝋' => 'φ', '𝝌' => 'χ', '𝝍' => 'ψ', '𝝎' => 'ω', '𝝏' => '∂', '𝝐' => 'ε', '𝝑' => 'θ', '𝝒' => 'κ', '𝝓' => 'φ', '𝝔' => 'ρ', '𝝕' => 'π', '𝝖' => 'Α', '𝝗' => 'Β', '𝝘' => 'Γ', '𝝙' => 'Δ', '𝝚' => 'Ε', '𝝛' => 'Ζ', '𝝜' => 'Η', '𝝝' => 'Θ', '𝝞' => 'Ι', '𝝟' => 'Κ', '𝝠' => 'Λ', '𝝡' => 'Μ', '𝝢' => 'Ν', '𝝣' => 'Ξ', '𝝤' => 'Ο', '𝝥' => 'Π', '𝝦' => 'Ρ', '𝝧' => 'Θ', '𝝨' => 'Σ', '𝝩' => 'Τ', '𝝪' => 'Υ', '𝝫' => 'Φ', '𝝬' => 'Χ', '𝝭' => 'Ψ', '𝝮' => 'Ω', '𝝯' => '∇', '𝝰' => 'α', '𝝱' => 'β', '𝝲' => 'γ', '𝝳' => 'δ', '𝝴' => 'ε', '𝝵' => 'ζ', '𝝶' => 'η', '𝝷' => 'θ', '𝝸' => 'ι', '𝝹' => 'κ', '𝝺' => 'λ', '𝝻' => 'μ', '𝝼' => 'ν', '𝝽' => 'ξ', '𝝾' => 'ο', '𝝿' => 'π', '𝞀' => 'ρ', '𝞁' => 'ς', '𝞂' => 'σ', '𝞃' => 'τ', '𝞄' => 'υ', '𝞅' => 'φ', '𝞆' => 'χ', '𝞇' => 'ψ', '𝞈' => 'ω', '𝞉' => '∂', '𝞊' => 'ε', '𝞋' => 'θ', '𝞌' => 'κ', '𝞍' => 'φ', '𝞎' => 'ρ', '𝞏' => 'π', '𝞐' => 'Α', '𝞑' => 'Β', '𝞒' => 'Γ', '𝞓' => 'Δ', '𝞔' => 'Ε', '𝞕' => 'Ζ', '𝞖' => 'Η', '𝞗' => 'Θ', '𝞘' => 'Ι', '𝞙' => 'Κ', '𝞚' => 'Λ', '𝞛' => 'Μ', '𝞜' => 'Ν', '𝞝' => 'Ξ', '𝞞' => 'Ο', '𝞟' => 'Π', '𝞠' => 'Ρ', '𝞡' => 'Θ', '𝞢' => 'Σ', '𝞣' => 'Τ', '𝞤' => 'Υ', '𝞥' => 'Φ', '𝞦' => 'Χ', '𝞧' => 'Ψ', '𝞨' => 'Ω', '𝞩' => '∇', '𝞪' => 'α', '𝞫' => 'β', '𝞬' => 'γ', '𝞭' => 'δ', '𝞮' => 'ε', '𝞯' => 'ζ', '𝞰' => 'η', '𝞱' => 'θ', '𝞲' => 'ι', '𝞳' => 'κ', '𝞴' => 'λ', '𝞵' => 'μ', '𝞶' => 'ν', '𝞷' => 'ξ', '𝞸' => 'ο', '𝞹' => 'π', '𝞺' => 'ρ', '𝞻' => 'ς', '𝞼' => 'σ', '𝞽' => 'τ', '𝞾' => 'υ', '𝞿' => 'φ', '𝟀' => 'χ', '𝟁' => 'ψ', '𝟂' => 'ω', '𝟃' => '∂', '𝟄' => 'ε', '𝟅' => 'θ', '𝟆' => 'κ', '𝟇' => 'φ', '𝟈' => 'ρ', '𝟉' => 'π', '𝟊' => 'Ϝ', '𝟋' => 'ϝ', '𝟎' => '0', '𝟏' => '1', '𝟐' => '2', '𝟑' => '3', '𝟒' => '4', '𝟓' => '5', '𝟔' => '6', '𝟕' => '7', '𝟖' => '8', '𝟗' => '9', '𝟘' => '0', '𝟙' => '1', '𝟚' => '2', '𝟛' => '3', '𝟜' => '4', '𝟝' => '5', '𝟞' => '6', '𝟟' => '7', '𝟠' => '8', '𝟡' => '9', '𝟢' => '0', '𝟣' => '1', '𝟤' => '2', '𝟥' => '3', '𝟦' => '4', '𝟧' => '5', '𝟨' => '6', '𝟩' => '7', '𝟪' => '8', '𝟫' => '9', '𝟬' => '0', '𝟭' => '1', '𝟮' => '2', '𝟯' => '3', '𝟰' => '4', '𝟱' => '5', '𝟲' => '6', '𝟳' => '7', '𝟴' => '8', '𝟵' => '9', '𝟶' => '0', '𝟷' => '1', '𝟸' => '2', '𝟹' => '3', '𝟺' => '4', '𝟻' => '5', '𝟼' => '6', '𝟽' => '7', '𝟾' => '8', '𝟿' => '9', '𞸀' => 'ا', '𞸁' => 'ب', '𞸂' => 'ج', '𞸃' => 'د', '𞸅' => 'و', '𞸆' => 'ز', '𞸇' => 'ح', '𞸈' => 'ط', '𞸉' => 'ي', '𞸊' => 'ك', '𞸋' => 'ل', '𞸌' => 'م', '𞸍' => 'ن', '𞸎' => 'س', '𞸏' => 'ع', '𞸐' => 'ف', '𞸑' => 'ص', '𞸒' => 'ق', '𞸓' => 'ر', '𞸔' => 'ش', '𞸕' => 'ت', '𞸖' => 'ث', '𞸗' => 'خ', '𞸘' => 'ذ', '𞸙' => 'ض', '𞸚' => 'ظ', '𞸛' => 'غ', '𞸜' => 'ٮ', '𞸝' => 'ں', '𞸞' => 'ڡ', '𞸟' => 'ٯ', '𞸡' => 'ب', '𞸢' => 'ج', '𞸤' => 'ه', '𞸧' => 'ح', '𞸩' => 'ي', '𞸪' => 'ك', '𞸫' => 'ل', '𞸬' => 'م', '𞸭' => 'ن', '𞸮' => 'س', '𞸯' => 'ع', '𞸰' => 'ف', '𞸱' => 'ص', '𞸲' => 'ق', '𞸴' => 'ش', '𞸵' => 'ت', '𞸶' => 'ث', '𞸷' => 'خ', '𞸹' => 'ض', '𞸻' => 'غ', '𞹂' => 'ج', '𞹇' => 'ح', '𞹉' => 'ي', '𞹋' => 'ل', '𞹍' => 'ن', '𞹎' => 'س', '𞹏' => 'ع', '𞹑' => 'ص', '𞹒' => 'ق', '𞹔' => 'ش', '𞹗' => 'خ', '𞹙' => 'ض', '𞹛' => 'غ', '𞹝' => 'ں', '𞹟' => 'ٯ', '𞹡' => 'ب', '𞹢' => 'ج', '𞹤' => 'ه', '𞹧' => 'ح', '𞹨' => 'ط', '𞹩' => 'ي', '𞹪' => 'ك', '𞹬' => 'م', '𞹭' => 'ن', '𞹮' => 'س', '𞹯' => 'ع', '𞹰' => 'ف', '𞹱' => 'ص', '𞹲' => 'ق', '𞹴' => 'ش', '𞹵' => 'ت', '𞹶' => 'ث', '𞹷' => 'خ', '𞹹' => 'ض', '𞹺' => 'ظ', '𞹻' => 'غ', '𞹼' => 'ٮ', '𞹾' => 'ڡ', '𞺀' => 'ا', '𞺁' => 'ب', '𞺂' => 'ج', '𞺃' => 'د', '𞺄' => 'ه', '𞺅' => 'و', '𞺆' => 'ز', '𞺇' => 'ح', '𞺈' => 'ط', '𞺉' => 'ي', '𞺋' => 'ل', '𞺌' => 'م', '𞺍' => 'ن', '𞺎' => 'س', '𞺏' => 'ع', '𞺐' => 'ف', '𞺑' => 'ص', '𞺒' => 'ق', '𞺓' => 'ر', '𞺔' => 'ش', '𞺕' => 'ت', '𞺖' => 'ث', '𞺗' => 'خ', '𞺘' => 'ذ', '𞺙' => 'ض', '𞺚' => 'ظ', '𞺛' => 'غ', '𞺡' => 'ب', '𞺢' => 'ج', '𞺣' => 'د', '𞺥' => 'و', '𞺦' => 'ز', '𞺧' => 'ح', '𞺨' => 'ط', '𞺩' => 'ي', '𞺫' => 'ل', '𞺬' => 'م', '𞺭' => 'ن', '𞺮' => 'س', '𞺯' => 'ع', '𞺰' => 'ف', '𞺱' => 'ص', '𞺲' => 'ق', '𞺳' => 'ر', '𞺴' => 'ش', '𞺵' => 'ت', '𞺶' => 'ث', '𞺷' => 'خ', '𞺸' => 'ذ', '𞺹' => 'ض', '𞺺' => 'ظ', '𞺻' => 'غ', '🄀' => '0.', '🄁' => '0,', '🄂' => '1,', '🄃' => '2,', '🄄' => '3,', '🄅' => '4,', '🄆' => '5,', '🄇' => '6,', '🄈' => '7,', '🄉' => '8,', '🄊' => '9,', '🄐' => '(A)', '🄑' => '(B)', '🄒' => '(C)', '🄓' => '(D)', '🄔' => '(E)', '🄕' => '(F)', '🄖' => '(G)', '🄗' => '(H)', '🄘' => '(I)', '🄙' => '(J)', '🄚' => '(K)', '🄛' => '(L)', '🄜' => '(M)', '🄝' => '(N)', '🄞' => '(O)', '🄟' => '(P)', '🄠' => '(Q)', '🄡' => '(R)', '🄢' => '(S)', '🄣' => '(T)', '🄤' => '(U)', '🄥' => '(V)', '🄦' => '(W)', '🄧' => '(X)', '🄨' => '(Y)', '🄩' => '(Z)', '🄪' => '〔S〕', '🄫' => 'C', '🄬' => 'R', '🄭' => 'CD', '🄮' => 'WZ', '🄰' => 'A', '🄱' => 'B', '🄲' => 'C', '🄳' => 'D', '🄴' => 'E', '🄵' => 'F', '🄶' => 'G', '🄷' => 'H', '🄸' => 'I', '🄹' => 'J', '🄺' => 'K', '🄻' => 'L', '🄼' => 'M', '🄽' => 'N', '🄾' => 'O', '🄿' => 'P', '🅀' => 'Q', '🅁' => 'R', '🅂' => 'S', '🅃' => 'T', '🅄' => 'U', '🅅' => 'V', '🅆' => 'W', '🅇' => 'X', '🅈' => 'Y', '🅉' => 'Z', '🅊' => 'HV', '🅋' => 'MV', '🅌' => 'SD', '🅍' => 'SS', '🅎' => 'PPV', '🅏' => 'WC', '🅪' => 'MC', '🅫' => 'MD', '🅬' => 'MR', '🆐' => 'DJ', '🈀' => 'ほか', '🈁' => 'ココ', '🈂' => 'サ', '🈐' => '手', '🈑' => '字', '🈒' => '双', '🈓' => 'デ', '🈔' => '二', '🈕' => '多', '🈖' => '解', '🈗' => '天', '🈘' => '交', '🈙' => '映', '🈚' => '無', '🈛' => '料', '🈜' => '前', '🈝' => '後', '🈞' => '再', '🈟' => '新', '🈠' => '初', '🈡' => '終', '🈢' => '生', '🈣' => '販', '🈤' => '声', '🈥' => '吹', '🈦' => '演', '🈧' => '投', '🈨' => '捕', '🈩' => '一', '🈪' => '三', '🈫' => '遊', '🈬' => '左', '🈭' => '中', '🈮' => '右', '🈯' => '指', '🈰' => '走', '🈱' => '打', '🈲' => '禁', '🈳' => '空', '🈴' => '合', '🈵' => '満', '🈶' => '有', '🈷' => '月', '🈸' => '申', '🈹' => '割', '🈺' => '営', '🈻' => '配', '🉀' => '〔本〕', '🉁' => '〔三〕', '🉂' => '〔二〕', '🉃' => '〔安〕', '🉄' => '〔点〕', '🉅' => '〔打〕', '🉆' => '〔盗〕', '🉇' => '〔勝〕', '🉈' => '〔敗〕', '🉐' => '得', '🉑' => '可', '🯰' => '0', '🯱' => '1', '🯲' => '2', '🯳' => '3', '🯴' => '4', '🯵' => '5', '🯶' => '6', '🯷' => '7', '🯸' => '8', '🯹' => '9'); * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String; /** * A string whose value is computed lazily by a callback. * * @author Nicolas Grekas */ class LazyString implements \Stringable, \JsonSerializable { private $value; /** * @param callable|array $callback A callable or a [Closure, method] lazy-callable * * @return static */ public static function fromCallable($callback, ...$arguments) : self { if (!\is_callable($callback) && !(\is_array($callback) && isset($callback[0]) && $callback[0] instanceof \Closure && 2 >= \count($callback))) { throw new \TypeError(\sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, \get_debug_type($callback))); } $lazyString = new static(); $lazyString->value = static function () use(&$callback, &$arguments, &$value) : string { if (null !== $arguments) { if (!\is_callable($callback)) { $callback[0] = $callback[0](); $callback[1] = $callback[1] ?? '__invoke'; } $value = $callback(...$arguments); $callback = self::getPrettyName($callback); $arguments = null; } return $value ?? ''; }; return $lazyString; } /** * @param string|int|float|bool|\Stringable $value * * @return static */ public static function fromStringable($value) : self { if (!self::isStringable($value)) { throw new \TypeError(\sprintf('Argument 1 passed to "%s()" must be a scalar or a stringable object, "%s" given.', __METHOD__, \get_debug_type($value))); } if (\is_object($value)) { return static::fromCallable([$value, '__toString']); } $lazyString = new static(); $lazyString->value = (string) $value; return $lazyString; } /** * Tells whether the provided value can be cast to string. */ public static final function isStringable($value) : bool { return \is_string($value) || $value instanceof self || (\is_object($value) ? \method_exists($value, '__toString') : \is_scalar($value)); } /** * Casts scalars and stringable objects to strings. * * @param object|string|int|float|bool $value * * @throws \TypeError When the provided value is not stringable */ public static final function resolve($value) : string { return $value; } /** * @return string */ public function __toString() { if (\is_string($this->value)) { return $this->value; } try { return $this->value = ($this->value)(); } catch (\Throwable $e) { if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) { $type = \explode(', ', $e->getMessage()); $type = \substr(\array_pop($type), 0, -\strlen(' returned')); $r = new \ReflectionFunction($this->value); $callback = $r->getStaticVariables()['callback']; $e = new \TypeError(\sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type)); } if (\PHP_VERSION_ID < 70400) { // leverage the ErrorHandler component with graceful fallback when it's not available return \trigger_error($e, \E_USER_ERROR); } throw $e; } } public function __sleep() : array { $this->__toString(); return ['value']; } public function jsonSerialize() : string { return $this->__toString(); } private function __construct() { } private static function getPrettyName(callable $callback) : string { if (\is_string($callback)) { return $callback; } if (\is_array($callback)) { $class = \is_object($callback[0]) ? \get_debug_type($callback[0]) : $callback[0]; $method = $callback[1]; } elseif ($callback instanceof \Closure) { $r = new \ReflectionFunction($callback); if (\false !== \strpos($r->name, '{closure}') || !($class = $r->getClosureScopeClass())) { return $r->name; } $class = $class->name; $method = $r->name; } else { $class = \get_debug_type($callback); $method = '__invoke'; } return $class . '::' . $method; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\ExceptionInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException; /** * Represents a string of abstract Unicode characters. * * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). * This class is the abstract type to use as a type-hint when the logic you want to * implement is Unicode-aware but doesn't care about code points vs grapheme clusters. * * @author Nicolas Grekas * * @throws ExceptionInterface */ abstract class AbstractUnicodeString extends \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { public const NFC = \Normalizer::NFC; public const NFD = \Normalizer::NFD; public const NFKC = \Normalizer::NFKC; public const NFKD = \Normalizer::NFKD; // all ASCII letters sorted by typical frequency of occurrence private const ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))']; private static $transliterators = []; /** * @return static */ public static function fromCodePoints(int ...$codes) : self { $string = ''; foreach ($codes as $code) { if (0x80 > ($code %= 0x200000)) { $string .= \chr($code); } elseif (0x800 > $code) { $string .= \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f); } elseif (0x10000 > $code) { $string .= \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f); } else { $string .= \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f); } } return new static($string); } /** * Generic UTF-8 to ASCII transliteration. * * Install the intl extension for best results. * * @param string[]|\Transliterator[] $rules See "*-Latin" rules from Transliterator::listIDs() */ public function ascii(array $rules = []) : self { $str = clone $this; $s = $str->string; $str->string = ''; \array_unshift($rules, 'nfd'); $rules[] = 'latin-ascii'; if (\function_exists('transliterator_transliterate')) { $rules[] = 'any-latin/bgn'; } $rules[] = 'nfkd'; $rules[] = '[:nonspacing mark:] remove'; while (\strlen($s) - 1 > ($i = \strspn($s, self::ASCII))) { if (0 < --$i) { $str->string .= \substr($s, 0, $i); $s = \substr($s, $i); } if (!($rule = \array_shift($rules))) { $rules = []; // An empty rule interrupts the next ones } if ($rule instanceof \Transliterator) { $s = $rule->transliterate($s); } elseif ($rule) { if ('nfd' === ($rule = \strtolower($rule))) { \normalizer_is_normalized($s, self::NFD) ?: ($s = \normalizer_normalize($s, self::NFD)); } elseif ('nfkd' === $rule) { \normalizer_is_normalized($s, self::NFKD) ?: ($s = \normalizer_normalize($s, self::NFKD)); } elseif ('[:nonspacing mark:] remove' === $rule) { $s = \preg_replace('/\\p{Mn}++/u', '', $s); } elseif ('latin-ascii' === $rule) { $s = \str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s); } elseif ('de-ascii' === $rule) { $s = \preg_replace("/([AUO])̈(?=\\p{Ll})/u", '$1e', $s); $s = \str_replace(["ä", "ö", "ü", "Ä", "Ö", "Ü"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s); } elseif (\function_exists('transliterator_transliterate')) { if (null === ($transliterator = self::$transliterators[$rule] ?? (self::$transliterators[$rule] = \Transliterator::create($rule)))) { if ('any-latin/bgn' === $rule) { $rule = 'any-latin'; $transliterator = self::$transliterators[$rule] ?? (self::$transliterators[$rule] = \Transliterator::create($rule)); } if (null === $transliterator) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException(\sprintf('Unknown transliteration rule "%s".', $rule)); } self::$transliterators['any-latin/bgn'] = $transliterator; } $s = $transliterator->transliterate($s); } } elseif (!\function_exists('iconv')) { $s = \preg_replace('/[^\\x00-\\x7F]/u', '?', $s); } else { $s = @\preg_replace_callback('/[^\\x00-\\x7F]/u', static function ($c) { $c = (string) \iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]); if ('' === $c && '' === \iconv('UTF-8', 'ASCII//TRANSLIT', '²')) { throw new \LogicException(\sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class)); } return 1 < \strlen($c) ? \ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?'); }, $s); } } $str->string .= $s; return $str; } public function camel() : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \str_replace(' ', '', \preg_replace_callback('/\\b./u', static function ($m) use(&$i) { 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))); return $str; } /** * @return int[] */ public function codePointsAt(int $offset) : array { $str = $this->slice($offset, 1); if ('' === $str->string) { return []; } $codePoints = []; foreach (\preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { $codePoints[] = \mb_ord($c, 'UTF-8'); } return $codePoints; } public function folded(bool $compat = \true) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; if (!$compat || \PHP_VERSION_ID < 70300 || !\defined('Normalizer::NFKC_CF')) { $str->string = \normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC); $str->string = \mb_strtolower(\str_replace(self::FOLD_FROM, self::FOLD_TO, $this->string), 'UTF-8'); } else { $str->string = \normalizer_normalize($str->string, \Normalizer::NFKC_CF); } return $str; } public function join(array $strings, string $lastGlue = null) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . \array_pop($strings) : ''; $str->string = \implode($this->string, $strings) . $tail; if (!\preg_match('//u', $str->string)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function lower() : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \mb_strtolower(\str_replace('İ', 'i̇', $str->string), 'UTF-8'); return $str; } public function match(string $regexp, int $flags = 0, int $offset = 0) : array { $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match'; if ($this->ignoreCase) { $regexp .= 'i'; } \set_error_handler(static function ($t, $m) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException($m); }); try { if (\false === $match($regexp . 'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Matching failed with ' . $k . '.'); } } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Matching failed with unknown error code.'); } } finally { \restore_error_handler(); } return $matches; } /** * @return static */ public function normalize(int $form = self::NFC) : self { if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Unsupported normalization form.'); } $str = clone $this; \normalizer_is_normalized($str->string, $form) ?: ($str->string = \normalizer_normalize($str->string, $form)); return $str; } public function padBoth(int $length, string $padStr = ' ') : \_HumbugBoxd02f763d3c56\parent { if ('' === $padStr || !\preg_match('//u', $padStr)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } $pad = clone $this; $pad->string = $padStr; return $this->pad($length, $pad, \STR_PAD_BOTH); } public function padEnd(int $length, string $padStr = ' ') : \_HumbugBoxd02f763d3c56\parent { if ('' === $padStr || !\preg_match('//u', $padStr)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } $pad = clone $this; $pad->string = $padStr; return $this->pad($length, $pad, \STR_PAD_RIGHT); } public function padStart(int $length, string $padStr = ' ') : \_HumbugBoxd02f763d3c56\parent { if ('' === $padStr || !\preg_match('//u', $padStr)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } $pad = clone $this; $pad->string = $padStr; return $this->pad($length, $pad, \STR_PAD_LEFT); } public function replaceMatches(string $fromRegexp, $to) : \_HumbugBoxd02f763d3c56\parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; } if (\is_array($to) || $to instanceof \Closure) { if (!\is_callable($to)) { throw new \TypeError(\sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); } $replace = 'preg_replace_callback'; $to = static function (array $m) use($to) : string { $to = $to($m); if ('' !== $to && (!\is_string($to) || !\preg_match('//u', $to))) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Replace callback must return a valid UTF-8 string.'); } return $to; }; } elseif ('' !== $to && !\preg_match('//u', $to)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } else { $replace = 'preg_replace'; } \set_error_handler(static function ($t, $m) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException($m); }); try { if (null === ($string = $replace($fromRegexp . 'u', $to, $this->string))) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Matching failed with ' . $k . '.'); } } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Matching failed with unknown error code.'); } } finally { \restore_error_handler(); } $str = clone $this; $str->string = $string; return $str; } public function reverse() : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \implode('', \array_reverse(\preg_split('/(\\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY))); return $str; } public function snake() : \_HumbugBoxd02f763d3c56\parent { $str = $this->camel()->title(); $str->string = \mb_strtolower(\preg_replace(['/(\\p{Lu}+)(\\p{Lu}\\p{Ll})/u', '/([\\p{Ll}0-9])(\\p{Lu})/u'], '_HumbugBoxd02f763d3c56\\1_\\2', $str->string), 'UTF-8'); return $str; } public function title(bool $allWords = \false) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $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); return $str; } public function trim(string $chars = " \t\n\r\0\v\f ") : \_HumbugBoxd02f763d3c56\parent { if (" \t\n\r\0\v\f " !== $chars && !\preg_match('//u', $chars)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 chars.'); } $chars = \preg_quote($chars); $str = clone $this; $str->string = \preg_replace("{^[{$chars}]++|[{$chars}]++\$}uD", '', $str->string); return $str; } public function trimEnd(string $chars = " \t\n\r\0\v\f ") : \_HumbugBoxd02f763d3c56\parent { if (" \t\n\r\0\v\f " !== $chars && !\preg_match('//u', $chars)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 chars.'); } $chars = \preg_quote($chars); $str = clone $this; $str->string = \preg_replace("{[{$chars}]++\$}uD", '', $str->string); return $str; } public function trimStart(string $chars = " \t\n\r\0\v\f ") : \_HumbugBoxd02f763d3c56\parent { if (" \t\n\r\0\v\f " !== $chars && !\preg_match('//u', $chars)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 chars.'); } $chars = \preg_quote($chars); $str = clone $this; $str->string = \preg_replace("{^[{$chars}]++}uD", '', $str->string); return $str; } public function upper() : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \mb_strtoupper($str->string, 'UTF-8'); if (\PHP_VERSION_ID < 70300) { $str->string = \str_replace(self::UPPER_FROM, self::UPPER_TO, $str->string); } return $str; } public function width(bool $ignoreAnsiDecoration = \true) : int { $width = 0; $s = \str_replace(["\0", "\5", "\7"], '', $this->string); if (\false !== \strpos($s, "\r")) { $s = \str_replace(["\r\n", "\r"], "\n", $s); } if (!$ignoreAnsiDecoration) { $s = \preg_replace('/[\\p{Cc}\\x7F]++/u', '', $s); } foreach (\explode("\n", $s) as $s) { if ($ignoreAnsiDecoration) { $s = \preg_replace('/(?:\\x1B(?: \\[ [\\x30-\\x3F]*+ [\\x20-\\x2F]*+ [0x40-\\x7E] | [P\\]X^_] .*? \\x1B\\\\ | [\\x41-\\x7E] )|[\\p{Cc}\\x7F]++)/xu', '', $s); } // Non printable characters have been dropped, so wcswidth cannot logically return -1. $width += $this->wcswidth($s); } return $width; } /** * @return static */ private function pad(int $len, self $pad, int $type) : \_HumbugBoxd02f763d3c56\parent { $sLen = $this->length(); if ($len <= $sLen) { return clone $this; } $padLen = $pad->length(); $freeLen = $len - $sLen; $len = $freeLen % $padLen; switch ($type) { case \STR_PAD_RIGHT: return $this->append(\str_repeat($pad->string, $freeLen / $padLen) . ($len ? $pad->slice(0, $len) : '')); case \STR_PAD_LEFT: return $this->prepend(\str_repeat($pad->string, $freeLen / $padLen) . ($len ? $pad->slice(0, $len) : '')); case \STR_PAD_BOTH: $freeLen /= 2; $rightLen = \ceil($freeLen); $len = $rightLen % $padLen; $str = $this->append(\str_repeat($pad->string, $rightLen / $padLen) . ($len ? $pad->slice(0, $len) : '')); $leftLen = \floor($freeLen); $len = $leftLen % $padLen; return $str->prepend(\str_repeat($pad->string, $leftLen / $padLen) . ($len ? $pad->slice(0, $len) : '')); default: throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid padding type.'); } } /** * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c. */ private function wcswidth(string $string) : int { $width = 0; foreach (\preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { $codePoint = \mb_ord($c, 'UTF-8'); if (0 === $codePoint || 0x34f === $codePoint || 0x200b <= $codePoint && 0x200f >= $codePoint || 0x2028 === $codePoint || 0x2029 === $codePoint || 0x202a <= $codePoint && 0x202e >= $codePoint || 0x2060 <= $codePoint && 0x2063 >= $codePoint) { continue; } // Non printable characters if (32 > $codePoint || 0x7f <= $codePoint && 0xa0 > $codePoint) { return -1; } static $tableZero; if (null === $tableZero) { $tableZero = (require __DIR__ . '/Resources/data/wcswidth_table_zero.php'); } if ($codePoint >= $tableZero[0][0] && $codePoint <= $tableZero[$ubound = \count($tableZero) - 1][1]) { $lbound = 0; while ($ubound >= $lbound) { $mid = \floor(($lbound + $ubound) / 2); if ($codePoint > $tableZero[$mid][1]) { $lbound = $mid + 1; } elseif ($codePoint < $tableZero[$mid][0]) { $ubound = $mid - 1; } else { continue 2; } } } static $tableWide; if (null === $tableWide) { $tableWide = (require __DIR__ . '/Resources/data/wcswidth_table_wide.php'); } if ($codePoint >= $tableWide[0][0] && $codePoint <= $tableWide[$ubound = \count($tableWide) - 1][1]) { $lbound = 0; while ($ubound >= $lbound) { $mid = \floor(($lbound + $ubound) / 2); if ($codePoint > $tableWide[$mid][1]) { $lbound = $mid + 1; } elseif ($codePoint < $tableWide[$mid][0]) { $ubound = $mid - 1; } else { $width += 2; continue 2; } } } ++$width; } return $width; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\ExceptionInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException; /** * Represents a string of abstract characters. * * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). * This class is the abstract type to use as a type-hint when the logic you want to * implement doesn't care about the exact variant it deals with. * * @author Nicolas Grekas * @author Hugo Hamon * * @throws ExceptionInterface */ abstract class AbstractString implements \Stringable, \JsonSerializable { public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER; public const PREG_SET_ORDER = \PREG_SET_ORDER; public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE; public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL; public const PREG_SPLIT = 0; public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY; public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE; public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE; protected $string = ''; protected $ignoreCase = \false; public abstract function __construct(string $string = ''); /** * Unwraps instances of AbstractString back to strings. * * @return string[]|array */ public static function unwrap(array $values) : array { foreach ($values as $k => $v) { if ($v instanceof self) { $values[$k] = $v->__toString(); } elseif (\is_array($v) && $values[$k] !== ($v = static::unwrap($v))) { $values[$k] = $v; } } return $values; } /** * Wraps (and normalizes) strings in instances of AbstractString. * * @return static[]|array */ public static function wrap(array $values) : array { $i = 0; $keys = null; foreach ($values as $k => $v) { if (\is_string($k) && '' !== $k && $k !== ($j = (string) new static($k))) { $keys = $keys ?? \array_keys($values); $keys[$i] = $j; } if (\is_string($v)) { $values[$k] = new static($v); } elseif (\is_array($v) && $values[$k] !== ($v = static::wrap($v))) { $values[$k] = $v; } ++$i; } return null !== $keys ? \array_combine($keys, $values) : $values; } /** * @param string|string[] $needle * * @return static */ public function after($needle, bool $includeNeedle = \false, int $offset = 0) : self { $str = clone $this; $str->string = ''; $i = \PHP_INT_MAX; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); if (null !== $j && $j < $i) { $i = $j; $str->string = $n; } } if (\PHP_INT_MAX === $i) { return $str; } if (!$includeNeedle) { $i += $str->length(); } return $this->slice($i); } /** * @param string|string[] $needle * * @return static */ public function afterLast($needle, bool $includeNeedle = \false, int $offset = 0) : self { $str = clone $this; $str->string = ''; $i = null; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); if (null !== $j && $j >= $i) { $i = $offset = $j; $str->string = $n; } } if (null === $i) { return $str; } if (!$includeNeedle) { $i += $str->length(); } return $this->slice($i); } /** * @return static */ public abstract function append(string ...$suffix) : self; /** * @param string|string[] $needle * * @return static */ public function before($needle, bool $includeNeedle = \false, int $offset = 0) : self { $str = clone $this; $str->string = ''; $i = \PHP_INT_MAX; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); if (null !== $j && $j < $i) { $i = $j; $str->string = $n; } } if (\PHP_INT_MAX === $i) { return $str; } if ($includeNeedle) { $i += $str->length(); } return $this->slice(0, $i); } /** * @param string|string[] $needle * * @return static */ public function beforeLast($needle, bool $includeNeedle = \false, int $offset = 0) : self { $str = clone $this; $str->string = ''; $i = null; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); if (null !== $j && $j >= $i) { $i = $offset = $j; $str->string = $n; } } if (null === $i) { return $str; } if ($includeNeedle) { $i += $str->length(); } return $this->slice(0, $i); } /** * @return int[] */ public function bytesAt(int $offset) : array { $str = $this->slice($offset, 1); return '' === $str->string ? [] : \array_values(\unpack('C*', $str->string)); } /** * @return static */ public abstract function camel() : self; /** * @return static[] */ public abstract function chunk(int $length = 1) : array; /** * @return static */ public function collapseWhitespace() : self { $str = clone $this; $str->string = \trim(\preg_replace('/(?:\\s{2,}+|[^\\S ])/', ' ', $str->string)); return $str; } /** * @param string|string[] $needle */ public function containsAny($needle) : bool { return null !== $this->indexOf($needle); } /** * @param string|string[] $suffix */ public function endsWith($suffix) : bool { if (!\is_array($suffix) && !$suffix instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } foreach ($suffix as $s) { if ($this->endsWith((string) $s)) { return \true; } } return \false; } /** * @return static */ public function ensureEnd(string $suffix) : self { if (!$this->endsWith($suffix)) { return $this->append($suffix); } $suffix = \preg_quote($suffix); $regex = '{(' . $suffix . ')(?:' . $suffix . ')++$}D'; return $this->replaceMatches($regex . ($this->ignoreCase ? 'i' : ''), '$1'); } /** * @return static */ public function ensureStart(string $prefix) : self { $prefix = new static($prefix); if (!$this->startsWith($prefix)) { return $this->prepend($prefix); } $str = clone $this; $i = $prefixLen = $prefix->length(); while ($this->indexOf($prefix, $i) === $i) { $str = $str->slice($prefixLen); $i += $prefixLen; } return $str; } /** * @param string|string[] $string */ public function equalsTo($string) : bool { if (!\is_array($string) && !$string instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } foreach ($string as $s) { if ($this->equalsTo((string) $s)) { return \true; } } return \false; } /** * @return static */ public abstract function folded() : self; /** * @return static */ public function ignoreCase() : self { $str = clone $this; $str->ignoreCase = \true; return $str; } /** * @param string|string[] $needle */ public function indexOf($needle, int $offset = 0) : ?int { if (!\is_array($needle) && !$needle instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } $i = \PHP_INT_MAX; foreach ($needle as $n) { $j = $this->indexOf((string) $n, $offset); if (null !== $j && $j < $i) { $i = $j; } } return \PHP_INT_MAX === $i ? null : $i; } /** * @param string|string[] $needle */ public function indexOfLast($needle, int $offset = 0) : ?int { if (!\is_array($needle) && !$needle instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } $i = null; foreach ($needle as $n) { $j = $this->indexOfLast((string) $n, $offset); if (null !== $j && $j >= $i) { $i = $offset = $j; } } return $i; } public function isEmpty() : bool { return '' === $this->string; } /** * @return static */ public abstract function join(array $strings, string $lastGlue = null) : self; public function jsonSerialize() : string { return $this->string; } public abstract function length() : int; /** * @return static */ public abstract function lower() : self; /** * Matches the string using a regular expression. * * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression. * * @return array All matches in a multi-dimensional array ordered according to flags */ public abstract function match(string $regexp, int $flags = 0, int $offset = 0) : array; /** * @return static */ public abstract function padBoth(int $length, string $padStr = ' ') : self; /** * @return static */ public abstract function padEnd(int $length, string $padStr = ' ') : self; /** * @return static */ public abstract function padStart(int $length, string $padStr = ' ') : self; /** * @return static */ public abstract function prepend(string ...$prefix) : self; /** * @return static */ public function repeat(int $multiplier) : self { if (0 > $multiplier) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException(\sprintf('Multiplier must be positive, %d given.', $multiplier)); } $str = clone $this; $str->string = \str_repeat($str->string, $multiplier); return $str; } /** * @return static */ public abstract function replace(string $from, string $to) : self; /** * @param string|callable $to * * @return static */ public abstract function replaceMatches(string $fromRegexp, $to) : self; /** * @return static */ public abstract function reverse() : self; /** * @return static */ public abstract function slice(int $start = 0, int $length = null) : self; /** * @return static */ public abstract function snake() : self; /** * @return static */ public abstract function splice(string $replacement, int $start = 0, int $length = null) : self; /** * @return static[] */ public function split(string $delimiter, int $limit = null, int $flags = null) : array { if (null === $flags) { throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.'); } if ($this->ignoreCase) { $delimiter .= 'i'; } \set_error_handler(static function ($t, $m) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException($m); }); try { if (\false === ($chunks = \preg_split($delimiter, $this->string, $limit, $flags))) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Splitting failed with ' . $k . '.'); } } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Splitting failed with unknown error code.'); } } finally { \restore_error_handler(); } $str = clone $this; if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) { foreach ($chunks as &$chunk) { $str->string = $chunk[0]; $chunk[0] = clone $str; } } else { foreach ($chunks as &$chunk) { $str->string = $chunk; $chunk = clone $str; } } return $chunks; } /** * @param string|string[] $prefix */ public function startsWith($prefix) : bool { if (!\is_array($prefix) && !$prefix instanceof \Traversable) { throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } foreach ($prefix as $prefix) { if ($this->startsWith((string) $prefix)) { return \true; } } return \false; } /** * @return static */ public abstract function title(bool $allWords = \false) : self; public function toByteString(string $toEncoding = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\ByteString { $b = new \_HumbugBoxd02f763d3c56\Symfony\Component\String\ByteString(); $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], \true) ? 'UTF-8' : $toEncoding; if (null === $toEncoding || $toEncoding === ($fromEncoding = $this instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractUnicodeString || \preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252')) { $b->string = $this->string; return $b; } \set_error_handler(static function ($t, $m) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException($m); }); try { try { $b->string = \mb_convert_encoding($this->string, $toEncoding, 'UTF-8'); } catch (\_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException $e) { if (!\function_exists('iconv')) { throw $e; } $b->string = \iconv('UTF-8', $toEncoding, $this->string); } } finally { \restore_error_handler(); } return $b; } public function toCodePointString() : \_HumbugBoxd02f763d3c56\Symfony\Component\String\CodePointString { return new \_HumbugBoxd02f763d3c56\Symfony\Component\String\CodePointString($this->string); } public function toString() : string { return $this->string; } public function toUnicodeString() : \_HumbugBoxd02f763d3c56\Symfony\Component\String\UnicodeString { return new \_HumbugBoxd02f763d3c56\Symfony\Component\String\UnicodeString($this->string); } /** * @return static */ public abstract function trim(string $chars = " \t\n\r\0\v\f ") : self; /** * @return static */ public abstract function trimEnd(string $chars = " \t\n\r\0\v\f ") : self; /** * @return static */ public abstract function trimStart(string $chars = " \t\n\r\0\v\f ") : self; /** * @return static */ public function truncate(int $length, string $ellipsis = '', bool $cut = \true) : self { $stringLength = $this->length(); if ($stringLength <= $length) { return clone $this; } $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0; if ($length < $ellipsisLength) { $ellipsisLength = 0; } if (!$cut) { if (null === ($length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1))) { return clone $this; } $length += $ellipsisLength; } $str = $this->slice(0, $length - $ellipsisLength); return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str; } /** * @return static */ public abstract function upper() : self; /** * Returns the printable length on a terminal. */ public abstract function width(bool $ignoreAnsiDecoration = \true) : int; /** * @return static */ public function wordwrap(int $width = 75, string $break = "\n", bool $cut = \false) : self { $lines = '' !== $break ? $this->split($break) : [clone $this]; $chars = []; $mask = ''; if (1 === \count($lines) && '' === $lines[0]->string) { return $lines[0]; } foreach ($lines as $i => $line) { if ($i) { $chars[] = $break; $mask .= '#'; } foreach ($line->chunk() as $char) { $chars[] = $char->string; $mask .= ' ' === $char->string ? ' ' : '?'; } } $string = ''; $j = 0; $b = $i = -1; $mask = \wordwrap($mask, $width, '#', $cut); while (\false !== ($b = \strpos($mask, '#', $b + 1))) { for (++$i; $i < $b; ++$i) { $string .= $chars[$j]; unset($chars[$j++]); } if ($break === $chars[$j] || ' ' === $chars[$j]) { unset($chars[$j++]); } $string .= $break; } $str = clone $this; $str->string = $string . \implode('', $chars); return $str; } public function __sleep() : array { return ['string']; } public function __clone() { $this->ignoreCase = \false; } public function __toString() : string { return $this->string; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception; interface ExceptionInterface extends \Throwable { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception; class RuntimeException extends \RuntimeException implements \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception; class InvalidArgumentException extends \InvalidArgumentException implements \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\ExceptionInterface { } Copyright (c) 2019-2020 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String\Inflector; interface InflectorInterface { /** * Returns the singular forms of a string. * * If the method can't determine the form with certainty, several possible singulars are returned. * * @return string[] An array of possible singular forms */ public function singularize(string $plural) : array; /** * Returns the plural forms of a string. * * If the method can't determine the form with certainty, several possible plurals are returned. * * @return string[] An array of possible plural forms */ public function pluralize(string $singular) : array; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String\Inflector; final class EnglishInflector implements \_HumbugBoxd02f763d3c56\Symfony\Component\String\Inflector\InflectorInterface { /** * Map English plural to singular suffixes. * * @see http://english-zone.com/spelling/plurals.html */ private static $pluralMap = [ // First entry: plural suffix, reversed // Second entry: length of plural suffix // Third entry: Whether the suffix may succeed a vocal // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: singular suffix, normal // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['a', 1, \true, \true, ['on', 'um']], // nebulae (nebula) ['ea', 2, \true, \true, 'a'], // services (service) ['secivres', 8, \true, \true, 'service'], // mice (mouse), lice (louse) ['eci', 3, \false, \true, 'ouse'], // geese (goose) ['esee', 4, \false, \true, 'oose'], // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) ['i', 1, \true, \true, 'us'], // men (man), women (woman) ['nem', 3, \true, \true, 'man'], // children (child) ['nerdlihc', 8, \true, \true, 'child'], // oxen (ox) ['nexo', 4, \false, \false, 'ox'], // indices (index), appendices (appendix), prices (price) ['seci', 4, \false, \true, ['ex', 'ix', 'ice']], // selfies (selfie) ['seifles', 7, \true, \true, 'selfie'], // movies (movie) ['seivom', 6, \true, \true, 'movie'], // feet (foot) ['teef', 4, \true, \true, 'foot'], // geese (goose) ['eseeg', 5, \true, \true, 'goose'], // teeth (tooth) ['hteet', 5, \true, \true, 'tooth'], // news (news) ['swen', 4, \true, \true, 'news'], // series (series) ['seires', 6, \true, \true, 'series'], // babies (baby) ['sei', 3, \false, \true, 'y'], // accesses (access), addresses (address), kisses (kiss) ['sess', 4, \true, \false, 'ss'], // analyses (analysis), ellipses (ellipsis), fungi (fungus), // neuroses (neurosis), theses (thesis), emphases (emphasis), // oases (oasis), crises (crisis), houses (house), bases (base), // atlases (atlas) ['ses', 3, \true, \true, ['s', 'se', 'sis']], // objectives (objective), alternative (alternatives) ['sevit', 5, \true, \true, 'tive'], // drives (drive) ['sevird', 6, \false, \true, 'drive'], // lives (life), wives (wife) ['sevi', 4, \false, \true, 'ife'], // moves (move) ['sevom', 5, \true, \true, 'move'], // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff) ['sev', 3, \true, \true, ['f', 've', 'ff']], // axes (axis), axes (ax), axes (axe) ['sexa', 4, \false, \false, ['ax', 'axe', 'axis']], // indexes (index), matrixes (matrix) ['sex', 3, \true, \false, 'x'], // quizzes (quiz) ['sezz', 4, \true, \false, 'z'], // bureaus (bureau) ['suae', 4, \false, \true, 'eau'], // fees (fee), trees (tree), employees (employee) ['see', 3, \true, \true, 'ee'], // roses (rose), garages (garage), cassettes (cassette), // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), // shoes (shoe) ['se', 2, \true, \true, ['', 'e']], // tags (tag) ['s', 1, \true, \true, ''], // chateaux (chateau) ['xuae', 4, \false, \true, 'eau'], // people (person) ['elpoep', 6, \true, \true, 'person'], ]; /** * Map English singular to plural suffixes. * * @see http://english-zone.com/spelling/plurals.html */ private static $singularMap = [ // First entry: singular suffix, reversed // Second entry: length of singular suffix // Third entry: Whether the suffix may succeed a vocal // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: plural suffix, normal // criterion (criteria) ['airetirc', 8, \false, \false, 'criterion'], // nebulae (nebula) ['aluben', 6, \false, \false, 'nebulae'], // children (child) ['dlihc', 5, \true, \true, 'children'], // prices (price) ['eci', 3, \false, \true, 'ices'], // services (service) ['ecivres', 7, \true, \true, 'services'], // lives (life), wives (wife) ['efi', 3, \false, \true, 'ives'], // selfies (selfie) ['eifles', 6, \true, \true, 'selfies'], // movies (movie) ['eivom', 5, \true, \true, 'movies'], // lice (louse) ['esuol', 5, \false, \true, 'lice'], // mice (mouse) ['esuom', 5, \false, \true, 'mice'], // geese (goose) ['esoo', 4, \false, \true, 'eese'], // houses (house), bases (base) ['es', 2, \true, \true, 'ses'], // geese (goose) ['esoog', 5, \true, \true, 'geese'], // caves (cave) ['ev', 2, \true, \true, 'ves'], // drives (drive) ['evird', 5, \false, \true, 'drives'], // objectives (objective), alternative (alternatives) ['evit', 4, \true, \true, 'tives'], // moves (move) ['evom', 4, \true, \true, 'moves'], // staves (staff) ['ffats', 5, \true, \true, 'staves'], // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) ['ff', 2, \true, \true, 'ffs'], // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) ['f', 1, \true, \true, ['fs', 'ves']], // arches (arch) ['hc', 2, \true, \true, 'ches'], // bushes (bush) ['hs', 2, \true, \true, 'shes'], // teeth (tooth) ['htoot', 5, \true, \true, 'teeth'], // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['mu', 2, \true, \true, 'a'], // men (man), women (woman) ['nam', 3, \true, \true, 'men'], // people (person) ['nosrep', 6, \true, \true, ['persons', 'people']], // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['noi', 3, \true, \true, 'ions'], // seasons (season), treasons (treason), poisons (poison), lessons (lesson) ['nos', 3, \true, \true, 'sons'], // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['no', 2, \true, \true, 'a'], // echoes (echo) ['ohce', 4, \true, \true, 'echoes'], // heroes (hero) ['oreh', 4, \true, \true, 'heroes'], // atlases (atlas) ['salta', 5, \true, \true, 'atlases'], // irises (iris) ['siri', 4, \true, \true, 'irises'], // analyses (analysis), ellipses (ellipsis), neuroses (neurosis) // theses (thesis), emphases (emphasis), oases (oasis), // crises (crisis) ['sis', 3, \true, \true, 'ses'], // accesses (access), addresses (address), kisses (kiss) ['ss', 2, \true, \false, 'sses'], // syllabi (syllabus) ['suballys', 8, \true, \true, 'syllabi'], // buses (bus) ['sub', 3, \true, \true, 'buses'], // circuses (circus) ['suc', 3, \true, \true, 'cuses'], // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) ['su', 2, \true, \true, 'i'], // news (news) ['swen', 4, \true, \true, 'news'], // feet (foot) ['toof', 4, \true, \true, 'feet'], // chateaux (chateau), bureaus (bureau) ['uae', 3, \false, \true, ['eaus', 'eaux']], // oxen (ox) ['xo', 2, \false, \false, 'oxen'], // hoaxes (hoax) ['xaoh', 4, \true, \false, 'hoaxes'], // indices (index) ['xedni', 5, \false, \true, ['indicies', 'indexes']], // boxes (box) ['xo', 2, \false, \true, 'oxes'], // indexes (index), matrixes (matrix) ['x', 1, \true, \false, ['cies', 'xes']], // appendices (appendix) ['xi', 2, \false, \true, 'ices'], // babies (baby) ['y', 1, \false, \true, 'ies'], // quizzes (quiz) ['ziuq', 4, \true, \false, 'quizzes'], // waltzes (waltz) ['z', 1, \true, \true, 'zes'], ]; /** * A list of words which should not be inflected, reversed. */ private static $uninflected = ['atad', 'reed', 'kcabdeef', 'hsif', 'ofni', 'esoom', 'seires', 'peehs', 'seiceps']; /** * {@inheritdoc} */ public function singularize(string $plural) : array { $pluralRev = \strrev($plural); $lowerPluralRev = \strtolower($pluralRev); $pluralLength = \strlen($lowerPluralRev); // Check if the word is one which is not inflected, return early if so if (\in_array($lowerPluralRev, self::$uninflected, \true)) { return [$plural]; } // The outer loop iterates over the entries of the plural table // The inner loop $j iterates over the characters of the plural suffix // in the plural table to compare them with the characters of the actual // given plural suffix foreach (self::$pluralMap as $map) { $suffix = $map[0]; $suffixLength = $map[1]; $j = 0; // Compare characters in the plural table and of the suffix of the // given plural one by one while ($suffix[$j] === $lowerPluralRev[$j]) { // Let $j point to the next character ++$j; // Successfully compared the last character // Add an entry with the singular suffix to the singular array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $pluralLength) { $nextIsVocal = \false !== \strpos('aeiou', $lowerPluralRev[$j]); if (!$map[2] && $nextIsVocal) { // suffix may not succeed a vocal but next char is one break; } if (!$map[3] && !$nextIsVocal) { // suffix may not succeed a consonant but next char is one break; } } $newBase = \substr($plural, 0, $pluralLength - $suffixLength); $newSuffix = $map[4]; // Check whether the first character in the plural suffix // is uppercased. If yes, uppercase the first character in // the singular suffix too $firstUpper = \ctype_upper($pluralRev[$j - 1]); if (\is_array($newSuffix)) { $singulars = []; foreach ($newSuffix as $newSuffixEntry) { $singulars[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry); } return $singulars; } return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)]; } // Suffix is longer than word if ($j === $pluralLength) { break; } } } // Assume that plural and singular is identical return [$plural]; } /** * {@inheritdoc} */ public function pluralize(string $singular) : array { $singularRev = \strrev($singular); $lowerSingularRev = \strtolower($singularRev); $singularLength = \strlen($lowerSingularRev); // Check if the word is one which is not inflected, return early if so if (\in_array($lowerSingularRev, self::$uninflected, \true)) { return [$singular]; } // The outer loop iterates over the entries of the singular table // The inner loop $j iterates over the characters of the singular suffix // in the singular table to compare them with the characters of the actual // given singular suffix foreach (self::$singularMap as $map) { $suffix = $map[0]; $suffixLength = $map[1]; $j = 0; // Compare characters in the singular table and of the suffix of the // given plural one by one while ($suffix[$j] === $lowerSingularRev[$j]) { // Let $j point to the next character ++$j; // Successfully compared the last character // Add an entry with the plural suffix to the plural array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $singularLength) { $nextIsVocal = \false !== \strpos('aeiou', $lowerSingularRev[$j]); if (!$map[2] && $nextIsVocal) { // suffix may not succeed a vocal but next char is one break; } if (!$map[3] && !$nextIsVocal) { // suffix may not succeed a consonant but next char is one break; } } $newBase = \substr($singular, 0, $singularLength - $suffixLength); $newSuffix = $map[4]; // Check whether the first character in the singular suffix // is uppercased. If yes, uppercase the first character in // the singular suffix too $firstUpper = \ctype_upper($singularRev[$j - 1]); if (\is_array($newSuffix)) { $plurals = []; foreach ($newSuffix as $newSuffixEntry) { $plurals[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry); } return $plurals; } return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)]; } // Suffix is longer than word if ($j === $singularLength) { break; } } } // Assume that plural is singular with a trailing `s` return [$singular . 's']; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String\Slugger; use _HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractUnicodeString; /** * Creates a URL-friendly slug from a given string. * * @author Titouan Galopin */ interface SluggerInterface { /** * Creates a slug for the given string and locale, using appropriate transliteration when needed. */ public function slug(string $string, string $separator = '-', string $locale = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractUnicodeString; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String\Slugger; use _HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractUnicodeString; use _HumbugBoxd02f763d3c56\Symfony\Component\String\UnicodeString; use _HumbugBoxd02f763d3c56\Symfony\Contracts\Translation\LocaleAwareInterface; if (!\interface_exists(\_HumbugBoxd02f763d3c56\Symfony\Contracts\Translation\LocaleAwareInterface::class)) { throw new \LogicException('You cannot use the "Symfony\\Component\\String\\Slugger\\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".'); } /** * @author Titouan Galopin */ class AsciiSlugger implements \_HumbugBoxd02f763d3c56\Symfony\Component\String\Slugger\SluggerInterface, \_HumbugBoxd02f763d3c56\Symfony\Contracts\Translation\LocaleAwareInterface { private const LOCALE_TO_TRANSLITERATOR_ID = ['am' => 'Amharic-Latin', 'ar' => 'Arabic-Latin', 'az' => 'Azerbaijani-Latin', 'be' => 'Belarusian-Latin', 'bg' => 'Bulgarian-Latin', 'bn' => 'Bengali-Latin', 'de' => 'de-ASCII', 'el' => 'Greek-Latin', 'fa' => 'Persian-Latin', 'he' => 'Hebrew-Latin', 'hy' => 'Armenian-Latin', 'ka' => 'Georgian-Latin', 'kk' => 'Kazakh-Latin', 'ky' => 'Kirghiz-Latin', 'ko' => 'Korean-Latin', 'mk' => 'Macedonian-Latin', 'mn' => 'Mongolian-Latin', 'or' => 'Oriya-Latin', 'ps' => 'Pashto-Latin', 'ru' => 'Russian-Latin', 'sr' => 'Serbian-Latin', 'sr_Cyrl' => 'Serbian-Latin', 'th' => 'Thai-Latin', 'tk' => 'Turkmen-Latin', 'uk' => 'Ukrainian-Latin', 'uz' => 'Uzbek-Latin', 'zh' => 'Han-Latin']; private $defaultLocale; private $symbolsMap = ['en' => ['@' => 'at', '&' => 'and']]; /** * Cache of transliterators per locale. * * @var \Transliterator[] */ private $transliterators = []; public function __construct(string $defaultLocale = null, array $symbolsMap = null) { $this->defaultLocale = $defaultLocale; $this->symbolsMap = $symbolsMap ?? $this->symbolsMap; } /** * {@inheritdoc} */ public function setLocale($locale) { $this->defaultLocale = $locale; } /** * {@inheritdoc} */ public function getLocale() { return $this->defaultLocale; } /** * {@inheritdoc} */ public function slug(string $string, string $separator = '-', string $locale = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractUnicodeString { $locale = $locale ?? $this->defaultLocale; $transliterator = []; if ('de' === $locale || 0 === \strpos($locale, 'de_')) { // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl) $transliterator = ['de-ASCII']; } elseif (\function_exists('transliterator_transliterate') && $locale) { $transliterator = (array) $this->createTransliterator($locale); } $unicodeString = (new \_HumbugBoxd02f763d3c56\Symfony\Component\String\UnicodeString($string))->ascii($transliterator); if (isset($this->symbolsMap[$locale])) { foreach ($this->symbolsMap[$locale] as $char => $replace) { $unicodeString = $unicodeString->replace($char, ' ' . $replace . ' '); } } return $unicodeString->replaceMatches('/[^A-Za-z0-9]++/', $separator)->trim($separator); } private function createTransliterator(string $locale) : ?\Transliterator { if (\array_key_exists($locale, $this->transliterators)) { return $this->transliterators[$locale]; } // Exact locale supported, cache and return if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) { return $this->transliterators[$locale] = \Transliterator::create($id . '/BGN') ?? \Transliterator::create($id); } // Locale not supported and no parent, fallback to any-latin if (\false === ($str = \strrchr($locale, '_'))) { return $this->transliterators[$locale] = null; } // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales $parent = \substr($locale, 0, -\strlen($str)); if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) { $transliterator = \Transliterator::create($id . '/BGN') ?? \Transliterator::create($id); } return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\ExceptionInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException; /** * Represents a string of Unicode code points encoded as UTF-8. * * @author Nicolas Grekas * @author Hugo Hamon * * @throws ExceptionInterface */ class CodePointString extends \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractUnicodeString { public function __construct(string $string = '') { if ('' !== $string && !\preg_match('//u', $string)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } $this->string = $string; } public function append(string ...$suffix) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = clone $this; $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix); if (!\preg_match('//u', $str->string)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function chunk(int $length = 1) : array { if (1 > $length) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('The chunk length must be greater than zero.'); } if ('' === $this->string) { return []; } $rx = '/('; while (65535 < $length) { $rx .= '.{65535}'; $length -= 65535; } $rx .= '.{' . $length . '})/us'; $str = clone $this; $chunks = []; foreach (\preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { $str->string = $chunk; $chunks[] = clone $str; } return $chunks; } public function codePointsAt(int $offset) : array { $str = $offset ? $this->slice($offset, 1) : $this; return '' === $str->string ? [] : [\mb_ord($str->string, 'UTF-8')]; } public function endsWith($suffix) : bool { if ($suffix instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $suffix = $suffix->string; } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); } else { $suffix = (string) $suffix; } if ('' === $suffix || !\preg_match('//u', $suffix)) { return \false; } if ($this->ignoreCase) { return \preg_match('{' . \preg_quote($suffix) . '$}iuD', $this->string); } return \strlen($this->string) >= \strlen($suffix) && 0 === \substr_compare($this->string, $suffix, -\strlen($suffix)); } public function equalsTo($string) : bool { if ($string instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $string = $string->string; } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); } else { $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { return \strlen($string) === \strlen($this->string) && 0 === \mb_stripos($this->string, $string, 0, 'UTF-8'); } return $string === $this->string; } public function indexOf($needle, int $offset = 0) : ?int { if ($needle instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? \mb_stripos($this->string, $needle, $offset, 'UTF-8') : \mb_strpos($this->string, $needle, $offset, 'UTF-8'); return \false === $i ? null : $i; } public function indexOfLast($needle, int $offset = 0) : ?int { if ($needle instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? \mb_strripos($this->string, $needle, $offset, 'UTF-8') : \mb_strrpos($this->string, $needle, $offset, 'UTF-8'); return \false === $i ? null : $i; } public function length() : int { return \mb_strlen($this->string, 'UTF-8'); } public function prepend(string ...$prefix) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = clone $this; $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $this->string; if (!\preg_match('//u', $str->string)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function replace(string $from, string $to) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = clone $this; if ('' === $from || !\preg_match('//u', $from)) { return $str; } if ('' !== $to && !\preg_match('//u', $to)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } if ($this->ignoreCase) { $str->string = \implode($to, \preg_split('{' . \preg_quote($from) . '}iuD', $this->string)); } else { $str->string = \str_replace($from, $to, $this->string); } return $str; } public function slice(int $start = 0, int $length = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = clone $this; $str->string = \mb_substr($this->string, $start, $length, 'UTF-8'); return $str; } public function splice(string $replacement, int $start = 0, int $length = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { if (!\preg_match('//u', $replacement)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } $str = clone $this; $start = $start ? \strlen(\mb_substr($this->string, 0, $start, 'UTF-8')) : 0; $length = $length ? \strlen(\mb_substr($this->string, $start, $length, 'UTF-8')) : $length; $str->string = \substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); return $str; } public function split(string $delimiter, int $limit = null, int $flags = null) : array { if (1 > ($limit = $limit ?? \PHP_INT_MAX)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Split limit must be a positive integer.'); } if ('' === $delimiter) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Split delimiter is empty.'); } if (null !== $flags) { return parent::split($delimiter . 'u', $limit, $flags); } if (!\preg_match('//u', $delimiter)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); } $str = clone $this; $chunks = $this->ignoreCase ? \preg_split('{' . \preg_quote($delimiter) . '}iuD', $this->string, $limit) : \explode($delimiter, $this->string, $limit); foreach ($chunks as &$chunk) { $str->string = $chunk; $chunk = clone $str; } return $chunks; } public function startsWith($prefix) : bool { if ($prefix instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $prefix = $prefix->string; } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { return parent::startsWith($prefix); } else { $prefix = (string) $prefix; } if ('' === $prefix || !\preg_match('//u', $prefix)) { return \false; } if ($this->ignoreCase) { return 0 === \mb_stripos($this->string, $prefix, 0, 'UTF-8'); } return 0 === \strncmp($this->string, $prefix, \strlen($prefix)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\ExceptionInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException; /** * Represents a string of Unicode grapheme clusters encoded as UTF-8. * * A letter followed by combining characters (accents typically) form what Unicode defines * as a grapheme cluster: a character as humans mean it in written texts. This class knows * about the concept and won't split a letter apart from its combining accents. It also * ensures all string comparisons happen on their canonically-composed representation, * ignoring e.g. the order in which accents are listed when a letter has many of them. * * @see https://unicode.org/reports/tr15/ * * @author Nicolas Grekas * @author Hugo Hamon * * @throws ExceptionInterface */ class UnicodeString extends \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractUnicodeString { public function __construct(string $string = '') { $this->string = \normalizer_is_normalized($string) ? $string : \normalizer_normalize($string); if (\false === $this->string) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } } public function append(string ...$suffix) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = clone $this; $str->string = $this->string . (1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix)); \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); if (\false === $str->string) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function chunk(int $length = 1) : array { if (1 > $length) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('The chunk length must be greater than zero.'); } if ('' === $this->string) { return []; } $rx = '/('; while (65535 < $length) { $rx .= '\\X{65535}'; $length -= 65535; } $rx .= '\\X{' . $length . '})/u'; $str = clone $this; $chunks = []; foreach (\preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { $str->string = $chunk; $chunks[] = clone $str; } return $chunks; } public function endsWith($suffix) : bool { if ($suffix instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $suffix = $suffix->string; } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); } else { $suffix = (string) $suffix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($suffix, $form) ?: ($suffix = \normalizer_normalize($suffix, $form)); if ('' === $suffix || \false === $suffix) { return \false; } if ($this->ignoreCase) { return 0 === \mb_stripos(\grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8'); } return $suffix === \grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)); } public function equalsTo($string) : bool { if ($string instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $string = $string->string; } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); } else { $string = (string) $string; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($string, $form) ?: ($string = \normalizer_normalize($string, $form)); if ('' !== $string && \false !== $string && $this->ignoreCase) { return \strlen($string) === \strlen($this->string) && 0 === \mb_stripos($this->string, $string, 0, 'UTF-8'); } return $string === $this->string; } public function indexOf($needle, int $offset = 0) : ?int { if ($needle instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); } else { $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($needle, $form) ?: ($needle = \normalizer_normalize($needle, $form)); if ('' === $needle || \false === $needle) { return null; } try { $i = $this->ignoreCase ? \grapheme_stripos($this->string, $needle, $offset) : \grapheme_strpos($this->string, $needle, $offset); } catch (\ValueError $e) { return null; } return \false === $i ? null : $i; } public function indexOfLast($needle, int $offset = 0) : ?int { if ($needle instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); } else { $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($needle, $form) ?: ($needle = \normalizer_normalize($needle, $form)); if ('' === $needle || \false === $needle) { return null; } $string = $this->string; if (0 > $offset) { // workaround https://bugs.php.net/74264 if (0 > ($offset += \grapheme_strlen($needle))) { $string = \grapheme_substr($string, 0, $offset); } $offset = 0; } $i = $this->ignoreCase ? \grapheme_strripos($string, $needle, $offset) : \grapheme_strrpos($string, $needle, $offset); return \false === $i ? null : $i; } public function join(array $strings, string $lastGlue = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = parent::join($strings, $lastGlue); \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); return $str; } public function length() : int { return \grapheme_strlen($this->string); } /** * @return static */ public function normalize(int $form = self::NFC) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; if (\in_array($form, [self::NFC, self::NFKC], \true)) { \normalizer_is_normalized($str->string, $form) ?: ($str->string = \normalizer_normalize($str->string, $form)); } elseif (!\in_array($form, [self::NFD, self::NFKD], \true)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Unsupported normalization form.'); } elseif (!\normalizer_is_normalized($str->string, $form)) { $str->string = \normalizer_normalize($str->string, $form); $str->ignoreCase = null; } return $str; } public function prepend(string ...$prefix) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = clone $this; $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $this->string; \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); if (\false === $str->string) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function replace(string $from, string $to) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = clone $this; \normalizer_is_normalized($from) ?: ($from = \normalizer_normalize($from)); if ('' !== $from && \false !== $from) { $tail = $str->string; $result = ''; $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; while ('' !== $tail && \false !== ($i = $indexOf($tail, $from))) { $slice = \grapheme_substr($tail, 0, $i); $result .= $slice . $to; $tail = \substr($tail, \strlen($slice) + \strlen($from)); } $str->string = $result . $tail; \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); if (\false === $str->string) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } } return $str; } public function replaceMatches(string $fromRegexp, $to) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = parent::replaceMatches($fromRegexp, $to); \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); return $str; } public function slice(int $start = 0, int $length = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = clone $this; try { $str->string = (string) \grapheme_substr($this->string, $start, $length ?? \PHP_INT_MAX); } catch (\ValueError $e) { $str->string = ''; } return $str; } public function splice(string $replacement, int $start = 0, int $length = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { $str = clone $this; $start = $start ? \strlen(\grapheme_substr($this->string, 0, $start)) : 0; $length = $length ? \strlen(\grapheme_substr($this->string, $start, $length ?? \PHP_INT_MAX)) : $length; $str->string = \substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string)); if (\false === $str->string) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function split(string $delimiter, int $limit = null, int $flags = null) : array { if (1 > ($limit = $limit ?? \PHP_INT_MAX)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Split limit must be a positive integer.'); } if ('' === $delimiter) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Split delimiter is empty.'); } if (null !== $flags) { return parent::split($delimiter . 'u', $limit, $flags); } \normalizer_is_normalized($delimiter) ?: ($delimiter = \normalizer_normalize($delimiter)); if (\false === $delimiter) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); } $str = clone $this; $tail = $this->string; $chunks = []; $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; while (1 < $limit && \false !== ($i = $indexOf($tail, $delimiter))) { $str->string = \grapheme_substr($tail, 0, $i); $chunks[] = clone $str; $tail = \substr($tail, \strlen($str->string) + \strlen($delimiter)); --$limit; } $str->string = $tail; $chunks[] = clone $str; return $chunks; } public function startsWith($prefix) : bool { if ($prefix instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString) { $prefix = $prefix->string; } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { return parent::startsWith($prefix); } else { $prefix = (string) $prefix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; \normalizer_is_normalized($prefix, $form) ?: ($prefix = \normalizer_normalize($prefix, $form)); if ('' === $prefix || \false === $prefix) { return \false; } if ($this->ignoreCase) { return 0 === \mb_stripos(\grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8'); } return $prefix === \grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES); } public function __wakeup() { \normalizer_is_normalized($this->string) ?: ($this->string = \normalizer_normalize($this->string)); } public function __clone() { if (null === $this->ignoreCase) { \normalizer_is_normalized($this->string) ?: ($this->string = \normalizer_normalize($this->string)); } $this->ignoreCase = \false; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\ExceptionInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException; /** * Represents a binary-safe string of bytes. * * @author Nicolas Grekas * @author Hugo Hamon * * @throws ExceptionInterface */ class ByteString extends \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { private const ALPHABET_ALPHANUMERIC = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; public function __construct(string $string = '') { $this->string = $string; } /* * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03) * * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16 * * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE). * * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) */ public static function fromRandom(int $length = 16, string $alphabet = null) : self { if ($length <= 0) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException(\sprintf('A strictly positive length is expected, "%d" given.', $length)); } $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC; $alphabetSize = \strlen($alphabet); $bits = (int) \ceil(\log($alphabetSize, 2.0)); if ($bits <= 0 || $bits > 56) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.'); } $ret = ''; while ($length > 0) { $urandomLength = (int) \ceil(2 * $length * $bits / 8.0); $data = \random_bytes($urandomLength); $unpackedData = 0; $unpackedBits = 0; for ($i = 0; $i < $urandomLength && $length > 0; ++$i) { // Unpack 8 bits $unpackedData = $unpackedData << 8 | \ord($data[$i]); $unpackedBits += 8; // While we have enough bits to select a character from the alphabet, keep // consuming the random data for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) { $index = $unpackedData & (1 << $bits) - 1; $unpackedData >>= $bits; // Unfortunately, the alphabet size is not necessarily a power of two. // Worst case, it is 2^k + 1, which means we need (k+1) bits and we // have around a 50% chance of missing as k gets larger if ($index < $alphabetSize) { $ret .= $alphabet[$index]; --$length; } } } } return new static($ret); } public function bytesAt(int $offset) : array { $str = $this->string[$offset] ?? ''; return '' === $str ? [] : [\ord($str)]; } public function append(string ...$suffix) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix); return $str; } public function camel() : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \lcfirst(\str_replace(' ', '', \ucwords(\preg_replace('/[^a-zA-Z0-9\\x7f-\\xff]++/', ' ', $this->string)))); return $str; } public function chunk(int $length = 1) : array { if (1 > $length) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('The chunk length must be greater than zero.'); } if ('' === $this->string) { return []; } $str = clone $this; $chunks = []; foreach (\str_split($this->string, $length) as $chunk) { $str->string = $chunk; $chunks[] = clone $str; } return $chunks; } public function endsWith($suffix) : bool { if ($suffix instanceof parent) { $suffix = $suffix->string; } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); } else { $suffix = (string) $suffix; } return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === \substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase); } public function equalsTo($string) : bool { if ($string instanceof parent) { $string = $string->string; } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); } else { $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { return 0 === \strcasecmp($string, $this->string); } return $string === $this->string; } public function folded() : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \strtolower($str->string); return $str; } public function indexOf($needle, int $offset = 0) : ?int { if ($needle instanceof parent) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? \stripos($this->string, $needle, $offset) : \strpos($this->string, $needle, $offset); return \false === $i ? null : $i; } public function indexOfLast($needle, int $offset = 0) : ?int { if ($needle instanceof parent) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? \strripos($this->string, $needle, $offset) : \strrpos($this->string, $needle, $offset); return \false === $i ? null : $i; } public function isUtf8() : bool { return '' === $this->string || \preg_match('//u', $this->string); } public function join(array $strings, string $lastGlue = null) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . \array_pop($strings) : ''; $str->string = \implode($this->string, $strings) . $tail; return $str; } public function length() : int { return \strlen($this->string); } public function lower() : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \strtolower($str->string); return $str; } public function match(string $regexp, int $flags = 0, int $offset = 0) : array { $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match'; if ($this->ignoreCase) { $regexp .= 'i'; } \set_error_handler(static function ($t, $m) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException($m); }); try { if (\false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Matching failed with ' . $k . '.'); } } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Matching failed with unknown error code.'); } } finally { \restore_error_handler(); } return $matches; } public function padBoth(int $length, string $padStr = ' ') : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_BOTH); return $str; } public function padEnd(int $length, string $padStr = ' ') : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT); return $str; } public function padStart(int $length, string $padStr = ' ') : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_LEFT); return $str; } public function prepend(string ...$prefix) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $str->string; return $str; } public function replace(string $from, string $to) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; if ('' !== $from) { $str->string = $this->ignoreCase ? \str_ireplace($from, $to, $this->string) : \str_replace($from, $to, $this->string); } return $str; } public function replaceMatches(string $fromRegexp, $to) : \_HumbugBoxd02f763d3c56\parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; } if (\is_array($to)) { if (!\is_callable($to)) { throw new \TypeError(\sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); } $replace = 'preg_replace_callback'; } else { $replace = $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace'; } \set_error_handler(static function ($t, $m) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException($m); }); try { if (null === ($string = $replace($fromRegexp, $to, $this->string))) { $lastError = \preg_last_error(); foreach (\get_defined_constants(\true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === \substr($k, -6)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Matching failed with ' . $k . '.'); } } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\RuntimeException('Matching failed with unknown error code.'); } } finally { \restore_error_handler(); } $str = clone $this; $str->string = $string; return $str; } public function reverse() : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \strrev($str->string); return $str; } public function slice(int $start = 0, int $length = null) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = (string) \substr($this->string, $start, $length ?? \PHP_INT_MAX); return $str; } public function snake() : \_HumbugBoxd02f763d3c56\parent { $str = $this->camel()->title(); $str->string = \strtolower(\preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\\d])([A-Z])/'], '_HumbugBoxd02f763d3c56\\1_\\2', $str->string)); return $str; } public function splice(string $replacement, int $start = 0, int $length = null) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); return $str; } public function split(string $delimiter, int $limit = null, int $flags = null) : array { if (1 > ($limit = $limit ?? \PHP_INT_MAX)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Split limit must be a positive integer.'); } if ('' === $delimiter) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException('Split delimiter is empty.'); } if (null !== $flags) { return parent::split($delimiter, $limit, $flags); } $str = clone $this; $chunks = $this->ignoreCase ? \preg_split('{' . \preg_quote($delimiter) . '}iD', $this->string, $limit) : \explode($delimiter, $this->string, $limit); foreach ($chunks as &$chunk) { $str->string = $chunk; $chunk = clone $str; } return $chunks; } public function startsWith($prefix) : bool { if ($prefix instanceof parent) { $prefix = $prefix->string; } elseif (!\is_string($prefix)) { return parent::startsWith($prefix); } return '' !== $prefix && 0 === ($this->ignoreCase ? \strncasecmp($this->string, $prefix, \strlen($prefix)) : \strncmp($this->string, $prefix, \strlen($prefix))); } public function title(bool $allWords = \false) : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = $allWords ? \ucwords($str->string) : \ucfirst($str->string); return $str; } public function toUnicodeString(string $fromEncoding = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\UnicodeString { return new \_HumbugBoxd02f763d3c56\Symfony\Component\String\UnicodeString($this->toCodePointString($fromEncoding)->string); } public function toCodePointString(string $fromEncoding = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\CodePointString { $u = new \_HumbugBoxd02f763d3c56\Symfony\Component\String\CodePointString(); if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], \true) && \preg_match('//u', $this->string)) { $u->string = $this->string; return $u; } \set_error_handler(static function ($t, $m) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException($m); }); try { try { $validEncoding = \false !== \mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', \true); } catch (\_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException $e) { if (!\function_exists('iconv')) { throw $e; } $u->string = \iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string); return $u; } } finally { \restore_error_handler(); } if (!$validEncoding) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\String\Exception\InvalidArgumentException(\sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252')); } $u->string = \mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252'); return $u; } public function trim(string $chars = " \t\n\r\0\v\f") : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \trim($str->string, $chars); return $str; } public function trimEnd(string $chars = " \t\n\r\0\v\f") : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \rtrim($str->string, $chars); return $str; } public function trimStart(string $chars = " \t\n\r\0\v\f") : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \ltrim($str->string, $chars); return $str; } public function upper() : \_HumbugBoxd02f763d3c56\parent { $str = clone $this; $str->string = \strtoupper($str->string); return $str; } public function width(bool $ignoreAnsiDecoration = \true) : int { $string = \preg_match('//u', $this->string) ? $this->string : \preg_replace('/[\\x80-\\xFF]/', '?', $this->string); return (new \_HumbugBoxd02f763d3c56\Symfony\Component\String\CodePointString($string))->width($ignoreAnsiDecoration); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\String; function u(string $string = '') : \_HumbugBoxd02f763d3c56\Symfony\Component\String\UnicodeString { return new \_HumbugBoxd02f763d3c56\Symfony\Component\String\UnicodeString($string); } function b(string $string = '') : \_HumbugBoxd02f763d3c56\Symfony\Component\String\ByteString { return new \_HumbugBoxd02f763d3c56\Symfony\Component\String\ByteString($string); } /** * @return UnicodeString|ByteString */ function s(string $string) : \_HumbugBoxd02f763d3c56\Symfony\Component\String\AbstractString { return \preg_match('//u', $string) ? new \_HumbugBoxd02f763d3c56\Symfony\Component\String\UnicodeString($string) : new \_HumbugBoxd02f763d3c56\Symfony\Component\String\ByteString($string); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use _HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme as p; if (\extension_loaded('intl')) { return; } if (!\defined('GRAPHEME_EXTR_COUNT')) { \define('GRAPHEME_EXTR_COUNT', 0); } if (!\defined('GRAPHEME_EXTR_MAXBYTES')) { \define('GRAPHEME_EXTR_MAXBYTES', 1); } if (!\defined('GRAPHEME_EXTR_MAXCHARS')) { \define('GRAPHEME_EXTR_MAXCHARS', 2); } if (!\function_exists('grapheme_extract')) { function grapheme_extract($s, $size, $type = 0, $start = 0, &$next = 0) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::grapheme_extract($s, $size, $type, $start, $next); } } if (!\function_exists('grapheme_stripos')) { function grapheme_stripos($s, $needle, $offset = 0) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::grapheme_stripos($s, $needle, $offset); } } if (!\function_exists('grapheme_stristr')) { function grapheme_stristr($s, $needle, $beforeNeedle = \false) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::grapheme_stristr($s, $needle, $beforeNeedle); } } if (!\function_exists('grapheme_strlen')) { function grapheme_strlen($s) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::grapheme_strlen($s); } } if (!\function_exists('grapheme_strpos')) { function grapheme_strpos($s, $needle, $offset = 0) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::grapheme_strpos($s, $needle, $offset); } } if (!\function_exists('grapheme_strripos')) { function grapheme_strripos($s, $needle, $offset = 0) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::grapheme_strripos($s, $needle, $offset); } } if (!\function_exists('grapheme_strrpos')) { function grapheme_strrpos($s, $needle, $offset = 0) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::grapheme_strrpos($s, $needle, $offset); } } if (!\function_exists('grapheme_strstr')) { function grapheme_strstr($s, $needle, $beforeNeedle = \false) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::grapheme_strstr($s, $needle, $beforeNeedle); } } if (!\function_exists('grapheme_substr')) { function grapheme_substr($s, $start, $len = 2147483647) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::grapheme_substr($s, $start, $len); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme; \define('SYMFONY_GRAPHEME_CLUSTER_RX', \PCRE_VERSION >= '8.32' ? '\\X' : \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Intl\Grapheme\Grapheme::GRAPHEME_CLUSTER_RX); /** * Partial intl implementation in pure PHP. * * Implemented: * - grapheme_extract - Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8 * - grapheme_stripos - Find position (in grapheme units) of first occurrence of a case-insensitive string * - grapheme_stristr - Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack * - grapheme_strlen - Get string length in grapheme units * - grapheme_strpos - Find position (in grapheme units) of first occurrence of a string * - grapheme_strripos - Find position (in grapheme units) of last occurrence of a case-insensitive string * - grapheme_strrpos - Find position (in grapheme units) of last occurrence of a string * - grapheme_strstr - Returns part of haystack string from the first occurrence of needle to the end of haystack * - grapheme_substr - Return part of a string * * @author Nicolas Grekas * * @internal */ final class Grapheme { // (CRLF|([ZWNJ-ZWJ]|T+|L*(LV?V+|LV|LVT)T*|L+|[^Control])[Extend]*|[Control]) // This regular expression is a work around for http://bugs.exim.org/1279 const GRAPHEME_CLUSTER_RX = '(?:\\r\\n|(?:[ -~\\x{200C}\\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\\p{Cc}\\p{Cf}\\p{Zl}\\p{Zp}])[\\p{Mn}\\p{Me}\\x{09BE}\\x{09D7}\\x{0B3E}\\x{0B57}\\x{0BBE}\\x{0BD7}\\x{0CC2}\\x{0CD5}\\x{0CD6}\\x{0D3E}\\x{0D57}\\x{0DCF}\\x{0DDF}\\x{200C}\\x{200D}\\x{1D165}\\x{1D16E}-\\x{1D172}]*|[\\p{Cc}\\p{Cf}\\p{Zl}\\p{Zp}])'; public static function grapheme_extract($s, $size, $type = \GRAPHEME_EXTR_COUNT, $start = 0, &$next = 0) { if (\PHP_VERSION_ID >= 70100 && 0 > $start) { $start = \strlen($s) + $start; } if (!\is_scalar($s)) { $hasError = \false; \set_error_handler(function () use(&$hasError) { $hasError = \true; }); $next = \substr($s, $start); \restore_error_handler(); if ($hasError) { \substr($s, $start); $s = ''; } else { $s = $next; } } else { $s = \substr($s, $start); } $size = (int) $size; $type = (int) $type; $start = (int) $start; if (!isset($s[0]) || 0 > $size || 0 > $start || 0 > $type || 2 < $type) { return \false; } if (0 === $size) { return ''; } $next = $start; $s = \preg_split('/(' . SYMFONY_GRAPHEME_CLUSTER_RX . ')/u', "\r\n" . $s, $size + 1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE); if (!isset($s[1])) { return \false; } $i = 1; $ret = ''; do { if (\GRAPHEME_EXTR_COUNT === $type) { --$size; } elseif (\GRAPHEME_EXTR_MAXBYTES === $type) { $size -= \strlen($s[$i]); } else { $size -= \iconv_strlen($s[$i], 'UTF-8//IGNORE'); } if ($size >= 0) { $ret .= $s[$i]; } } while (isset($s[++$i]) && $size > 0); $next += \strlen($ret); return $ret; } public static function grapheme_strlen($s) { \preg_replace('/' . SYMFONY_GRAPHEME_CLUSTER_RX . '/u', '', $s, -1, $len); return 0 === $len && '' !== $s ? null : $len; } public static function grapheme_substr($s, $start, $len = 2147483647) { \preg_match_all('/' . SYMFONY_GRAPHEME_CLUSTER_RX . '/u', $s, $s); $slen = \count($s[0]); $start = (int) $start; if (0 > $start) { $start += $slen; } if (0 > $start) { return \false; } if ($start >= $slen) { return \false; } $rem = $slen - $start; if (0 > $len) { $len += $rem; } if (0 === $len) { return ''; } if (0 > $len) { return \false; } if ($len > $rem) { $len = $rem; } return \implode('', \array_slice($s[0], $start, $len)); } public static function grapheme_strpos($s, $needle, $offset = 0) { return self::grapheme_position($s, $needle, $offset, 0); } public static function grapheme_stripos($s, $needle, $offset = 0) { return self::grapheme_position($s, $needle, $offset, 1); } public static function grapheme_strrpos($s, $needle, $offset = 0) { return self::grapheme_position($s, $needle, $offset, 2); } public static function grapheme_strripos($s, $needle, $offset = 0) { return self::grapheme_position($s, $needle, $offset, 3); } public static function grapheme_stristr($s, $needle, $beforeNeedle = \false) { return \mb_stristr($s, $needle, $beforeNeedle, 'UTF-8'); } public static function grapheme_strstr($s, $needle, $beforeNeedle = \false) { return \mb_strstr($s, $needle, $beforeNeedle, 'UTF-8'); } private static function grapheme_position($s, $needle, $offset, $mode) { $needle = (string) $needle; if (!\preg_match('/./us', $needle)) { return \false; } $s = (string) $s; if (!\preg_match('/./us', $s)) { return \false; } if ($offset > 0) { $s = self::grapheme_substr($s, $offset); } elseif ($offset < 0) { if (\PHP_VERSION_ID < 50535 || 50600 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 50621 || 70000 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70006) { $offset = 0; } elseif (2 > $mode) { $offset += self::grapheme_strlen($s); $s = self::grapheme_substr($s, $offset); if (0 > $offset) { $offset = 0; } } elseif (0 > ($offset += self::grapheme_strlen($needle))) { $s = self::grapheme_substr($s, 0, $offset); $offset = 0; } else { $offset = 0; } } switch ($mode) { case 0: $needle = \iconv_strpos($s, $needle, 0, 'UTF-8'); break; case 1: $needle = \mb_stripos($s, $needle, 0, 'UTF-8'); break; case 2: $needle = \iconv_strrpos($s, $needle, 'UTF-8'); break; default: $needle = \mb_strripos($s, $needle, 0, 'UTF-8'); break; } return \false !== $needle ? self::grapheme_strlen(\iconv_substr($s, 0, $needle, 'UTF-8')) + $offset : \false; } } Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Polyfill\Php80; /** * @author Ion Bazan * @author Nico Oelgart * @author Nicolas Grekas * * @internal */ final class Php80 { public static function fdiv(float $dividend, float $divisor) : float { return @($dividend / $divisor); } public static function get_debug_type($value) : string { switch (\true) { case null === $value: return 'null'; case \is_bool($value): return 'bool'; case \is_string($value): return 'string'; case \is_array($value): return 'array'; case \is_int($value): return 'int'; case \is_float($value): return 'float'; case \is_object($value): break; case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; default: if (null === ($type = @\get_resource_type($value))) { return 'unknown'; } if ('Unknown' === $type) { $type = 'closed'; } return "resource ({$type})"; } $class = \get_class($value); if (\false === \strpos($class, '@')) { return $class; } return (\get_parent_class($class) ?: \key(\class_implements($class)) ?: 'class') . '@anonymous'; } public static function get_resource_id($res) : int { if (!\is_resource($res) && null === @\get_resource_type($res)) { throw new \TypeError(\sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', \get_debug_type($res))); } return (int) $res; } public static function preg_last_error_msg() : string { switch (\preg_last_error()) { case \PREG_INTERNAL_ERROR: return 'Internal error'; case \PREG_BAD_UTF8_ERROR: return 'Malformed UTF-8 characters, possibly incorrectly encoded'; case \PREG_BAD_UTF8_OFFSET_ERROR: return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; case \PREG_BACKTRACK_LIMIT_ERROR: return 'Backtrack limit exhausted'; case \PREG_RECURSION_LIMIT_ERROR: return 'Recursion limit exhausted'; case \PREG_JIT_STACKLIMIT_ERROR: return 'JIT stack limit exhausted'; case \PREG_NO_ERROR: return 'No error'; default: return 'Unknown error'; } } public static function str_contains(string $haystack, string $needle) : bool { return '' === $needle || \false !== \strpos($haystack, $needle); } public static function str_starts_with(string $haystack, string $needle) : bool { return 0 === \strncmp($haystack, $needle, \strlen($needle)); } public static function str_ends_with(string $haystack, string $needle) : bool { return '' === $needle || '' !== $haystack && 0 === \substr_compare($haystack, $needle, -\strlen($needle)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use _HumbugBoxd02f763d3c56\Symfony\Polyfill\Php80 as p; if (\PHP_VERSION_ID >= 80000) { return; } if (!\defined('FILTER_VALIDATE_BOOL') && \defined('FILTER_VALIDATE_BOOLEAN')) { \define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); } if (!\function_exists('fdiv')) { function fdiv(float $dividend, float $divisor) : float { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Php80\Php80::fdiv($dividend, $divisor); } } if (!\function_exists('preg_last_error_msg')) { function preg_last_error_msg() : string { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Php80\Php80::preg_last_error_msg(); } } if (!\function_exists('str_contains')) { function str_contains(string $haystack, string $needle) : bool { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Php80\Php80::str_contains($haystack, $needle); } } if (!\function_exists('str_starts_with')) { function str_starts_with(string $haystack, string $needle) : bool { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Php80\Php80::str_starts_with($haystack, $needle); } } if (!\function_exists('str_ends_with')) { function str_ends_with(string $haystack, string $needle) : bool { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Php80\Php80::str_ends_with($haystack, $needle); } } if (!\function_exists('get_debug_type')) { function get_debug_type($value) : string { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Php80\Php80::get_debug_type($value); } } if (!\function_exists('get_resource_id')) { function get_resource_id($res) : int { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Php80\Php80::get_resource_id($res); } } Copyright (c) 2020 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\HelpCommand; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\ListCommand; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\CommandLoader\CommandLoaderInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleCommandEvent; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleErrorEvent; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleTerminateEvent; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\NamespaceNotFoundException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\DebugFormatterHelper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\FormatterHelper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\HelperSet; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\ProcessHelper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\QuestionHelper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\ArgvInput; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\ArrayInput; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputAwareInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutput; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Style\SymfonyStyle; use _HumbugBoxd02f763d3c56\Symfony\Component\ErrorHandler\ErrorHandler; use _HumbugBoxd02f763d3c56\Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use _HumbugBoxd02f763d3c56\Symfony\Contracts\Service\ResetInterface; /** * An Application is the container for a collection of commands. * * It is the main entry point of a Console application. * * This class is optimized for a standard CLI environment. * * Usage: * * $app = new Application('myapp', '1.0 (stable)'); * $app->add(new SimpleCommand()); * $app->run(); * * @author Fabien Potencier */ class Application implements \_HumbugBoxd02f763d3c56\Symfony\Contracts\Service\ResetInterface { private $commands = []; private $wantHelps = \false; private $runningCommand; private $name; private $version; private $commandLoader; private $catchExceptions = \true; private $autoExit = \true; private $definition; private $helperSet; private $dispatcher; private $terminal; private $defaultCommand; private $singleCommand = \false; private $initialized; public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN') { $this->name = $name; $this->version = $version; $this->terminal = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal(); $this->defaultCommand = 'list'; } /** * @final */ public function setDispatcher(\_HumbugBoxd02f763d3c56\Symfony\Contracts\EventDispatcher\EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } public function setCommandLoader(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\CommandLoader\CommandLoaderInterface $commandLoader) { $this->commandLoader = $commandLoader; } /** * Runs the current application. * * @return int 0 if everything went fine, or an error code * * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}. */ public function run(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input = null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output = null) { if (\function_exists('putenv')) { @\putenv('LINES=' . $this->terminal->getHeight()); @\putenv('COLUMNS=' . $this->terminal->getWidth()); } if (null === $input) { $input = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\ArgvInput(); } if (null === $output) { $output = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutput(); } $renderException = function (\Throwable $e) use($output) { if ($output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface) { $this->renderThrowable($e, $output->getErrorOutput()); } else { $this->renderThrowable($e, $output); } }; if ($phpHandler = \set_exception_handler($renderException)) { \restore_exception_handler(); if (!\is_array($phpHandler) || !$phpHandler[0] instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\ErrorHandler\ErrorHandler) { $errorHandler = \true; } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) { $phpHandler[0]->setExceptionHandler($errorHandler); } } $this->configureIO($input, $output); try { $exitCode = $this->doRun($input, $output); } catch (\Exception $e) { if (!$this->catchExceptions) { throw $e; } $renderException($e); $exitCode = $e->getCode(); if (\is_numeric($exitCode)) { $exitCode = (int) $exitCode; if (0 === $exitCode) { $exitCode = 1; } } else { $exitCode = 1; } } finally { // if the exception handler changed, keep it // otherwise, unregister $renderException if (!$phpHandler) { if (\set_exception_handler($renderException) === $renderException) { \restore_exception_handler(); } \restore_exception_handler(); } elseif (!$errorHandler) { $finalHandler = $phpHandler[0]->setExceptionHandler(null); if ($finalHandler !== $renderException) { $phpHandler[0]->setExceptionHandler($finalHandler); } } } if ($this->autoExit) { if ($exitCode > 255) { $exitCode = 255; } exit($exitCode); } return $exitCode; } /** * Runs the current application. * * @return int 0 if everything went fine, or an error code */ public function doRun(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { if (\true === $input->hasParameterOption(['--version', '-V'], \true)) { $output->writeln($this->getLongVersion()); return 0; } try { // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument. $input->bind($this->getDefinition()); } catch (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface $e) { // Errors must be ignored, full binding/validation happens later when the command is known. } $name = $this->getCommandName($input); if (\true === $input->hasParameterOption(['--help', '-h'], \true)) { if (!$name) { $name = 'help'; $input = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\ArrayInput(['command_name' => $this->defaultCommand]); } else { $this->wantHelps = \true; } } if (!$name) { $name = $this->defaultCommand; $definition = $this->getDefinition(); $definition->setArguments(\array_merge($definition->getArguments(), ['command' => new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument('command', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name)])); } try { $this->runningCommand = null; // the command name MUST be the first element of the input $command = $this->find($name); } catch (\Throwable $e) { if (!($e instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException && !$e instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\NamespaceNotFoundException) || 1 !== \count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) { if (null !== $this->dispatcher) { $event = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleErrorEvent($input, $output, $e); $this->dispatcher->dispatch($event, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\ConsoleEvents::ERROR); if (0 === $event->getExitCode()) { return 0; } $e = $event->getError(); } throw $e; } $alternative = $alternatives[0]; $style = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Style\SymfonyStyle($input, $output); $style->block(\sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error'); if (!$style->confirm(\sprintf('Do you want to run "%s" instead? ', $alternative), \false)) { if (null !== $this->dispatcher) { $event = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleErrorEvent($input, $output, $e); $this->dispatcher->dispatch($event, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\ConsoleEvents::ERROR); return $event->getExitCode(); } return 1; } $command = $this->find($alternative); } $this->runningCommand = $command; $exitCode = $this->doRunCommand($command, $input, $output); $this->runningCommand = null; return $exitCode; } /** * {@inheritdoc} */ public function reset() { } public function setHelperSet(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\HelperSet $helperSet) { $this->helperSet = $helperSet; } /** * Get the helper set associated with the command. * * @return HelperSet The HelperSet instance associated with this command */ public function getHelperSet() { if (!$this->helperSet) { $this->helperSet = $this->getDefaultHelperSet(); } return $this->helperSet; } public function setDefinition(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition) { $this->definition = $definition; } /** * Gets the InputDefinition related to this Application. * * @return InputDefinition The InputDefinition instance */ public function getDefinition() { if (!$this->definition) { $this->definition = $this->getDefaultInputDefinition(); } if ($this->singleCommand) { $inputDefinition = $this->definition; $inputDefinition->setArguments(); return $inputDefinition; } return $this->definition; } /** * Gets the help message. * * @return string A help message */ public function getHelp() { return $this->getLongVersion(); } /** * Gets whether to catch exceptions or not during commands execution. * * @return bool Whether to catch exceptions or not during commands execution */ public function areExceptionsCaught() { return $this->catchExceptions; } /** * Sets whether to catch exceptions or not during commands execution. */ public function setCatchExceptions(bool $boolean) { $this->catchExceptions = $boolean; } /** * Gets whether to automatically exit after a command execution or not. * * @return bool Whether to automatically exit after a command execution or not */ public function isAutoExitEnabled() { return $this->autoExit; } /** * Sets whether to automatically exit after a command execution or not. */ public function setAutoExit(bool $boolean) { $this->autoExit = $boolean; } /** * Gets the name of the application. * * @return string The application name */ public function getName() { return $this->name; } /** * Sets the application name. **/ public function setName(string $name) { $this->name = $name; } /** * Gets the application version. * * @return string The application version */ public function getVersion() { return $this->version; } /** * Sets the application version. */ public function setVersion(string $version) { $this->version = $version; } /** * Returns the long version of the application. * * @return string The long application version */ public function getLongVersion() { if ('UNKNOWN' !== $this->getName()) { if ('UNKNOWN' !== $this->getVersion()) { return \sprintf('%s %s', $this->getName(), $this->getVersion()); } return $this->getName(); } return 'Console Tool'; } /** * Registers a new command. * * @return Command The newly created command */ public function register(string $name) { return $this->add(new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command($name)); } /** * Adds an array of command objects. * * If a Command is not enabled it will not be added. * * @param Command[] $commands An array of commands */ public function addCommands(array $commands) { foreach ($commands as $command) { $this->add($command); } } /** * Adds a command object. * * If a command with the same name already exists, it will be overridden. * If the command is not enabled it will not be added. * * @return Command|null The registered command if enabled or null */ public function add(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command) { $this->init(); $command->setApplication($this); if (!$command->isEnabled()) { $command->setApplication(null); return null; } // Will throw if the command is not correctly initialized. $command->getDefinition(); if (!$command->getName()) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException(\sprintf('The command defined in "%s" cannot have an empty name.', \get_debug_type($command))); } $this->commands[$command->getName()] = $command; foreach ($command->getAliases() as $alias) { $this->commands[$alias] = $command; } return $command; } /** * Returns a registered command by name or alias. * * @return Command A Command object * * @throws CommandNotFoundException When given command name does not exist */ public function get(string $name) { $this->init(); if (!$this->has($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name)); } // When the command has a different name than the one used at the command loader level if (!isset($this->commands[$name])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException(\sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name)); } $command = $this->commands[$name]; if ($this->wantHelps) { $this->wantHelps = \false; $helpCommand = $this->get('help'); $helpCommand->setCommand($command); return $helpCommand; } return $command; } /** * Returns true if the command exists, false otherwise. * * @return bool true if the command exists, false otherwise */ public function has(string $name) { $this->init(); return isset($this->commands[$name]) || $this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name)); } /** * Returns an array of all unique namespaces used by currently registered commands. * * It does not return the global namespace which always exists. * * @return string[] An array of namespaces */ public function getNamespaces() { $namespaces = []; foreach ($this->all() as $command) { if ($command->isHidden()) { continue; } $namespaces = \array_merge($namespaces, $this->extractAllNamespaces($command->getName())); foreach ($command->getAliases() as $alias) { $namespaces = \array_merge($namespaces, $this->extractAllNamespaces($alias)); } } return \array_values(\array_unique(\array_filter($namespaces))); } /** * Finds a registered namespace by a name or an abbreviation. * * @return string A registered namespace * * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous */ public function findNamespace(string $namespace) { $allNamespaces = $this->getNamespaces(); $expr = \preg_replace_callback('{([^:]+|)}', function ($matches) { return \preg_quote($matches[1]) . '[^:]*'; }, $namespace); $namespaces = \preg_grep('{^' . $expr . '}', $allNamespaces); if (empty($namespaces)) { $message = \sprintf('There are no commands defined in the "%s" namespace.', $namespace); if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { if (1 == \count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { $message .= "\n\nDid you mean one of these?\n "; } $message .= \implode("\n ", $alternatives); } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\NamespaceNotFoundException($message, $alternatives); } $exact = \in_array($namespace, $namespaces, \true); if (\count($namespaces) > 1 && !$exact) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\NamespaceNotFoundException(\sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(\array_values($namespaces))), \array_values($namespaces)); } return $exact ? $namespace : \reset($namespaces); } /** * Finds a command by name or alias. * * Contrary to get, this command tries to find the best * match if you give it an abbreviation of a name or alias. * * @return Command A Command instance * * @throws CommandNotFoundException When command name is incorrect or ambiguous */ public function find(string $name) { $this->init(); $aliases = []; foreach ($this->commands as $command) { foreach ($command->getAliases() as $alias) { if (!$this->has($alias)) { $this->commands[$alias] = $command; } } } if ($this->has($name)) { return $this->get($name); } $allCommands = $this->commandLoader ? \array_merge($this->commandLoader->getNames(), \array_keys($this->commands)) : \array_keys($this->commands); $expr = \preg_replace_callback('{([^:]+|)}', function ($matches) { return \preg_quote($matches[1]) . '[^:]*'; }, $name); $commands = \preg_grep('{^' . $expr . '}', $allCommands); if (empty($commands)) { $commands = \preg_grep('{^' . $expr . '}i', $allCommands); } // if no commands matched or we just matched namespaces if (empty($commands) || \count(\preg_grep('{^' . $expr . '$}i', $commands)) < 1) { if (\false !== ($pos = \strrpos($name, ':'))) { // check if a namespace exists and contains commands $this->findNamespace(\substr($name, 0, $pos)); } $message = \sprintf('Command "%s" is not defined.', $name); if ($alternatives = $this->findAlternatives($name, $allCommands)) { // remove hidden commands $alternatives = \array_filter($alternatives, function ($name) { return !$this->get($name)->isHidden(); }); if (1 == \count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { $message .= "\n\nDid you mean one of these?\n "; } $message .= \implode("\n ", $alternatives); } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException($message, \array_values($alternatives)); } // filter out aliases for commands which are already on the list if (\count($commands) > 1) { $commandList = $this->commandLoader ? \array_merge(\array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; $commands = \array_unique(\array_filter($commands, function ($nameOrAlias) use(&$commandList, $commands, &$aliases) { if (!$commandList[$nameOrAlias] instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command) { $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias); } $commandName = $commandList[$nameOrAlias]->getName(); $aliases[$nameOrAlias] = $commandName; return $commandName === $nameOrAlias || !\in_array($commandName, $commands); })); } if (\count($commands) > 1) { $usableWidth = $this->terminal->getWidth() - 10; $abbrevs = \array_values($commands); $maxLen = 0; foreach ($abbrevs as $abbrev) { $maxLen = \max(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($abbrev), $maxLen); } $abbrevs = \array_map(function ($cmd) use($commandList, $usableWidth, $maxLen, &$commands) { if ($commandList[$cmd]->isHidden()) { unset($commands[\array_search($cmd, $commands)]); return \false; } $abbrev = \str_pad($cmd, $maxLen, ' ') . ' ' . $commandList[$cmd]->getDescription(); return \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($abbrev) > $usableWidth ? \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::substr($abbrev, 0, $usableWidth - 3) . '...' : $abbrev; }, \array_values($commands)); if (\count($commands) > 1) { $suggestions = $this->getAbbreviationSuggestions(\array_filter($abbrevs)); throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException(\sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), \array_values($commands)); } } $command = $this->get(\reset($commands)); if ($command->isHidden()) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name)); } return $command; } /** * Gets the commands (registered in the given namespace if provided). * * The array keys are the full names and the values the command instances. * * @return Command[] An array of Command instances */ public function all(string $namespace = null) { $this->init(); if (null === $namespace) { if (!$this->commandLoader) { return $this->commands; } $commands = $this->commands; foreach ($this->commandLoader->getNames() as $name) { if (!isset($commands[$name]) && $this->has($name)) { $commands[$name] = $this->get($name); } } return $commands; } $commands = []; foreach ($this->commands as $name => $command) { if ($namespace === $this->extractNamespace($name, \substr_count($namespace, ':') + 1)) { $commands[$name] = $command; } } if ($this->commandLoader) { foreach ($this->commandLoader->getNames() as $name) { if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, \substr_count($namespace, ':') + 1) && $this->has($name)) { $commands[$name] = $this->get($name); } } } return $commands; } /** * Returns an array of possible abbreviations given a set of names. * * @return string[][] An array of abbreviations */ public static function getAbbreviations(array $names) { $abbrevs = []; foreach ($names as $name) { for ($len = \strlen($name); $len > 0; --$len) { $abbrev = \substr($name, 0, $len); $abbrevs[$abbrev][] = $name; } } return $abbrevs; } public function renderThrowable(\Throwable $e, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) : void { $output->writeln('', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); $this->doRenderThrowable($e, $output); if (null !== $this->runningCommand) { $output->writeln(\sprintf('%s', \sprintf($this->runningCommand->getSynopsis(), $this->getName())), \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); $output->writeln('', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); } } protected function doRenderThrowable(\Throwable $e, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) : void { do { $message = \trim($e->getMessage()); if ('' === $message || \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $class = \get_debug_type($e); $title = \sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' (' . $code . ')' : ''); $len = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($title); } else { $len = 0; } if (\false !== \strpos($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); } $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX; $lines = []; foreach ('' !== $message ? \preg_split('/\\r?\\n/', $message) : [] as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { // pre-format lines to get the right string length $lineLength = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($line) + 4; $lines[] = [$line, $lineLength]; $len = \max($lineLength, $len); } } $messages = []; if (!$e instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface || \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $messages[] = \sprintf('%s', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape(\sprintf('In %s line %s:', \basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); } $messages[] = $emptyLine = \sprintf('%s', \str_repeat(' ', $len)); if ('' === $message || \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $messages[] = \sprintf('%s%s', $title, \str_repeat(' ', \max(0, $len - \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($title)))); } foreach ($lines as $line) { $messages[] = \sprintf(' %s %s', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape($line[0]), \str_repeat(' ', $len - $line[1])); } $messages[] = $emptyLine; $messages[] = ''; $output->writeln($messages, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); if (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $output->writeln('Exception trace:', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); // exception related properties $trace = $e->getTrace(); \array_unshift($trace, ['function' => '', 'file' => $e->getFile() ?: 'n/a', 'line' => $e->getLine() ?: 'n/a', 'args' => []]); for ($i = 0, $count = \count($trace); $i < $count; ++$i) { $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; $function = isset($trace[$i]['function']) ? $trace[$i]['function'] : ''; $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; $output->writeln(\sprintf(' %s%s at %s:%s', $class, $function ? $type . $function . '()' : '', $file, $line), \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); } $output->writeln('', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); } } while ($e = $e->getPrevious()); } /** * Configures the input and output instances based on the user arguments and options. */ protected function configureIO(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { if (\true === $input->hasParameterOption(['--ansi'], \true)) { $output->setDecorated(\true); } elseif (\true === $input->hasParameterOption(['--no-ansi'], \true)) { $output->setDecorated(\false); } if (\true === $input->hasParameterOption(['--no-interaction', '-n'], \true)) { $input->setInteractive(\false); } switch ($shellVerbosity = (int) \getenv('SHELL_VERBOSITY')) { case -1: $output->setVerbosity(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); break; case 1: $output->setVerbosity(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE); break; case 2: $output->setVerbosity(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE); break; case 3: $output->setVerbosity(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG); break; default: $shellVerbosity = 0; break; } if (\true === $input->hasParameterOption(['--quiet', '-q'], \true)) { $output->setVerbosity(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET); $shellVerbosity = -1; } else { if ($input->hasParameterOption('-vvv', \true) || $input->hasParameterOption('--verbose=3', \true) || 3 === $input->getParameterOption('--verbose', \false, \true)) { $output->setVerbosity(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG); $shellVerbosity = 3; } elseif ($input->hasParameterOption('-vv', \true) || $input->hasParameterOption('--verbose=2', \true) || 2 === $input->getParameterOption('--verbose', \false, \true)) { $output->setVerbosity(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE); $shellVerbosity = 2; } elseif ($input->hasParameterOption('-v', \true) || $input->hasParameterOption('--verbose=1', \true) || $input->hasParameterOption('--verbose', \true) || $input->getParameterOption('--verbose', \false, \true)) { $output->setVerbosity(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE); $shellVerbosity = 1; } } if (-1 === $shellVerbosity) { $input->setInteractive(\false); } if (\function_exists('putenv')) { @\putenv('SHELL_VERBOSITY=' . $shellVerbosity); } $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; } /** * Runs the current command. * * If an event dispatcher has been attached to the application, * events are also dispatched during the life-cycle of the command. * * @return int 0 if everything went fine, or an error code */ protected function doRunCommand(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { foreach ($command->getHelperSet() as $helper) { if ($helper instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputAwareInterface) { $helper->setInput($input); } } if (null === $this->dispatcher) { return $command->run($input, $output); } // bind before the console.command event, so the listeners have access to input options/arguments try { $command->mergeApplicationDefinition(); $input->bind($command->getDefinition()); } catch (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface $e) { // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition } $event = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleCommandEvent($command, $input, $output); $e = null; try { $this->dispatcher->dispatch($event, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\ConsoleEvents::COMMAND); if ($event->commandShouldRun()) { $exitCode = $command->run($input, $output); } else { $exitCode = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleCommandEvent::RETURN_CODE_DISABLED; } } catch (\Throwable $e) { $event = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleErrorEvent($input, $output, $e, $command); $this->dispatcher->dispatch($event, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\ConsoleEvents::ERROR); $e = $event->getError(); if (0 === ($exitCode = $event->getExitCode())) { $e = null; } } $event = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleTerminateEvent($command, $input, $output, $exitCode); $this->dispatcher->dispatch($event, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\ConsoleEvents::TERMINATE); if (null !== $e) { throw $e; } return $event->getExitCode(); } /** * Gets the name of the command based on input. * * @return string|null */ protected function getCommandName(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input) { return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument(); } /** * Gets the default input definition. * * @return InputDefinition An InputDefinition instance */ protected function getDefaultInputDefinition() { return new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition([new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument('command', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument::REQUIRED, 'The command to execute'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('--help', '-h', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Display this help message'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('--quiet', '-q', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Do not output any message'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('--verbose', '-v|vv|vvv', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('--version', '-V', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Display this application version'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('--ansi', '', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Force ANSI output'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('--no-ansi', '', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Disable ANSI output'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('--no-interaction', '-n', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'Do not ask any interactive question')]); } /** * Gets the default commands that should always be available. * * @return Command[] An array of default Command instances */ protected function getDefaultCommands() { return [new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\HelpCommand(), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\ListCommand()]; } /** * Gets the default helper set with the helpers that should always be available. * * @return HelperSet A HelperSet instance */ protected function getDefaultHelperSet() { return new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\HelperSet([new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\FormatterHelper(), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\DebugFormatterHelper(), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\ProcessHelper(), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\QuestionHelper()]); } /** * Returns abbreviated suggestions in string format. */ private function getAbbreviationSuggestions(array $abbrevs) : string { return ' ' . \implode("\n ", $abbrevs); } /** * Returns the namespace part of the command name. * * This method is not part of public API and should not be used directly. * * @return string The namespace of the command */ public function extractNamespace(string $name, int $limit = null) { $parts = \explode(':', $name, -1); return \implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit)); } /** * Finds alternative of $name among $collection, * if nothing is found in $collection, try in $abbrevs. * * @return string[] A sorted array of similar string */ private function findAlternatives(string $name, iterable $collection) : array { $threshold = 1000.0; $alternatives = []; $collectionParts = []; foreach ($collection as $item) { $collectionParts[$item] = \explode(':', $item); } foreach (\explode(':', $name) as $i => $subname) { foreach ($collectionParts as $collectionName => $parts) { $exists = isset($alternatives[$collectionName]); if (!isset($parts[$i]) && $exists) { $alternatives[$collectionName] += $threshold; continue; } elseif (!isset($parts[$i])) { continue; } $lev = \levenshtein($subname, $parts[$i]); if ($lev <= \strlen($subname) / 3 || '' !== $subname && \false !== \strpos($parts[$i], $subname)) { $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; } elseif ($exists) { $alternatives[$collectionName] += $threshold; } } } foreach ($collection as $item) { $lev = \levenshtein($name, $item); if ($lev <= \strlen($name) / 3 || \false !== \strpos($item, $name)) { $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; } } $alternatives = \array_filter($alternatives, function ($lev) use($threshold) { return $lev < 2 * $threshold; }); \ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE); return \array_keys($alternatives); } /** * Sets the default Command name. * * @return self */ public function setDefaultCommand(string $commandName, bool $isSingleCommand = \false) { $this->defaultCommand = $commandName; if ($isSingleCommand) { // Ensure the command exist $this->find($commandName); $this->singleCommand = \true; } return $this; } /** * @internal */ public function isSingleCommand() : bool { return $this->singleCommand; } private function splitStringByWidth(string $string, int $width) : array { // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly. // additionally, array_slice() is not enough as some character has doubled width. // we need a function to split string not by character count but by string width if (\false === ($encoding = \mb_detect_encoding($string, null, \true))) { return \str_split($string, $width); } $utf8String = \mb_convert_encoding($string, 'utf8', $encoding); $lines = []; $line = ''; $offset = 0; while (\preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) { $offset += \strlen($m[0]); foreach (\preg_split('//u', $m[0]) as $char) { // test if $char could be appended to current line if (\mb_strwidth($line . $char, 'utf8') <= $width) { $line .= $char; continue; } // if not, push current line to array and make new line $lines[] = \str_pad($line, $width); $line = $char; } } $lines[] = \count($lines) ? \str_pad($line, $width) : $line; \mb_convert_variables($encoding, 'utf8', $lines); return $lines; } /** * Returns all namespaces of the command name. * * @return string[] The namespaces of the command */ private function extractAllNamespaces(string $name) : array { // -1 as third argument is needed to skip the command short name when exploding $parts = \explode(':', $name, -1); $namespaces = []; foreach ($parts as $part) { if (\count($namespaces)) { $namespaces[] = \end($namespaces) . ':' . $part; } else { $namespaces[] = $part; } } return $namespaces; } private function init() { if ($this->initialized) { return; } $this->initialized = \true; foreach ($this->getDefaultCommands() as $command) { $this->add($command); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Logger; use _HumbugBoxd02f763d3c56\Psr\Log\AbstractLogger; use _HumbugBoxd02f763d3c56\Psr\Log\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Psr\Log\LogLevel; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * PSR-3 compliant console logger. * * @author Kévin Dunglas * * @see https://www.php-fig.org/psr/psr-3/ */ class ConsoleLogger extends \_HumbugBoxd02f763d3c56\Psr\Log\AbstractLogger { const INFO = 'info'; const ERROR = 'error'; private $output; private $verbosityLevelMap = [\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::EMERGENCY => \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::ALERT => \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::CRITICAL => \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::ERROR => \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::WARNING => \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_NORMAL, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::NOTICE => \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::INFO => \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::DEBUG => \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG]; private $formatLevelMap = [\_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::EMERGENCY => self::ERROR, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::ALERT => self::ERROR, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::CRITICAL => self::ERROR, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::ERROR => self::ERROR, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::WARNING => self::INFO, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::NOTICE => self::INFO, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::INFO => self::INFO, \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::DEBUG => self::INFO]; private $errored = \false; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = []) { $this->output = $output; $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap; $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap; } /** * {@inheritdoc} * * @return void */ public function log($level, $message, array $context = []) { if (!isset($this->verbosityLevelMap[$level])) { throw new \_HumbugBoxd02f763d3c56\Psr\Log\InvalidArgumentException(\sprintf('The log level "%s" does not exist.', $level)); } $output = $this->output; // Write to the error output if necessary and available if (self::ERROR === $this->formatLevelMap[$level]) { if ($this->output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface) { $output = $output->getErrorOutput(); } $this->errored = \true; } // the if condition check isn't necessary -- it's the same one that $output will do internally anyway. // We only do it for efficiency here as the message formatting is relatively expensive. if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) { $output->writeln(\sprintf('<%1$s>[%2$s] %3$s', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]); } } /** * Returns true when any messages have been logged at error levels. * * @return bool */ public function hasErrored() { return $this->errored; } /** * Interpolates context values into the message placeholders. * * @author PHP Framework Interoperability Group */ private function interpolate(string $message, array $context) : string { if (\false === \strpos($message, '{')) { return $message; } $replacements = []; foreach ($context as $key => $val) { if (null === $val || \is_scalar($val) || \is_object($val) && \method_exists($val, '__toString')) { $replacements["{{$key}}"] = $val; } elseif ($val instanceof \DateTimeInterface) { $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); } elseif (\is_object($val)) { $replacements["{{$key}}"] = '[object ' . \get_class($val) . ']'; } else { $replacements["{{$key}}"] = '[' . \gettype($val) . ']'; } } return \strtr($message, $replacements); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR. * * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR. * * $output = new ConsoleOutput(); * * This is equivalent to: * * $output = new StreamOutput(fopen('php://stdout', 'w')); * $stdErr = new StreamOutput(fopen('php://stderr', 'w')); * * @author Fabien Potencier */ class ConsoleOutput extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\StreamOutput implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface { private $stderr; private $consoleSectionOutputs = []; /** * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) */ public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter = null) { parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); $actualDecorated = $this->isDecorated(); $this->stderr = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); if (null === $decorated) { $this->setDecorated($actualDecorated && $this->stderr->isDecorated()); } } /** * Creates a new output section. */ public function section() : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput { return new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter()); } /** * {@inheritdoc} */ public function setDecorated(bool $decorated) { parent::setDecorated($decorated); $this->stderr->setDecorated($decorated); } /** * {@inheritdoc} */ public function setFormatter(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter) { parent::setFormatter($formatter); $this->stderr->setFormatter($formatter); } /** * {@inheritdoc} */ public function setVerbosity(int $level) { parent::setVerbosity($level); $this->stderr->setVerbosity($level); } /** * {@inheritdoc} */ public function getErrorOutput() { return $this->stderr; } /** * {@inheritdoc} */ public function setErrorOutput(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $error) { $this->stderr = $error; } /** * Returns true if current environment supports writing console output to * STDOUT. * * @return bool */ protected function hasStdoutSupport() { return \false === $this->isRunningOS400(); } /** * Returns true if current environment supports writing console output to * STDERR. * * @return bool */ protected function hasStderrSupport() { return \false === $this->isRunningOS400(); } /** * Checks if current executing environment is IBM iSeries (OS400), which * doesn't properly convert character-encodings between ASCII to EBCDIC. */ private function isRunningOS400() : bool { $checks = [\function_exists('php_uname') ? \php_uname('s') : '', \getenv('OSTYPE'), \PHP_OS]; return \false !== \stripos(\implode(';', $checks), 'OS400'); } /** * @return resource */ private function openOutputStream() { if (!$this->hasStdoutSupport()) { return \fopen('php://output', 'w'); } return @\fopen('php://stdout', 'w') ?: \fopen('php://output', 'w'); } /** * @return resource */ private function openErrorStream() { return \fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * OutputInterface is the interface implemented by all Output classes. * * @author Fabien Potencier */ interface OutputInterface { const VERBOSITY_QUIET = 16; const VERBOSITY_NORMAL = 32; const VERBOSITY_VERBOSE = 64; const VERBOSITY_VERY_VERBOSE = 128; const VERBOSITY_DEBUG = 256; const OUTPUT_NORMAL = 1; const OUTPUT_RAW = 2; const OUTPUT_PLAIN = 4; /** * Writes a message to the output. * * @param string|iterable $messages The message as an iterable of strings or a single string * @param bool $newline Whether to add a newline * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL */ public function write($messages, bool $newline = \false, int $options = 0); /** * Writes a message to the output and adds a newline at the end. * * @param string|iterable $messages The message as an iterable of strings or a single string * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL */ public function writeln($messages, int $options = 0); /** * Sets the verbosity of the output. */ public function setVerbosity(int $level); /** * Gets the current verbosity of the output. * * @return int The current level of verbosity (one of the VERBOSITY constants) */ public function getVerbosity(); /** * Returns whether verbosity is quiet (-q). * * @return bool true if verbosity is set to VERBOSITY_QUIET, false otherwise */ public function isQuiet(); /** * Returns whether verbosity is verbose (-v). * * @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise */ public function isVerbose(); /** * Returns whether verbosity is very verbose (-vv). * * @return bool true if verbosity is set to VERBOSITY_VERY_VERBOSE, false otherwise */ public function isVeryVerbose(); /** * Returns whether verbosity is debug (-vvv). * * @return bool true if verbosity is set to VERBOSITY_DEBUG, false otherwise */ public function isDebug(); /** * Sets the decorated flag. */ public function setDecorated(bool $decorated); /** * Gets the decorated flag. * * @return bool true if the output will decorate messages, false otherwise */ public function isDecorated(); public function setFormatter(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter); /** * Returns current output formatter instance. * * @return OutputFormatterInterface */ public function getFormatter(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * Base class for output classes. * * There are five levels of verbosity: * * * normal: no option passed (normal output) * * verbose: -v (more output) * * very verbose: -vv (highly extended output) * * debug: -vvv (all debug output) * * quiet: -q (no output) * * @author Fabien Potencier */ abstract class Output implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface { private $verbosity; private $formatter; /** * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool $decorated Whether to decorate messages * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) */ public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = \false, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter = null) { $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; $this->formatter = $formatter ?: new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter(); $this->formatter->setDecorated($decorated); } /** * {@inheritdoc} */ public function setFormatter(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter) { $this->formatter = $formatter; } /** * {@inheritdoc} */ public function getFormatter() { return $this->formatter; } /** * {@inheritdoc} */ public function setDecorated(bool $decorated) { $this->formatter->setDecorated($decorated); } /** * {@inheritdoc} */ public function isDecorated() { return $this->formatter->isDecorated(); } /** * {@inheritdoc} */ public function setVerbosity(int $level) { $this->verbosity = $level; } /** * {@inheritdoc} */ public function getVerbosity() { return $this->verbosity; } /** * {@inheritdoc} */ public function isQuiet() { return self::VERBOSITY_QUIET === $this->verbosity; } /** * {@inheritdoc} */ public function isVerbose() { return self::VERBOSITY_VERBOSE <= $this->verbosity; } /** * {@inheritdoc} */ public function isVeryVerbose() { return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; } /** * {@inheritdoc} */ public function isDebug() { return self::VERBOSITY_DEBUG <= $this->verbosity; } /** * {@inheritdoc} */ public function writeln($messages, int $options = self::OUTPUT_NORMAL) { $this->write($messages, \true, $options); } /** * {@inheritdoc} */ public function write($messages, bool $newline = \false, int $options = self::OUTPUT_NORMAL) { if (!\is_iterable($messages)) { $messages = [$messages]; } $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN; $type = $types & $options ?: self::OUTPUT_NORMAL; $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG; $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL; if ($verbosity > $this->getVerbosity()) { return; } foreach ($messages as $message) { switch ($type) { case \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::OUTPUT_NORMAL: $message = $this->formatter->format($message); break; case \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::OUTPUT_RAW: break; case \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::OUTPUT_PLAIN: $message = \strip_tags($this->formatter->format($message)); break; } $this->doWrite($message, $newline); } } /** * Writes a message to the output. */ protected abstract function doWrite(string $message, bool $newline); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal; /** * @author Pierre du Plessis * @author Gabriel Ostrolucký */ class ConsoleSectionOutput extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\StreamOutput { private $content = []; private $lines = 0; private $sections; private $terminal; /** * @param resource $stream * @param ConsoleSectionOutput[] $sections */ public function __construct($stream, array &$sections, int $verbosity, bool $decorated, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter) { parent::__construct($stream, $verbosity, $decorated, $formatter); \array_unshift($sections, $this); $this->sections =& $sections; $this->terminal = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal(); } /** * 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 */ public function clear(int $lines = null) { if (empty($this->content) || !$this->isDecorated()) { return; } if ($lines) { \array_splice($this->content, -($lines * 2)); // Multiply lines by 2 to cater for each new line added between content } else { $lines = $this->lines; $this->content = []; } $this->lines -= $lines; parent::doWrite($this->popStreamContentUntilCurrentSection($lines), \false); } /** * Overwrites the previous output with a new message. * * @param array|string $message */ public function overwrite($message) { $this->clear(); $this->writeln($message); } public function getContent() : string { return \implode('', $this->content); } /** * @internal */ public function addContent(string $input) { foreach (\explode(\PHP_EOL, $input) as $lineContent) { $this->lines += \ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1; $this->content[] = $lineContent; $this->content[] = \PHP_EOL; } } /** * {@inheritdoc} */ protected function doWrite($message, $newline) { if (!$this->isDecorated()) { parent::doWrite($message, $newline); return; } $erasedContent = $this->popStreamContentUntilCurrentSection(); $this->addContent($message); parent::doWrite($message, \true); parent::doWrite($erasedContent, \false); } /** * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits * current section. Then it erases content it crawled through. Optionally, it erases part of current section too. */ private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0) : string { $numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection; $erasedContent = []; foreach ($this->sections as $section) { if ($section === $this) { break; } $numberOfLinesToClear += $section->lines; $erasedContent[] = $section->getContent(); } if ($numberOfLinesToClear > 0) { // move cursor up n lines parent::doWrite(\sprintf("\33[%dA", $numberOfLinesToClear), \false); // erase to end of screen parent::doWrite("\33[0J", \false); } return \implode('', \array_reverse($erasedContent)); } private function getDisplayLength(string $text) : string { return \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->getFormatter(), \str_replace("\t", ' ', $text)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * StreamOutput writes the output to a given stream. * * Usage: * * $output = new StreamOutput(fopen('php://stdout', 'w')); * * As `StreamOutput` can use any stream, you can also use a file: * * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); * * @author Fabien Potencier */ class StreamOutput extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\Output { private $stream; /** * @param resource $stream A stream resource * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @throws InvalidArgumentException When first argument is not a real stream */ public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter = null) { if (!\is_resource($stream) || 'stream' !== \get_resource_type($stream)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); } $this->stream = $stream; if (null === $decorated) { $decorated = $this->hasColorSupport(); } parent::__construct($verbosity, $decorated, $formatter); } /** * Gets the stream attached to this StreamOutput instance. * * @return resource A stream resource */ public function getStream() { return $this->stream; } /** * {@inheritdoc} */ protected function doWrite(string $message, bool $newline) { if ($newline) { $message .= \PHP_EOL; } @\fwrite($this->stream, $message); \fflush($this->stream); } /** * Returns true if the stream supports colorization. * * Colorization is disabled if not supported by the stream: * * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo * terminals via named pipes, so we can only check the environment. * * Reference: Composer\XdebugHandler\Process::supportsColor * https://github.com/composer/xdebug-handler * * @return bool true if the stream supports colorization, false otherwise */ protected function hasColorSupport() { // Follow https://no-color.org/ if (isset($_SERVER['NO_COLOR']) || \false !== \getenv('NO_COLOR')) { return \false; } if ('Hyper' === \getenv('TERM_PROGRAM')) { return \true; } if (\DIRECTORY_SEPARATOR === '\\') { return \function_exists('sapi_windows_vt100_support') && @\sapi_windows_vt100_support($this->stream) || \false !== \getenv('ANSICON') || 'ON' === \getenv('ConEmuANSI') || 'xterm' === \getenv('TERM'); } return \stream_isatty($this->stream); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\NullOutputFormatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * NullOutput suppresses all output. * * $output = new NullOutput(); * * @author Fabien Potencier * @author Tobias Schultze */ class NullOutput implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface { private $formatter; /** * {@inheritdoc} */ public function setFormatter(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter) { // do nothing } /** * {@inheritdoc} */ public function getFormatter() { if ($this->formatter) { return $this->formatter; } // to comply with the interface we must return a OutputFormatterInterface return $this->formatter = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\NullOutputFormatter(); } /** * {@inheritdoc} */ public function setDecorated(bool $decorated) { // do nothing } /** * {@inheritdoc} */ public function isDecorated() { return \false; } /** * {@inheritdoc} */ public function setVerbosity(int $level) { // do nothing } /** * {@inheritdoc} */ public function getVerbosity() { return self::VERBOSITY_QUIET; } /** * {@inheritdoc} */ public function isQuiet() { return \true; } /** * {@inheritdoc} */ public function isVerbose() { return \false; } /** * {@inheritdoc} */ public function isVeryVerbose() { return \false; } /** * {@inheritdoc} */ public function isDebug() { return \false; } /** * {@inheritdoc} */ public function writeln($messages, int $options = self::OUTPUT_NORMAL) { // do nothing } /** * {@inheritdoc} */ public function write($messages, bool $newline = \false, int $options = self::OUTPUT_NORMAL) { // do nothing } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output; /** * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. * This adds information about stderr and section output stream. * * @author Dariusz Górecki */ interface ConsoleOutputInterface extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface { /** * Gets the OutputInterface for errors. * * @return OutputInterface */ public function getErrorOutput(); public function setErrorOutput(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $error); public function section() : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output; /** * @author Jean-François Simon */ class BufferedOutput extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\Output { private $buffer = ''; /** * Empties buffer and returns its content. * * @return string */ public function fetch() { $content = $this->buffer; $this->buffer = ''; return $content; } /** * {@inheritdoc} */ protected function doWrite(string $message, bool $newline) { $this->buffer .= $message; if ($newline) { $this->buffer .= \PHP_EOL; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; /** * Helps outputting debug information when running an external program from a command. * * An external program can be a Process, an HTTP request, or anything else. * * @author Fabien Potencier */ class DebugFormatterHelper extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper { private $colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default']; private $started = []; private $count = -1; /** * Starts a debug formatting session. * * @return string */ public function start(string $id, string $message, string $prefix = 'RUN') { $this->started[$id] = ['border' => ++$this->count % \count($this->colors)]; return \sprintf("%s %s %s\n", $this->getBorder($id), $prefix, $message); } /** * Adds progress to a formatting session. * * @return string */ public function progress(string $id, string $buffer, bool $error = \false, string $prefix = 'OUT', string $errorPrefix = 'ERR') { $message = ''; if ($error) { if (isset($this->started[$id]['out'])) { $message .= "\n"; unset($this->started[$id]['out']); } if (!isset($this->started[$id]['err'])) { $message .= \sprintf('%s %s ', $this->getBorder($id), $errorPrefix); $this->started[$id]['err'] = \true; } $message .= \str_replace("\n", \sprintf("\n%s %s ", $this->getBorder($id), $errorPrefix), $buffer); } else { if (isset($this->started[$id]['err'])) { $message .= "\n"; unset($this->started[$id]['err']); } if (!isset($this->started[$id]['out'])) { $message .= \sprintf('%s %s ', $this->getBorder($id), $prefix); $this->started[$id]['out'] = \true; } $message .= \str_replace("\n", \sprintf("\n%s %s ", $this->getBorder($id), $prefix), $buffer); } return $message; } /** * Stops a formatting session. * * @return string */ public function stop(string $id, string $message, bool $successful, string $prefix = 'RES') { $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; if ($successful) { return \sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); } $message = \sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); unset($this->started[$id]['out'], $this->started[$id]['err']); return $message; } private function getBorder(string $id) : string { return \sprintf(' ', $this->colors[$this->started[$id]['border']]); } /** * {@inheritdoc} */ public function getName() { return 'debug_formatter'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ConfirmationQuestion; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Style\SymfonyStyle; /** * Symfony Style Guide compliant question helper. * * @author Kevin Bond */ class SymfonyQuestionHelper extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\QuestionHelper { /** * {@inheritdoc} */ protected function writePrompt(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question $question) { $text = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escapeTrailingBackslash($question->getQuestion()); $default = $question->getDefault(); switch (\true) { case null === $default: $text = \sprintf(' %s:', $text); break; case $question instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ConfirmationQuestion: $text = \sprintf(' %s (yes/no) [%s]:', $text, $default ? 'yes' : 'no'); break; case $question instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion && $question->isMultiselect(): $choices = $question->getChoices(); $default = \explode(',', $default); foreach ($default as $key => $value) { $default[$key] = $choices[\trim($value)]; } $text = \sprintf(' %s [%s]:', $text, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape(\implode(', ', $default))); break; case $question instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion: $choices = $question->getChoices(); $text = \sprintf(' %s [%s]:', $text, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default)); break; default: $text = \sprintf(' %s [%s]:', $text, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape($default)); } $output->writeln($text); $prompt = ' > '; if ($question instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion) { $output->writeln($this->formatChoiceQuestionChoices($question, 'comment')); $prompt = $question->getPrompt(); } $output->write($prompt); } /** * {@inheritdoc} */ protected function writeError(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \Exception $error) { if ($output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Style\SymfonyStyle) { $output->newLine(); $output->error($error->getMessage()); return; } parent::writeError($output, $error); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * Provides helpers to display a table. * * @author Fabien Potencier * @author Саша Стаменковић * @author Abdellatif Ait boudad * @author Max Grigorian * @author Dany Maillard */ class Table { private const SEPARATOR_TOP = 0; private const SEPARATOR_TOP_BOTTOM = 1; private const SEPARATOR_MID = 2; private const SEPARATOR_BOTTOM = 3; private const BORDER_OUTSIDE = 0; private const BORDER_INSIDE = 1; private $headerTitle; private $footerTitle; /** * Table headers. */ private $headers = []; /** * Table rows. */ private $rows = []; private $horizontal = \false; /** * Column widths cache. */ private $effectiveColumnWidths = []; /** * Number of columns cache. * * @var int */ private $numberOfColumns; /** * @var OutputInterface */ private $output; /** * @var TableStyle */ private $style; /** * @var array */ private $columnStyles = []; /** * User set column widths. * * @var array */ private $columnWidths = []; private $columnMaxWidths = []; private static $styles; private $rendered = \false; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { $this->output = $output; if (!self::$styles) { self::$styles = self::initStyles(); } $this->setStyle('default'); } /** * Sets a style definition. */ public static function setStyleDefinition(string $name, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableStyle $style) { if (!self::$styles) { self::$styles = self::initStyles(); } self::$styles[$name] = $style; } /** * Gets a style definition by name. * * @return TableStyle */ public static function getStyleDefinition(string $name) { if (!self::$styles) { self::$styles = self::initStyles(); } if (isset(self::$styles[$name])) { return self::$styles[$name]; } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name)); } /** * Sets table style. * * @param TableStyle|string $name The style name or a TableStyle instance * * @return $this */ public function setStyle($name) { $this->style = $this->resolveStyle($name); return $this; } /** * Gets the current table style. * * @return TableStyle */ public function getStyle() { return $this->style; } /** * Sets table column style. * * @param TableStyle|string $name The style name or a TableStyle instance * * @return $this */ public function setColumnStyle(int $columnIndex, $name) { $this->columnStyles[$columnIndex] = $this->resolveStyle($name); return $this; } /** * Gets the current style for a column. * * If style was not set, it returns the global table style. * * @return TableStyle */ public function getColumnStyle(int $columnIndex) { return $this->columnStyles[$columnIndex] ?? $this->getStyle(); } /** * Sets the minimum width of a column. * * @return $this */ public function setColumnWidth(int $columnIndex, int $width) { $this->columnWidths[$columnIndex] = $width; return $this; } /** * Sets the minimum width of all columns. * * @return $this */ public function setColumnWidths(array $widths) { $this->columnWidths = []; foreach ($widths as $index => $width) { $this->setColumnWidth($index, $width); } return $this; } /** * Sets the maximum width of a column. * * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while * formatted strings are preserved. * * @return $this */ public function setColumnMaxWidth(int $columnIndex, int $width) : self { if (!$this->output->getFormatter() instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface) { throw new \LogicException(\sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface::class, \get_debug_type($this->output->getFormatter()))); } $this->columnMaxWidths[$columnIndex] = $width; return $this; } public function setHeaders(array $headers) { $headers = \array_values($headers); if (!empty($headers) && !\is_array($headers[0])) { $headers = [$headers]; } $this->headers = $headers; return $this; } public function setRows(array $rows) { $this->rows = []; return $this->addRows($rows); } public function addRows(array $rows) { foreach ($rows as $row) { $this->addRow($row); } return $this; } public function addRow($row) { if ($row instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator) { $this->rows[] = $row; return $this; } if (!\is_array($row)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('A row must be an array or a TableSeparator instance.'); } $this->rows[] = \array_values($row); return $this; } /** * Adds a row to the table, and re-renders the table. */ public function appendRow($row) : self { if (!$this->output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException(\sprintf('Output should be an instance of "%s" when calling "%s".', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput::class, __METHOD__)); } if ($this->rendered) { $this->output->clear($this->calculateRowCount()); } $this->addRow($row); $this->render(); return $this; } public function setRow($column, array $row) { $this->rows[$column] = $row; return $this; } public function setHeaderTitle(?string $title) : self { $this->headerTitle = $title; return $this; } public function setFooterTitle(?string $title) : self { $this->footerTitle = $title; return $this; } public function setHorizontal(bool $horizontal = \true) : self { $this->horizontal = $horizontal; return $this; } /** * Renders table to output. * * Example: * * +---------------+-----------------------+------------------+ * | ISBN | Title | Author | * +---------------+-----------------------+------------------+ * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ */ public function render() { $divider = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator(); if ($this->horizontal) { $rows = []; foreach ($this->headers[0] ?? [] as $i => $header) { $rows[$i] = [$header]; foreach ($this->rows as $row) { if ($row instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator) { continue; } if (isset($row[$i])) { $rows[$i][] = $row[$i]; } elseif ($rows[$i][0] instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell && $rows[$i][0]->getColspan() >= 2) { // Noop, there is a "title" } else { $rows[$i][] = null; } } } } else { $rows = \array_merge($this->headers, [$divider], $this->rows); } $this->calculateNumberOfColumns($rows); $rows = $this->buildTableRows($rows); $this->calculateColumnsWidth($rows); $isHeader = !$this->horizontal; $isFirstRow = $this->horizontal; foreach ($rows as $row) { if ($divider === $row) { $isHeader = \false; $isFirstRow = \true; continue; } if ($row instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator) { $this->renderRowSeparator(); continue; } if (!$row) { continue; } if ($isHeader || $isFirstRow) { if ($isFirstRow) { $this->renderRowSeparator(self::SEPARATOR_TOP_BOTTOM); $isFirstRow = \false; } else { $this->renderRowSeparator(self::SEPARATOR_TOP, $this->headerTitle, $this->style->getHeaderTitleFormat()); } } if ($this->horizontal) { $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat()); } else { $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); } } $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat()); $this->cleanup(); $this->rendered = \true; } /** * Renders horizontal header separator. * * Example: * * +-----+-----------+-------+ */ private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null) { if (0 === ($count = $this->numberOfColumns)) { return; } $borders = $this->style->getBorderChars(); if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) { return; } $crossings = $this->style->getCrossingChars(); if (self::SEPARATOR_MID === $type) { list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; } elseif (self::SEPARATOR_TOP === $type) { list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; } elseif (self::SEPARATOR_TOP_BOTTOM === $type) { list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; } else { list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; } $markup = $leftChar; for ($column = 0; $column < $count; ++$column) { $markup .= \str_repeat($horizontal, $this->effectiveColumnWidths[$column]); $markup .= $column === $count - 1 ? $rightChar : $midChar; } if (null !== $title) { $titleLength = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($formatter = $this->output->getFormatter(), $formattedTitle = \sprintf($titleFormat, $title)); $markupLength = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($markup); if ($titleLength > ($limit = $markupLength - 4)) { $titleLength = $limit; $formatLength = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($formatter, \sprintf($titleFormat, '')); $formattedTitle = \sprintf($titleFormat, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::substr($title, 0, $limit - $formatLength - 3) . '...'); } $titleStart = ($markupLength - $titleLength) / 2; if (\false === \mb_detect_encoding($markup, null, \true)) { $markup = \substr_replace($markup, $formattedTitle, $titleStart, $titleLength); } else { $markup = \mb_substr($markup, 0, $titleStart) . $formattedTitle . \mb_substr($markup, $titleStart + $titleLength); } } $this->output->writeln(\sprintf($this->style->getBorderFormat(), $markup)); } /** * Renders vertical column separator. */ private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE) : string { $borders = $this->style->getBorderChars(); return \sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]); } /** * Renders table row. * * Example: * * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | */ private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) { $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); $columns = $this->getRowColumns($row); $last = \count($columns) - 1; foreach ($columns as $i => $column) { if ($firstCellFormat && 0 === $i) { $rowContent .= $this->renderCell($row, $column, $firstCellFormat); } else { $rowContent .= $this->renderCell($row, $column, $cellFormat); } $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE); } $this->output->writeln($rowContent); } /** * Renders table cell with padding. */ private function renderCell(array $row, int $column, string $cellFormat) : string { $cell = isset($row[$column]) ? $row[$column] : ''; $width = $this->effectiveColumnWidths[$column]; if ($cell instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell && $cell->getColspan() > 1) { // add the width of the following columns(numbers of colspan). foreach (\range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) { $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn]; } } // str_pad won't work properly with multi-byte strings, we need to fix the padding if (\false !== ($encoding = \mb_detect_encoding($cell, null, \true))) { $width += \strlen($cell) - \mb_strwidth($cell, $encoding); } $style = $this->getColumnStyle($column); if ($cell instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator) { return \sprintf($style->getBorderFormat(), \str_repeat($style->getBorderChars()[2], $width)); } $width += \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($cell) - \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); $content = \sprintf($style->getCellRowContentFormat(), $cell); return \sprintf($cellFormat, \str_pad($content, $width, $style->getPaddingChar(), $style->getPadType())); } /** * Calculate number of columns for this table. */ private function calculateNumberOfColumns(array $rows) { $columns = [0]; foreach ($rows as $row) { if ($row instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator) { continue; } $columns[] = $this->getNumberOfColumns($row); } $this->numberOfColumns = \max($columns); } private function buildTableRows(array $rows) : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableRows { /** @var WrappableOutputFormatterInterface $formatter */ $formatter = $this->output->getFormatter(); $unmergedRows = []; for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) { $rows = $this->fillNextRows($rows, $rowKey); // Remove any new line breaks and replace it with a new line foreach ($rows[$rowKey] as $column => $cell) { $colspan = $cell instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell ? $cell->getColspan() : 1; if (isset($this->columnMaxWidths[$column]) && \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($formatter, $cell) > $this->columnMaxWidths[$column]) { $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan); } if (!\strstr($cell, "\n")) { continue; } $escaped = \implode("\n", \array_map([\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::class, 'escapeTrailingBackslash'], \explode("\n", $cell))); $cell = $cell instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell ? new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped; $lines = \explode("\n", \str_replace("\n", "\n", $cell)); foreach ($lines as $lineKey => $line) { if ($colspan > 1) { $line = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell($line, ['colspan' => $colspan]); } if (0 === $lineKey) { $rows[$rowKey][$column] = $line; } else { if (!\array_key_exists($rowKey, $unmergedRows) || !\array_key_exists($lineKey, $unmergedRows[$rowKey])) { $unmergedRows[$rowKey][$lineKey] = $this->copyRow($rows, $rowKey); } $unmergedRows[$rowKey][$lineKey][$column] = $line; } } } } return new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableRows(function () use($rows, $unmergedRows) : \Traversable { foreach ($rows as $rowKey => $row) { (yield $this->fillCells($row)); if (isset($unmergedRows[$rowKey])) { foreach ($unmergedRows[$rowKey] as $unmergedRow) { (yield $this->fillCells($unmergedRow)); } } } }); } private function calculateRowCount() : int { $numberOfRows = \count(\iterator_to_array($this->buildTableRows(\array_merge($this->headers, [new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator()], $this->rows)))); if ($this->headers) { ++$numberOfRows; // Add row for header separator } if (\count($this->rows) > 0) { ++$numberOfRows; // Add row for footer separator } return $numberOfRows; } /** * fill rows that contains rowspan > 1. * * @throws InvalidArgumentException */ private function fillNextRows(array $rows, int $line) : array { $unmergedRows = []; foreach ($rows[$line] as $column => $cell) { if (null !== $cell && !$cell instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell && !\is_scalar($cell) && !(\is_object($cell) && \method_exists($cell, '__toString'))) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', \get_debug_type($cell))); } if ($cell instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell && $cell->getRowspan() > 1) { $nbLines = $cell->getRowspan() - 1; $lines = [$cell]; if (\strstr($cell, "\n")) { $lines = \explode("\n", \str_replace("\n", "\n", $cell)); $nbLines = \count($lines) > $nbLines ? \substr_count($cell, "\n") : $nbLines; $rows[$line][$column] = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell($lines[0], ['colspan' => $cell->getColspan()]); unset($lines[0]); } // create a two dimensional array (rowspan x colspan) $unmergedRows = \array_replace_recursive(\array_fill($line + 1, $nbLines, []), $unmergedRows); foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : ''; $unmergedRows[$unmergedRowKey][$column] = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell($value, ['colspan' => $cell->getColspan()]); if ($nbLines === $unmergedRowKey - $line) { break; } } } } foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { // we need to know if $unmergedRow will be merged or inserted into $rows if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && $this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns) { foreach ($unmergedRow as $cellKey => $cell) { // insert cell into row at cellKey position \array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]); } } else { $row = $this->copyRow($rows, $unmergedRowKey - 1); foreach ($unmergedRow as $column => $cell) { if (!empty($cell)) { $row[$column] = $unmergedRow[$column]; } } \array_splice($rows, $unmergedRowKey, 0, [$row]); } } return $rows; } /** * fill cells for a row that contains colspan > 1. */ private function fillCells($row) { $newRow = []; foreach ($row as $column => $cell) { $newRow[] = $cell; if ($cell instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell && $cell->getColspan() > 1) { foreach (\range($column + 1, $column + $cell->getColspan() - 1) as $position) { // insert empty value at column position $newRow[] = ''; } } } return $newRow ?: $row; } private function copyRow(array $rows, int $line) : array { $row = $rows[$line]; foreach ($row as $cellKey => $cellValue) { $row[$cellKey] = ''; if ($cellValue instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell) { $row[$cellKey] = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell('', ['colspan' => $cellValue->getColspan()]); } } return $row; } /** * Gets number of columns by row. */ private function getNumberOfColumns(array $row) : int { $columns = \count($row); foreach ($row as $column) { $columns += $column instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell ? $column->getColspan() - 1 : 0; } return $columns; } /** * Gets list of columns for the given row. */ private function getRowColumns(array $row) : array { $columns = \range(0, $this->numberOfColumns - 1); foreach ($row as $cellKey => $cell) { if ($cell instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell && $cell->getColspan() > 1) { // exclude grouped columns. $columns = \array_diff($columns, \range($cellKey + 1, $cellKey + $cell->getColspan() - 1)); } } return $columns; } /** * Calculates columns widths. */ private function calculateColumnsWidth(iterable $rows) { for ($column = 0; $column < $this->numberOfColumns; ++$column) { $lengths = []; foreach ($rows as $row) { if ($row instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator) { continue; } foreach ($row as $i => $cell) { if ($cell instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell) { $textContent = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::removeDecoration($this->output->getFormatter(), $cell); $textLength = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($textContent); if ($textLength > 0) { $contentColumns = \str_split($textContent, \ceil($textLength / $cell->getColspan())); foreach ($contentColumns as $position => $content) { $row[$i + $position] = $content; } } } } $lengths[] = $this->getCellWidth($row, $column); } $this->effectiveColumnWidths[$column] = \max($lengths) + \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($this->style->getCellRowContentFormat()) - 2; } } private function getColumnSeparatorWidth() : int { return \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen(\sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3])); } private function getCellWidth(array $row, int $column) : int { $cellWidth = 0; if (isset($row[$column])) { $cell = $row[$column]; $cellWidth = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); } $columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0; $cellWidth = \max($cellWidth, $columnWidth); return isset($this->columnMaxWidths[$column]) ? \min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth; } /** * Called after rendering to cleanup cache data. */ private function cleanup() { $this->effectiveColumnWidths = []; $this->numberOfColumns = null; } private static function initStyles() : array { $borderless = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableStyle(); $borderless->setHorizontalBorderChars('=')->setVerticalBorderChars(' ')->setDefaultCrossingChar(' '); $compact = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableStyle(); $compact->setHorizontalBorderChars('')->setVerticalBorderChars(' ')->setDefaultCrossingChar('')->setCellRowContentFormat('%s'); $styleGuide = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableStyle(); $styleGuide->setHorizontalBorderChars('-')->setVerticalBorderChars(' ')->setDefaultCrossingChar(' ')->setCellHeaderFormat('%s'); $box = (new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableStyle())->setHorizontalBorderChars('─')->setVerticalBorderChars('│')->setCrossingChars('┼', '┌', '┬', '┐', '┤', '┘', '┴', '└', '├'); $boxDouble = (new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableStyle())->setHorizontalBorderChars('═', '─')->setVerticalBorderChars('║', '│')->setCrossingChars('┼', '╔', '╤', '╗', '╢', '╝', '╧', '╚', '╟', '╠', '╪', '╣'); return ['default' => new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableStyle(), 'borderless' => $borderless, 'compact' => $compact, 'symfony-style-guide' => $styleGuide, 'box' => $box, 'box-double' => $boxDouble]; } private function resolveStyle($name) : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableStyle { if ($name instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableStyle) { return $name; } if (isset(self::$styles[$name])) { return self::$styles[$name]; } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; /** * Marks a row as being a separator. * * @author Fabien Potencier */ class TableSeparator extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell { public function __construct(array $options = []) { parent::__construct('', $options); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\DescriptorInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\JsonDescriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\MarkdownDescriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\TextDescriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\XmlDescriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * This class adds helper method to describe objects in various formats. * * @author Jean-François Simon */ class DescriptorHelper extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper { /** * @var DescriptorInterface[] */ private $descriptors = []; public function __construct() { $this->register('txt', new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\TextDescriptor())->register('xml', new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\XmlDescriptor())->register('json', new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\JsonDescriptor())->register('md', new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\MarkdownDescriptor()); } /** * Describes an object if supported. * * Available options are: * * format: string, the output format name * * raw_text: boolean, sets output type as raw * * @throws InvalidArgumentException when the given format is not supported */ public function describe(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, ?object $object, array $options = []) { $options = \array_merge(['raw_text' => \false, 'format' => 'txt'], $options); if (!isset($this->descriptors[$options['format']])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Unsupported format "%s".', $options['format'])); } $descriptor = $this->descriptors[$options['format']]; $descriptor->describe($output, $object, $options); } /** * Registers a descriptor. * * @return $this */ public function register(string $format, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\DescriptorInterface $descriptor) { $this->descriptors[$format] = $descriptor; return $this; } /** * {@inheritdoc} */ public function getName() { return 'descriptor'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; /** * @internal */ class TableRows implements \IteratorAggregate { private $generator; public function __construct(callable $generator) { $this->generator = $generator; } public function getIterator() : \Traversable { $g = $this->generator; return $g(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; /** * Defines the styles for a Table. * * @author Fabien Potencier * @author Саша Стаменковић * @author Dany Maillard */ class TableStyle { private $paddingChar = ' '; private $horizontalOutsideBorderChar = '-'; private $horizontalInsideBorderChar = '-'; private $verticalOutsideBorderChar = '|'; private $verticalInsideBorderChar = '|'; private $crossingChar = '+'; private $crossingTopRightChar = '+'; private $crossingTopMidChar = '+'; private $crossingTopLeftChar = '+'; private $crossingMidRightChar = '+'; private $crossingBottomRightChar = '+'; private $crossingBottomMidChar = '+'; private $crossingBottomLeftChar = '+'; private $crossingMidLeftChar = '+'; private $crossingTopLeftBottomChar = '+'; private $crossingTopMidBottomChar = '+'; private $crossingTopRightBottomChar = '+'; private $headerTitleFormat = ' %s '; private $footerTitleFormat = ' %s '; private $cellHeaderFormat = '%s'; private $cellRowFormat = '%s'; private $cellRowContentFormat = ' %s '; private $borderFormat = '%s'; private $padType = \STR_PAD_RIGHT; /** * Sets padding character, used for cell padding. * * @return $this */ public function setPaddingChar(string $paddingChar) { if (!$paddingChar) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('The padding char must not be empty.'); } $this->paddingChar = $paddingChar; return $this; } /** * Gets padding character, used for cell padding. * * @return string */ public function getPaddingChar() { return $this->paddingChar; } /** * Sets horizontal border characters. * * * ╔═══════════════╤══════════════════════════╤══════════════════╗ * 1 ISBN 2 Title │ Author ║ * ╠═══════════════╪══════════════════════════╪══════════════════╣ * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ * ╚═══════════════╧══════════════════════════╧══════════════════╝ * */ public function setHorizontalBorderChars(string $outside, string $inside = null) : self { $this->horizontalOutsideBorderChar = $outside; $this->horizontalInsideBorderChar = $inside ?? $outside; return $this; } /** * Sets vertical border characters. * * * ╔═══════════════╤══════════════════════════╤══════════════════╗ * ║ ISBN │ Title │ Author ║ * ╠═══════1═══════╪══════════════════════════╪══════════════════╣ * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ * ╟───────2───────┼──────────────────────────┼──────────────────╢ * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ * ╚═══════════════╧══════════════════════════╧══════════════════╝ * */ public function setVerticalBorderChars(string $outside, string $inside = null) : self { $this->verticalOutsideBorderChar = $outside; $this->verticalInsideBorderChar = $inside ?? $outside; return $this; } /** * Gets border characters. * * @internal */ public function getBorderChars() : array { return [$this->horizontalOutsideBorderChar, $this->verticalOutsideBorderChar, $this->horizontalInsideBorderChar, $this->verticalInsideBorderChar]; } /** * Sets crossing characters. * * Example: * * 1═══════════════2══════════════════════════2══════════════════3 * ║ ISBN │ Title │ Author ║ * 8'══════════════0'═════════════════════════0'═════════════════4' * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ * 8───────────────0──────────────────────────0──────────────────4 * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ * 7═══════════════6══════════════════════════6══════════════════5 * * * @param string $cross Crossing char (see #0 of example) * @param string $topLeft Top left char (see #1 of example) * @param string $topMid Top mid char (see #2 of example) * @param string $topRight Top right char (see #3 of example) * @param string $midRight Mid right char (see #4 of example) * @param string $bottomRight Bottom right char (see #5 of example) * @param string $bottomMid Bottom mid char (see #6 of example) * @param string $bottomLeft Bottom left char (see #7 of example) * @param string $midLeft Mid left char (see #8 of example) * @param string|null $topLeftBottom Top left bottom char (see #8' of example), equals to $midLeft if null * @param string|null $topMidBottom Top mid bottom char (see #0' of example), equals to $cross if null * @param string|null $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null */ public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, string $topLeftBottom = null, string $topMidBottom = null, string $topRightBottom = null) : self { $this->crossingChar = $cross; $this->crossingTopLeftChar = $topLeft; $this->crossingTopMidChar = $topMid; $this->crossingTopRightChar = $topRight; $this->crossingMidRightChar = $midRight; $this->crossingBottomRightChar = $bottomRight; $this->crossingBottomMidChar = $bottomMid; $this->crossingBottomLeftChar = $bottomLeft; $this->crossingMidLeftChar = $midLeft; $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft; $this->crossingTopMidBottomChar = $topMidBottom ?? $cross; $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight; return $this; } /** * Sets default crossing character used for each cross. * * @see {@link setCrossingChars()} for setting each crossing individually. */ public function setDefaultCrossingChar(string $char) : self { return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char); } /** * Gets crossing character. * * @return string */ public function getCrossingChar() { return $this->crossingChar; } /** * Gets crossing characters. * * @internal */ public function getCrossingChars() : array { return [$this->crossingChar, $this->crossingTopLeftChar, $this->crossingTopMidChar, $this->crossingTopRightChar, $this->crossingMidRightChar, $this->crossingBottomRightChar, $this->crossingBottomMidChar, $this->crossingBottomLeftChar, $this->crossingMidLeftChar, $this->crossingTopLeftBottomChar, $this->crossingTopMidBottomChar, $this->crossingTopRightBottomChar]; } /** * Sets header cell format. * * @return $this */ public function setCellHeaderFormat(string $cellHeaderFormat) { $this->cellHeaderFormat = $cellHeaderFormat; return $this; } /** * Gets header cell format. * * @return string */ public function getCellHeaderFormat() { return $this->cellHeaderFormat; } /** * Sets row cell format. * * @return $this */ public function setCellRowFormat(string $cellRowFormat) { $this->cellRowFormat = $cellRowFormat; return $this; } /** * Gets row cell format. * * @return string */ public function getCellRowFormat() { return $this->cellRowFormat; } /** * Sets row cell content format. * * @return $this */ public function setCellRowContentFormat(string $cellRowContentFormat) { $this->cellRowContentFormat = $cellRowContentFormat; return $this; } /** * Gets row cell content format. * * @return string */ public function getCellRowContentFormat() { return $this->cellRowContentFormat; } /** * Sets table border format. * * @return $this */ public function setBorderFormat(string $borderFormat) { $this->borderFormat = $borderFormat; return $this; } /** * Gets table border format. * * @return string */ public function getBorderFormat() { return $this->borderFormat; } /** * Sets cell padding type. * * @return $this */ public function setPadType(int $padType) { if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], \true)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).'); } $this->padType = $padType; return $this; } /** * Gets cell padding type. * * @return int */ public function getPadType() { return $this->padType; } public function getHeaderTitleFormat() : string { return $this->headerTitleFormat; } public function setHeaderTitleFormat(string $format) : self { $this->headerTitleFormat = $format; return $this; } public function getFooterTitleFormat() : string { return $this->footerTitleFormat; } public function setFooterTitleFormat(string $format) : self { $this->footerTitleFormat = $format; return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputAwareInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; /** * An implementation of InputAwareInterface for Helpers. * * @author Wouter J */ abstract class InputAwareHelper extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputAwareInterface { protected $input; /** * {@inheritdoc} */ public function setInput(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input) { $this->input = $input; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter; /** * The Formatter class provides helpers to format messages. * * @author Fabien Potencier */ class FormatterHelper extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper { /** * Formats a message within a section. * * @return string The format section */ public function formatSection(string $section, string $message, string $style = 'info') { return \sprintf('<%s>[%s] %s', $style, $section, $style, $message); } /** * Formats a message as a block of text. * * @param string|array $messages The message to write in the block * * @return string The formatter message */ public function formatBlock($messages, string $style, bool $large = \false) { if (!\is_array($messages)) { $messages = [$messages]; } $len = 0; $lines = []; foreach ($messages as $message) { $message = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape($message); $lines[] = \sprintf($large ? ' %s ' : ' %s ', $message); $len = \max(self::strlen($message) + ($large ? 4 : 2), $len); } $messages = $large ? [\str_repeat(' ', $len)] : []; for ($i = 0; isset($lines[$i]); ++$i) { $messages[] = $lines[$i] . \str_repeat(' ', $len - self::strlen($lines[$i])); } if ($large) { $messages[] = \str_repeat(' ', $len); } for ($i = 0; isset($messages[$i]); ++$i) { $messages[$i] = \sprintf('<%s>%s', $style, $messages[$i], $style); } return \implode("\n", $messages); } /** * Truncates a message to the given length. * * @return string */ public function truncate(string $message, int $length, string $suffix = '...') { $computedLength = $length - self::strlen($suffix); if ($computedLength > self::strlen($message)) { return $message; } return self::substr($message, 0, $length) . $suffix; } /** * {@inheritdoc} */ public function getName() { return 'formatter'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; /** * HelperSet represents a set of helpers to be used with a command. * * @author Fabien Potencier */ class HelperSet implements \IteratorAggregate { /** * @var Helper[] */ private $helpers = []; private $command; /** * @param Helper[] $helpers An array of helper */ public function __construct(array $helpers = []) { foreach ($helpers as $alias => $helper) { $this->set($helper, \is_int($alias) ? null : $alias); } } public function set(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\HelperInterface $helper, string $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { $this->helpers[$alias] = $helper; } $helper->setHelperSet($this); } /** * Returns true if the helper if defined. * * @return bool true if the helper is defined, false otherwise */ public function has(string $name) { return isset($this->helpers[$name]); } /** * Gets a helper value. * * @return HelperInterface The helper instance * * @throws InvalidArgumentException if the helper is not defined */ public function get(string $name) { if (!$this->has($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The helper "%s" is not defined.', $name)); } return $this->helpers[$name]; } public function setCommand(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command = null) { $this->command = $command; } /** * Gets the command associated with this helper set. * * @return Command A Command instance */ public function getCommand() { return $this->command; } /** * @return Helper[] */ public function getIterator() { return new \ArrayIterator($this->helpers); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Cursor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\MissingInputException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyle; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\StreamableInputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal; use function _HumbugBoxd02f763d3c56\Symfony\Component\String\s; /** * The QuestionHelper class provides helpers to interact with the user. * * @author Fabien Potencier */ class QuestionHelper extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper { private $inputStream; private static $shell; private static $stty = \true; private static $stdinIsInteractive; /** * Asks a question to the user. * * @return mixed The user answer * * @throws RuntimeException If there is no data to read in the input stream */ public function ask(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question $question) { if ($output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface) { $output = $output->getErrorOutput(); } if (!$input->isInteractive()) { return $this->getDefaultAnswer($question); } if ($input instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\StreamableInputInterface && ($stream = $input->getStream())) { $this->inputStream = $stream; } try { if (!$question->getValidator()) { return $this->doAsk($output, $question); } $interviewer = function () use($output, $question) { return $this->doAsk($output, $question); }; return $this->validateAttempts($interviewer, $output, $question); } catch (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\MissingInputException $exception) { $input->setInteractive(\false); if (null === ($fallbackOutput = $this->getDefaultAnswer($question))) { throw $exception; } return $fallbackOutput; } } /** * {@inheritdoc} */ public function getName() { return 'question'; } /** * Prevents usage of stty. */ public static function disableStty() { self::$stty = \false; } /** * Asks the question to the user. * * @return bool|mixed|string|null * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ private function doAsk(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question $question) { $this->writePrompt($output, $question); $inputStream = $this->inputStream ?: \STDIN; $autocomplete = $question->getAutocompleterCallback(); if (\function_exists('sapi_windows_cp_set')) { // Codepage used by cmd.exe on Windows to allow special characters (éàüñ). @\sapi_windows_cp_set(1252); } if (null === $autocomplete || !self::$stty || !\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal::hasSttyAvailable()) { $ret = \false; if ($question->isHidden()) { try { $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable()); $ret = $question->isTrimmable() ? \trim($hiddenResponse) : $hiddenResponse; } catch (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException $e) { if (!$question->isHiddenFallback()) { throw $e; } } } if (\false === $ret) { $ret = \fgets($inputStream, 4096); if (\false === $ret) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\MissingInputException('Aborted.'); } if ($question->isTrimmable()) { $ret = \trim($ret); } } } else { $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete); $ret = $question->isTrimmable() ? \trim($autocomplete) : $autocomplete; } if ($output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput) { $output->addContent($ret); } $ret = \strlen($ret) > 0 ? $ret : $question->getDefault(); if ($normalizer = $question->getNormalizer()) { return $normalizer($ret); } return $ret; } /** * @return mixed */ private function getDefaultAnswer(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question $question) { $default = $question->getDefault(); if (null === $default) { return $default; } if ($validator = $question->getValidator()) { return \call_user_func($question->getValidator(), $default); } elseif ($question instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion) { $choices = $question->getChoices(); if (!$question->isMultiselect()) { return isset($choices[$default]) ? $choices[$default] : $default; } $default = \explode(',', $default); foreach ($default as $k => $v) { $v = $question->isTrimmable() ? \trim($v) : $v; $default[$k] = isset($choices[$v]) ? $choices[$v] : $v; } } return $default; } /** * Outputs the question prompt. */ protected function writePrompt(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question $question) { $message = $question->getQuestion(); if ($question instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion) { $output->writeln(\array_merge([$question->getQuestion()], $this->formatChoiceQuestionChoices($question, 'info'))); $message = $question->getPrompt(); } $output->write($message); } /** * @return string[] */ protected function formatChoiceQuestionChoices(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion $question, string $tag) { $messages = []; $maxWidth = \max(\array_map('self::strlen', \array_keys($choices = $question->getChoices()))); foreach ($choices as $key => $value) { $padding = \str_repeat(' ', $maxWidth - self::strlen($key)); $messages[] = \sprintf(" [<{$tag}>%s{$padding}] %s", $key, $value); } return $messages; } /** * Outputs an error message. */ protected function writeError(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \Exception $error) { if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) { $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'); } else { $message = '' . $error->getMessage() . ''; } $output->writeln($message); } /** * Autocompletes a question. * * @param resource $inputStream */ private function autocomplete(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question $question, $inputStream, callable $autocomplete) : string { $cursor = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Cursor($output, $inputStream); $fullChoice = ''; $ret = ''; $i = 0; $ofs = -1; $matches = $autocomplete($ret); $numMatches = \count($matches); $sttyMode = \shell_exec('stty -g'); // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) \shell_exec('stty -icanon -echo'); // Add highlighted text style $output->getFormatter()->setStyle('hl', new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyle('black', 'white')); // Read a keypress while (!\feof($inputStream)) { $c = \fread($inputStream, 1); // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. if (\false === $c || '' === $ret && '' === $c && null === $question->getDefault()) { \shell_exec(\sprintf('stty %s', $sttyMode)); throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\MissingInputException('Aborted.'); } elseif ("" === $c) { // Backspace Character if (0 === $numMatches && 0 !== $i) { --$i; $cursor->moveLeft(\_HumbugBoxd02f763d3c56\Symfony\Component\String\s($fullChoice)->slice(-1)->width(\false)); $fullChoice = self::substr($fullChoice, 0, $i); } if (0 === $i) { $ofs = -1; $matches = $autocomplete($ret); $numMatches = \count($matches); } else { $numMatches = 0; } // Pop the last character off the end of our string $ret = self::substr($ret, 0, $i); } elseif ("\33" === $c) { // Did we read an escape sequence? $c .= \fread($inputStream, 2); // A = Up Arrow. B = Down Arrow if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) { if ('A' === $c[2] && -1 === $ofs) { $ofs = 0; } if (0 === $numMatches) { continue; } $ofs += 'A' === $c[2] ? -1 : 1; $ofs = ($numMatches + $ofs) % $numMatches; } } elseif (\ord($c) < 32) { if ("\t" === $c || "\n" === $c) { if ($numMatches > 0 && -1 !== $ofs) { $ret = (string) $matches[$ofs]; // Echo out remaining chars for current match $remainingCharacters = \substr($ret, \strlen(\trim($this->mostRecentlyEnteredValue($fullChoice)))); $output->write($remainingCharacters); $fullChoice .= $remainingCharacters; $i = self::strlen($fullChoice); $matches = \array_filter($autocomplete($ret), function ($match) use($ret) { return '' === $ret || 0 === \strpos($match, $ret); }); $numMatches = \count($matches); $ofs = -1; } if ("\n" === $c) { $output->write($c); break; } $numMatches = 0; } continue; } else { if ("" <= $c) { $c .= \fread($inputStream, ["" => 1, "" => 1, "" => 2, "" => 3][$c & ""]); } $output->write($c); $ret .= $c; $fullChoice .= $c; ++$i; $tempRet = $ret; if ($question instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion && $question->isMultiselect()) { $tempRet = $this->mostRecentlyEnteredValue($fullChoice); } $numMatches = 0; $ofs = 0; foreach ($autocomplete($ret) as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) if (0 === \strpos($value, $tempRet)) { $matches[$numMatches++] = $value; } } } $cursor->clearLineAfter(); if ($numMatches > 0 && -1 !== $ofs) { $cursor->savePosition(); // Write highlighted text, complete the partially entered response $charactersEntered = \strlen(\trim($this->mostRecentlyEnteredValue($fullChoice))); $output->write('' . \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escapeTrailingBackslash(\substr($matches[$ofs], $charactersEntered)) . ''); $cursor->restorePosition(); } } // Reset stty so it behaves normally again \shell_exec(\sprintf('stty %s', $sttyMode)); return $fullChoice; } private function mostRecentlyEnteredValue(string $entered) : string { // Determine the most recent value that the user entered if (\false === \strpos($entered, ',')) { return $entered; } $choices = \explode(',', $entered); if (\strlen($lastChoice = \trim($choices[\count($choices) - 1])) > 0) { return $lastChoice; } return $entered; } /** * Gets a hidden response from user. * * @param resource $inputStream The handler resource * @param bool $trimmable Is the answer trimmable * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ private function getHiddenResponse(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, $inputStream, bool $trimmable = \true) : string { if ('\\' === \DIRECTORY_SEPARATOR) { $exe = __DIR__ . '/../Resources/bin/hiddeninput.exe'; // handle code running from a phar if ('phar:' === \substr(__FILE__, 0, 5)) { $tmpExe = \sys_get_temp_dir() . '/hiddeninput.exe'; \copy($exe, $tmpExe); $exe = $tmpExe; } $sExec = \shell_exec($exe); $value = $trimmable ? \rtrim($sExec) : $sExec; $output->writeln(''); if (isset($tmpExe)) { \unlink($tmpExe); } return $value; } if (self::$stty && \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal::hasSttyAvailable()) { $sttyMode = \shell_exec('stty -g'); \shell_exec('stty -echo'); } elseif ($this->isInteractiveInput($inputStream)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException('Unable to hide the response.'); } $value = \fgets($inputStream, 4096); if (self::$stty && \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal::hasSttyAvailable()) { \shell_exec(\sprintf('stty %s', $sttyMode)); } if (\false === $value) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\MissingInputException('Aborted.'); } if ($trimmable) { $value = \trim($value); } $output->writeln(''); return $value; } /** * Validates an attempt. * * @param callable $interviewer A callable that will ask for a question and return the result * * @return mixed The validated response * * @throws \Exception In case the max number of attempts has been reached and no valid response has been given */ private function validateAttempts(callable $interviewer, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question $question) { $error = null; $attempts = $question->getMaxAttempts(); while (null === $attempts || $attempts--) { if (null !== $error) { $this->writeError($output, $error); } try { return $question->getValidator()($interviewer()); } catch (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException $e) { throw $e; } catch (\Exception $error) { } } throw $error; } private function isInteractiveInput($inputStream) : bool { if ('php://stdin' !== (\stream_get_meta_data($inputStream)['uri'] ?? null)) { return \false; } if (null !== self::$stdinIsInteractive) { return self::$stdinIsInteractive; } if (\function_exists('stream_isatty')) { return self::$stdinIsInteractive = \stream_isatty(\fopen('php://stdin', 'r')); } if (\function_exists('posix_isatty')) { return self::$stdinIsInteractive = \posix_isatty(\fopen('php://stdin', 'r')); } if (!\function_exists('exec')) { return self::$stdinIsInteractive = \true; } \exec('stty 2> /dev/null', $output, $status); return self::$stdinIsInteractive = 1 !== $status; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Process\Exception\ProcessFailedException; use _HumbugBoxd02f763d3c56\Symfony\Component\Process\Process; /** * The ProcessHelper class provides helpers to run external processes. * * @author Fabien Potencier * * @final */ class ProcessHelper extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper { /** * Runs an external process. * * @param array|Process $cmd An instance of Process or an array of the command and arguments * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The process that ran */ public function run(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, $cmd, string $error = null, callable $callback = null, int $verbosity = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE) : \_HumbugBoxd02f763d3c56\Symfony\Component\Process\Process { if (!\class_exists(\_HumbugBoxd02f763d3c56\Symfony\Component\Process\Process::class)) { throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".'); } if ($output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface) { $output = $output->getErrorOutput(); } $formatter = $this->getHelperSet()->get('debug_formatter'); if ($cmd instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Process\Process) { $cmd = [$cmd]; } if (!\is_array($cmd)) { throw new \TypeError(\sprintf('The "command" argument of "%s()" must be an array or a "%s" instance, "%s" given.', __METHOD__, \_HumbugBoxd02f763d3c56\Symfony\Component\Process\Process::class, \get_debug_type($cmd))); } if (\is_string($cmd[0] ?? null)) { $process = new \_HumbugBoxd02f763d3c56\Symfony\Component\Process\Process($cmd); $cmd = []; } elseif (($cmd[0] ?? null) instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Process\Process) { $process = $cmd[0]; unset($cmd[0]); } else { throw new \InvalidArgumentException(\sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__)); } if ($verbosity <= $output->getVerbosity()) { $output->write($formatter->start(\spl_object_hash($process), $this->escapeString($process->getCommandLine()))); } if ($output->isDebug()) { $callback = $this->wrapCallback($output, $process, $callback); } $process->run($callback, $cmd); if ($verbosity <= $output->getVerbosity()) { $message = $process->isSuccessful() ? 'Command ran successfully' : \sprintf('%s Command did not run successfully', $process->getExitCode()); $output->write($formatter->stop(\spl_object_hash($process), $message, $process->isSuccessful())); } if (!$process->isSuccessful() && null !== $error) { $output->writeln(\sprintf('%s', $this->escapeString($error))); } return $process; } /** * Runs the process. * * This is identical to run() except that an exception is thrown if the process * exits with a non-zero exit code. * * @param string|Process $cmd An instance of Process or a command to run * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The process that ran * * @throws ProcessFailedException * * @see run() */ public function mustRun(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, $cmd, string $error = null, callable $callback = null) : \_HumbugBoxd02f763d3c56\Symfony\Component\Process\Process { $process = $this->run($output, $cmd, $error, $callback); if (!$process->isSuccessful()) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Process\Exception\ProcessFailedException($process); } return $process; } /** * Wraps a Process callback to add debugging output. */ public function wrapCallback(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \_HumbugBoxd02f763d3c56\Symfony\Component\Process\Process $process, callable $callback = null) : callable { if ($output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface) { $output = $output->getErrorOutput(); } $formatter = $this->getHelperSet()->get('debug_formatter'); return function ($type, $buffer) use($output, $process, $callback, $formatter) { $output->write($formatter->progress(\spl_object_hash($process), $this->escapeString($buffer), \_HumbugBoxd02f763d3c56\Symfony\Component\Process\Process::ERR === $type)); if (null !== $callback) { $callback($type, $buffer); } }; } private function escapeString(string $str) : string { return \str_replace('<', '\\<', $str); } /** * {@inheritdoc} */ public function getName() : string { return 'process'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; /** * HelperInterface is the interface all helpers must implement. * * @author Fabien Potencier */ interface HelperInterface { /** * Sets the helper set associated with this helper. */ public function setHelperSet(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\HelperSet $helperSet = null); /** * Gets the helper set associated with this helper. * * @return HelperSet A HelperSet instance */ public function getHelperSet(); /** * Returns the canonical name of this helper. * * @return string The canonical name */ public function getName(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; /** * @author Abdellatif Ait boudad */ class TableCell { private $value; private $options = ['rowspan' => 1, 'colspan' => 1]; public function __construct(string $value = '', array $options = []) { $this->value = $value; // check option names if ($diff = \array_diff(\array_keys($options), \array_keys($this->options))) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The TableCell does not support the following options: \'%s\'.', \implode('\', \'', $diff))); } $this->options = \array_merge($this->options, $options); } /** * Returns the cell value. * * @return string */ public function __toString() { return $this->value; } /** * Gets number of colspan. * * @return int */ public function getColspan() { return (int) $this->options['colspan']; } /** * Gets number of rowspan. * * @return int */ public function getRowspan() { return (int) $this->options['rowspan']; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * Helper is the base class for all helper classes. * * @author Fabien Potencier */ abstract class Helper implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\HelperInterface { protected $helperSet = null; /** * {@inheritdoc} */ public function setHelperSet(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\HelperSet $helperSet = null) { $this->helperSet = $helperSet; } /** * {@inheritdoc} */ public function getHelperSet() { return $this->helperSet; } /** * Returns the length of a string, using mb_strwidth if it is available. * * @return int The length of the string */ public static function strlen(?string $string) { if (\false === ($encoding = \mb_detect_encoding($string, null, \true))) { return \strlen($string); } return \mb_strwidth($string, $encoding); } /** * Returns the subset of a string, using mb_substr if it is available. * * @return string The string subset */ public static function substr(string $string, int $from, int $length = null) { if (\false === ($encoding = \mb_detect_encoding($string, null, \true))) { return \substr($string, $from, $length); } return \mb_substr($string, $from, $length, $encoding); } public static function formatTime($secs) { static $timeFormats = [[0, '< 1 sec'], [1, '1 sec'], [2, 'secs', 1], [60, '1 min'], [120, 'mins', 60], [3600, '1 hr'], [7200, 'hrs', 3600], [86400, '1 day'], [172800, 'days', 86400]]; foreach ($timeFormats as $index => $format) { if ($secs >= $format[0]) { if (isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0] || $index == \count($timeFormats) - 1) { if (2 == \count($format)) { return $format[1]; } return \floor($secs / $format[2]) . ' ' . $format[1]; } } } } public static function formatMemory(int $memory) { if ($memory >= 1024 * 1024 * 1024) { return \sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024); } if ($memory >= 1024 * 1024) { return \sprintf('%.1f MiB', $memory / 1024 / 1024); } if ($memory >= 1024) { return \sprintf('%d KiB', $memory / 1024); } return \sprintf('%d B', $memory); } public static function strlenWithoutDecoration(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter, $string) { return self::strlen(self::removeDecoration($formatter, $string)); } public static function removeDecoration(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter, $string) { $isDecorated = $formatter->isDecorated(); $formatter->setDecorated(\false); // remove <...> formatting $string = $formatter->format($string); // remove already formatted characters $string = \preg_replace("/\33\\[[^m]*m/", '', $string); $formatter->setDecorated($isDecorated); return $string; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * @author Kevin Bond */ class ProgressIndicator { private $output; private $startTime; private $format; private $message; private $indicatorValues; private $indicatorCurrent; private $indicatorChangeInterval; private $indicatorUpdateTime; private $started = \false; private static $formatters; private static $formats; /** * @param int $indicatorChangeInterval Change interval in milliseconds * @param array|null $indicatorValues Animated indicator characters */ public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) { $this->output = $output; if (null === $format) { $format = $this->determineBestFormat(); } if (null === $indicatorValues) { $indicatorValues = ['-', '\\', '|', '/']; } $indicatorValues = \array_values($indicatorValues); if (2 > \count($indicatorValues)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('Must have at least 2 indicator value characters.'); } $this->format = self::getFormatDefinition($format); $this->indicatorChangeInterval = $indicatorChangeInterval; $this->indicatorValues = $indicatorValues; $this->startTime = \time(); } /** * Sets the current indicator message. */ public function setMessage(?string $message) { $this->message = $message; $this->display(); } /** * Starts the indicator output. */ public function start(string $message) { if ($this->started) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('Progress indicator already started.'); } $this->message = $message; $this->started = \true; $this->startTime = \time(); $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval; $this->indicatorCurrent = 0; $this->display(); } /** * Advances the indicator. */ public function advance() { if (!$this->started) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('Progress indicator has not yet been started.'); } if (!$this->output->isDecorated()) { return; } $currentTime = $this->getCurrentTimeInMilliseconds(); if ($currentTime < $this->indicatorUpdateTime) { return; } $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval; ++$this->indicatorCurrent; $this->display(); } /** * Finish the indicator with message. * * @param $message */ public function finish(string $message) { if (!$this->started) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('Progress indicator has not yet been started.'); } $this->message = $message; $this->display(); $this->output->writeln(''); $this->started = \false; } /** * Gets the format for a given name. * * @return string|null A format string */ public static function getFormatDefinition(string $name) { if (!self::$formats) { self::$formats = self::initFormats(); } return isset(self::$formats[$name]) ? self::$formats[$name] : null; } /** * Sets a placeholder formatter for a given name. * * This method also allow you to override an existing placeholder. */ public static function setPlaceholderFormatterDefinition(string $name, callable $callable) { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } self::$formatters[$name] = $callable; } /** * Gets the placeholder formatter for a given name (including the delimiter char like %). * * @return callable|null A PHP callable */ public static function getPlaceholderFormatterDefinition(string $name) { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; } private function display() { if (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { return; } $this->overwrite(\preg_replace_callback("{%([a-z\\-_]+)(?:\\:([^%]+))?%}i", function ($matches) { if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) { return $formatter($this); } return $matches[0]; }, $this->format)); } private function determineBestFormat() : string { switch ($this->output->getVerbosity()) { // OutputInterface::VERBOSITY_QUIET: display is disabled anyway case \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE: return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi'; case \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE: case \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG: return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi'; default: return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi'; } } /** * Overwrites a previous message to the output. */ private function overwrite(string $message) { if ($this->output->isDecorated()) { $this->output->write("\r\33[2K"); $this->output->write($message); } else { $this->output->writeln($message); } } private function getCurrentTimeInMilliseconds() : float { return \round(\microtime(\true) * 1000); } 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 \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::formatTime(\time() - $indicator->startTime); }, 'memory' => function () { return \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::formatMemory(\memory_get_usage(\true)); }]; } private static function initFormats() : array { return ['normal' => ' %indicator% %message%', 'normal_no_ansi' => ' %message%', 'verbose' => ' %indicator% %message% (%elapsed:6s%)', 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)']; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Cursor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal; /** * The ProgressBar provides helpers to display progress output. * * @author Fabien Potencier * @author Chris Jones */ final class ProgressBar { private $barWidth = 28; private $barChar; private $emptyBarChar = '-'; private $progressChar = '>'; private $format; private $internalFormat; private $redrawFreq = 1; private $writeCount; private $lastWriteTime; private $minSecondsBetweenRedraws = 0; private $maxSecondsBetweenRedraws = 1; private $output; private $step = 0; private $max; private $startTime; private $stepWidth; private $percent = 0.0; private $formatLineCount; private $messages = []; private $overwrite = \true; private $terminal; private $previousMessage; private $cursor; private static $formatters; private static $formats; /** * @param int $max Maximum steps (0 if unknown) */ public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 0.1) { if ($output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface) { $output = $output->getErrorOutput(); } $this->output = $output; $this->setMaxSteps($max); $this->terminal = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal(); if (0 < $minSecondsBetweenRedraws) { $this->redrawFreq = null; $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws; } if (!$this->output->isDecorated()) { // disable overwrite when output does not support ANSI codes. $this->overwrite = \false; // set a reasonable redraw frequency so output isn't flooded $this->redrawFreq = null; } $this->startTime = \time(); $this->cursor = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Cursor($output); } /** * Sets a placeholder formatter for a given name. * * This method also allow you to override an existing placeholder. * * @param string $name The placeholder name (including the delimiter char like %) * @param callable $callable A PHP callable */ public static function setPlaceholderFormatterDefinition(string $name, callable $callable) : void { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } self::$formatters[$name] = $callable; } /** * Gets the placeholder formatter for a given name. * * @param string $name The placeholder name (including the delimiter char like %) * * @return callable|null A PHP callable */ public static function getPlaceholderFormatterDefinition(string $name) : ?callable { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; } /** * Sets a format for a given name. * * This method also allow you to override an existing format. * * @param string $name The format name * @param string $format A format string */ public static function setFormatDefinition(string $name, string $format) : void { if (!self::$formats) { self::$formats = self::initFormats(); } self::$formats[$name] = $format; } /** * Gets the format for a given name. * * @param string $name The format name * * @return string|null A format string */ public static function getFormatDefinition(string $name) : ?string { if (!self::$formats) { self::$formats = self::initFormats(); } return isset(self::$formats[$name]) ? self::$formats[$name] : null; } /** * Associates a text with a named placeholder. * * The text is displayed when the progress bar is rendered but only * when the corresponding placeholder is part of the custom format line * (by wrapping the name with %). * * @param string $message The text to associate with the placeholder * @param string $name The name of the placeholder */ public function setMessage(string $message, string $name = 'message') { $this->messages[$name] = $message; } public function getMessage(string $name = 'message') { return $this->messages[$name]; } public function getStartTime() : int { return $this->startTime; } public function getMaxSteps() : int { return $this->max; } public function getProgress() : int { return $this->step; } private function getStepWidth() : int { return $this->stepWidth; } public function getProgressPercent() : float { return $this->percent; } public function getBarOffset() : float { return \floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? \min(5, $this->barWidth / 15) * $this->writeCount : $this->step) % $this->barWidth); } public function getEstimated() : float { if (!$this->step) { return 0; } return \round((\time() - $this->startTime) / $this->step * $this->max); } public function getRemaining() : float { if (!$this->step) { return 0; } return \round((\time() - $this->startTime) / $this->step * ($this->max - $this->step)); } public function setBarWidth(int $size) { $this->barWidth = \max(1, $size); } public function getBarWidth() : int { return $this->barWidth; } public function setBarCharacter(string $char) { $this->barChar = $char; } public function getBarCharacter() : string { if (null === $this->barChar) { return $this->max ? '=' : $this->emptyBarChar; } return $this->barChar; } public function setEmptyBarCharacter(string $char) { $this->emptyBarChar = $char; } public function getEmptyBarCharacter() : string { return $this->emptyBarChar; } public function setProgressCharacter(string $char) { $this->progressChar = $char; } public function getProgressCharacter() : string { return $this->progressChar; } public function setFormat(string $format) { $this->format = null; $this->internalFormat = $format; } /** * Sets the redraw frequency. * * @param int|float $freq The frequency in steps */ public function setRedrawFrequency(?int $freq) { $this->redrawFreq = null !== $freq ? \max(1, $freq) : null; } public function minSecondsBetweenRedraws(float $seconds) : void { $this->minSecondsBetweenRedraws = $seconds; } public function maxSecondsBetweenRedraws(float $seconds) : void { $this->maxSecondsBetweenRedraws = $seconds; } /** * Returns an iterator that will automatically update the progress bar when iterated. * * @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable */ public function iterate(iterable $iterable, int $max = null) : iterable { $this->start($max ?? (\is_countable($iterable) ? \count($iterable) : 0)); foreach ($iterable as $key => $value) { (yield $key => $value); $this->advance(); } $this->finish(); } /** * Starts the progress output. * * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged */ public function start(int $max = null) { $this->startTime = \time(); $this->step = 0; $this->percent = 0.0; if (null !== $max) { $this->setMaxSteps($max); } $this->display(); } /** * Advances the progress output X steps. * * @param int $step Number of steps to advance */ public function advance(int $step = 1) { $this->setProgress($this->step + $step); } /** * Sets whether to overwrite the progressbar, false for new line. */ public function setOverwrite(bool $overwrite) { $this->overwrite = $overwrite; } public function setProgress(int $step) { if ($this->max && $step > $this->max) { $this->max = $step; } elseif ($step < 0) { $step = 0; } $redrawFreq = $this->redrawFreq ?? ($this->max ?: 10) / 10; $prevPeriod = (int) ($this->step / $redrawFreq); $currPeriod = (int) ($step / $redrawFreq); $this->step = $step; $this->percent = $this->max ? (float) $this->step / $this->max : 0; $timeInterval = \microtime(\true) - $this->lastWriteTime; // Draw regardless of other limits if ($this->max === $step) { $this->display(); return; } // Throttling if ($timeInterval < $this->minSecondsBetweenRedraws) { return; } // Draw each step period, but not too late if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) { $this->display(); } } public function setMaxSteps(int $max) { $this->format = null; $this->max = \max(0, $max); $this->stepWidth = $this->max ? \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen((string) $this->max) : 4; } /** * Finishes the progress output. */ public function finish() : void { if (!$this->max) { $this->max = $this->step; } if ($this->step === $this->max && !$this->overwrite) { // prevent double 100% output return; } $this->setProgress($this->max); } /** * Outputs the current progress string. */ public function display() : void { if (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { return; } if (null === $this->format) { $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); } $this->overwrite($this->buildLine()); } /** * Removes the progress bar from the current line. * * This is useful if you wish to write some output * while a progress bar is running. * Call display() to show the progress bar again. */ public function clear() : void { if (!$this->overwrite) { return; } if (null === $this->format) { $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); } $this->overwrite(''); } private function setRealFormat(string $format) { // try to use the _nomax variant if available if (!$this->max && null !== self::getFormatDefinition($format . '_nomax')) { $this->format = self::getFormatDefinition($format . '_nomax'); } elseif (null !== self::getFormatDefinition($format)) { $this->format = self::getFormatDefinition($format); } else { $this->format = $format; } $this->formatLineCount = \substr_count($this->format, "\n"); } /** * Overwrites a previous message to the output. */ private function overwrite(string $message) : void { if ($this->previousMessage === $message) { return; } $originalMessage = $message; if ($this->overwrite) { if (null !== $this->previousMessage) { if ($this->output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleSectionOutput) { $lines = \floor(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($message) / $this->terminal->getWidth()) + $this->formatLineCount + 1; $this->output->clear($lines); } else { if ($this->formatLineCount > 0) { $this->cursor->moveUp($this->formatLineCount); } $this->cursor->moveToColumn(1); $this->cursor->clearLine(); } } } elseif ($this->step > 0) { $message = \PHP_EOL . $message; } $this->previousMessage = $originalMessage; $this->lastWriteTime = \microtime(\true); $this->output->write($message); ++$this->writeCount; } private function determineBestFormat() : string { switch ($this->output->getVerbosity()) { // OutputInterface::VERBOSITY_QUIET: display is disabled anyway case \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERBOSE: return $this->max ? 'verbose' : 'verbose_nomax'; case \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE: return $this->max ? 'very_verbose' : 'very_verbose_nomax'; case \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_DEBUG: return $this->max ? 'debug' : 'debug_nomax'; default: return $this->max ? 'normal' : 'normal_nomax'; } } private static function initPlaceholderFormatters() : array { return ['bar' => function (self $bar, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { $completeBars = $bar->getBarOffset(); $display = \str_repeat($bar->getBarCharacter(), $completeBars); if ($completeBars < $bar->getBarWidth()) { $emptyBars = $bar->getBarWidth() - $completeBars - \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter()); $display .= $bar->getProgressCharacter() . \str_repeat($bar->getEmptyBarCharacter(), $emptyBars); } return $display; }, 'elapsed' => function (self $bar) { return \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::formatTime(\time() - $bar->getStartTime()); }, 'remaining' => function (self $bar) { if (!$bar->getMaxSteps()) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); } return \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::formatTime($bar->getRemaining()); }, 'estimated' => function (self $bar) { if (!$bar->getMaxSteps()) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); } return \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::formatTime($bar->getEstimated()); }, 'memory' => function (self $bar) { return \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\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); }]; } private static function initFormats() : array { return ['normal' => ' %current%/%max% [%bar%] %percent:3s%%', 'normal_nomax' => ' %current% [%bar%]', 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%']; } private function buildLine() : string { $regex = "{%([a-z\\-_]+)(?:\\:([^%]+))?%}i"; $callback = function ($matches) { if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { $text = $formatter($this, $this->output); } elseif (isset($this->messages[$matches[1]])) { $text = $this->messages[$matches[1]]; } else { return $matches[0]; } if (isset($matches[2])) { $text = \sprintf('%' . $matches[2], $text); } return $text; }; $line = \preg_replace_callback($regex, $callback, $this->format); // gets string length for each sub line with multiline format $linesLength = \array_map(function ($subLine) { return \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->output->getFormatter(), \rtrim($subLine, "\r")); }, \explode("\n", $line)); $linesWidth = \max($linesLength); $terminalWidth = $this->terminal->getWidth(); if ($linesWidth <= $terminalWidth) { return $line; } $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth); return \preg_replace_callback($regex, $callback, $this->format); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Cloner\ClonerInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Cloner\VarCloner; use _HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Dumper\CliDumper; /** * @author Roland Franssen */ final class Dumper { private $output; private $dumper; private $cloner; private $handler; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \_HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Dumper\CliDumper $dumper = null, \_HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Cloner\ClonerInterface $cloner = null) { $this->output = $output; $this->dumper = $dumper; $this->cloner = $cloner; if (\class_exists(\_HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Dumper\CliDumper::class)) { $this->handler = function ($var) : string { $dumper = $this->dumper ?? ($this->dumper = new \_HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Dumper\CliDumper(null, null, \_HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Dumper\CliDumper::DUMP_LIGHT_ARRAY | \_HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Dumper\CliDumper::DUMP_COMMA_SEPARATOR)); $dumper->setColors($this->output->isDecorated()); return \rtrim($dumper->dump(($this->cloner ?? ($this->cloner = new \_HumbugBoxd02f763d3c56\Symfony\Component\VarDumper\Cloner\VarCloner()))->cloneVar($var)->withRefHandles(\false), \true)); }; } else { $this->handler = function ($var) : string { switch (\true) { case null === $var: return 'null'; case \true === $var: return 'true'; case \false === $var: return 'false'; case \is_string($var): return '"' . $var . '"'; default: return \rtrim(\print_r($var, \true)); } }; } } public function __invoke($var) : string { return ($this->handler)($var); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; /** * Represents a choice question. * * @author Fabien Potencier */ class ChoiceQuestion extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question { private $choices; private $multiselect = \false; private $prompt = ' > '; private $errorMessage = 'Value "%s" is invalid'; /** * @param string $question The question to ask to the user * @param array $choices The list of available choices * @param mixed $default The default answer to return */ public function __construct(string $question, array $choices, $default = null) { if (!$choices) { throw new \LogicException('Choice question must have at least 1 choice available.'); } parent::__construct($question, $default); $this->choices = $choices; $this->setValidator($this->getDefaultValidator()); $this->setAutocompleterValues($choices); } /** * Returns available choices. * * @return array */ public function getChoices() { return $this->choices; } /** * Sets multiselect option. * * When multiselect is set to true, multiple choices can be answered. * * @return $this */ public function setMultiselect(bool $multiselect) { $this->multiselect = $multiselect; $this->setValidator($this->getDefaultValidator()); return $this; } /** * Returns whether the choices are multiselect. * * @return bool */ public function isMultiselect() { return $this->multiselect; } /** * Gets the prompt for choices. * * @return string */ public function getPrompt() { return $this->prompt; } /** * Sets the prompt for choices. * * @return $this */ public function setPrompt(string $prompt) { $this->prompt = $prompt; return $this; } /** * Sets the error message for invalid values. * * The error message has a string placeholder (%s) for the invalid value. * * @return $this */ public function setErrorMessage(string $errorMessage) { $this->errorMessage = $errorMessage; $this->setValidator($this->getDefaultValidator()); return $this; } private function getDefaultValidator() : callable { $choices = $this->choices; $errorMessage = $this->errorMessage; $multiselect = $this->multiselect; $isAssoc = $this->isAssoc($choices); return function ($selected) use($choices, $errorMessage, $multiselect, $isAssoc) { if ($multiselect) { // Check for a separated comma values if (!\preg_match('/^[^,]+(?:,[^,]+)*$/', $selected, $matches)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf($errorMessage, $selected)); } $selectedChoices = \explode(',', $selected); } else { $selectedChoices = [$selected]; } if ($this->isTrimmable()) { foreach ($selectedChoices as $k => $v) { $selectedChoices[$k] = \trim($v); } } $multiselectChoices = []; foreach ($selectedChoices as $value) { $results = []; foreach ($choices as $key => $choice) { if ($choice === $value) { $results[] = $key; } } if (\count($results) > 1) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The provided answer is ambiguous. Value should be one of "%s".', \implode('" or "', $results))); } $result = \array_search($value, $choices); if (!$isAssoc) { if (\false !== $result) { $result = $choices[$result]; } elseif (isset($choices[$value])) { $result = $choices[$value]; } } elseif (\false === $result && isset($choices[$value])) { $result = $value; } if (\false === $result) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf($errorMessage, $value)); } $multiselectChoices[] = (string) $result; } if ($multiselect) { return $multiselectChoices; } return \current($multiselectChoices); }; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question; /** * Represents a yes/no question. * * @author Fabien Potencier */ class ConfirmationQuestion extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question { private $trueAnswerRegex; /** * @param string $question The question to ask to the user * @param bool $default The default answer to return, true or false * @param string $trueAnswerRegex A regex to match the "yes" answer */ public function __construct(string $question, bool $default = \true, string $trueAnswerRegex = '/^y/i') { parent::__construct($question, $default); $this->trueAnswerRegex = $trueAnswerRegex; $this->setNormalizer($this->getDefaultNormalizer()); } /** * Returns the default answer normalizer. */ private function getDefaultNormalizer() : callable { $default = $this->getDefault(); $regex = $this->trueAnswerRegex; return function ($answer) use($default, $regex) { if (\is_bool($answer)) { return $answer; } $answerIsTrue = (bool) \preg_match($regex, $answer); if (\false === $default) { return $answer && $answerIsTrue; } return '' === $answer || $answerIsTrue; }; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; /** * Represents a Question. * * @author Fabien Potencier */ class Question { private $question; private $attempts; private $hidden = \false; private $hiddenFallback = \true; private $autocompleterCallback; private $validator; private $default; private $normalizer; private $trimmable = \true; /** * @param string $question The question to ask to the user * @param mixed $default The default answer to return if the user enters nothing */ public function __construct(string $question, $default = null) { $this->question = $question; $this->default = $default; } /** * Returns the question. * * @return string */ public function getQuestion() { return $this->question; } /** * Returns the default answer. * * @return mixed */ public function getDefault() { return $this->default; } /** * Returns whether the user response must be hidden. * * @return bool */ public function isHidden() { return $this->hidden; } /** * Sets whether the user response must be hidden or not. * * @param bool $hidden * * @return $this * * @throws LogicException In case the autocompleter is also used */ public function setHidden($hidden) { if ($this->autocompleterCallback) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('A hidden question cannot use the autocompleter.'); } $this->hidden = (bool) $hidden; return $this; } /** * In case the response can not be hidden, whether to fallback on non-hidden question or not. * * @return bool */ public function isHiddenFallback() { return $this->hiddenFallback; } /** * Sets whether to fallback on non-hidden question if the response can not be hidden. * * @param bool $fallback * * @return $this */ public function setHiddenFallback($fallback) { $this->hiddenFallback = (bool) $fallback; return $this; } /** * Gets values for the autocompleter. * * @return iterable|null */ public function getAutocompleterValues() { $callback = $this->getAutocompleterCallback(); return $callback ? $callback('') : null; } /** * Sets values for the autocompleter. * * @return $this * * @throws LogicException */ public function setAutocompleterValues(?iterable $values) { 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; }; } elseif ($values instanceof \Traversable) { $valueCache = null; $callback = static function () use($values, &$valueCache) { return $valueCache ?? ($valueCache = \iterator_to_array($values, \false)); }; } else { $callback = null; } return $this->setAutocompleterCallback($callback); } /** * Gets the callback function used for the autocompleter. */ public function getAutocompleterCallback() : ?callable { return $this->autocompleterCallback; } /** * Sets the callback function used for the autocompleter. * * The callback is passed the user input as argument and should return an iterable of corresponding suggestions. * * @return $this */ public function setAutocompleterCallback(callable $callback = null) : self { if ($this->hidden && null !== $callback) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('A hidden question cannot use the autocompleter.'); } $this->autocompleterCallback = $callback; return $this; } /** * Sets a validator for the question. * * @return $this */ public function setValidator(callable $validator = null) { $this->validator = $validator; return $this; } /** * Gets the validator for the question. * * @return callable|null */ public function getValidator() { return $this->validator; } /** * Sets the maximum number of attempts. * * Null means an unlimited number of attempts. * * @return $this * * @throws InvalidArgumentException in case the number of attempts is invalid */ public function setMaxAttempts(?int $attempts) { if (null !== $attempts) { $attempts = (int) $attempts; if ($attempts < 1) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('Maximum number of attempts must be a positive value.'); } } $this->attempts = $attempts; return $this; } /** * Gets the maximum number of attempts. * * Null means an unlimited number of attempts. * * @return int|null */ public function getMaxAttempts() { return $this->attempts; } /** * Sets a normalizer for the response. * * The normalizer can be a callable (a string), a closure or a class implementing __invoke. * * @return $this */ public function setNormalizer(callable $normalizer) { $this->normalizer = $normalizer; return $this; } /** * Gets the normalizer for the response. * * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. * * @return callable|null */ public function getNormalizer() { return $this->normalizer; } protected function isAssoc(array $array) { return (bool) \count(\array_filter(\array_keys($array), 'is_string')); } public function isTrimmable() : bool { return $this->trimmable; } /** * @return $this */ public function setTrimmable(bool $trimmable) : self { $this->trimmable = $trimmable; return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Tester; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\ArrayInput; /** * Eases the testing of console commands. * * @author Fabien Potencier * @author Robin Chalas */ class CommandTester { use TesterTrait; private $command; private $input; private $statusCode; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command) { $this->command = $command; } /** * Executes the command. * * Available execution options: * * * interactive: Sets the input interactive flag * * decorated: Sets the output decorated flag * * verbosity: Sets the output verbosity flag * * capture_stderr_separately: Make output of stdOut and stdErr separately available * * @param array $input An array of command arguments and options * @param array $options An array of execution options * * @return int The command exit code */ public function execute(array $input, array $options = []) { // set the command name automatically if the application requires // this argument and no command name was passed if (!isset($input['command']) && null !== ($application = $this->command->getApplication()) && $application->getDefinition()->hasArgument('command')) { $input = \array_merge(['command' => $this->command->getName()], $input); } $this->input = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\ArrayInput($input); // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN. $this->input->setStream(self::createStream($this->inputs)); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } if (!isset($options['decorated'])) { $options['decorated'] = \false; } $this->initOutput($options); return $this->statusCode = $this->command->run($this->input, $this->output); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Tester; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutput; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\StreamOutput; /** * @author Amrouche Hamza */ trait TesterTrait { /** @var StreamOutput */ private $output; private $inputs = []; private $captureStreamsIndependently = \false; /** * Gets the display returned by the last execution of the command or application. * * @return string The display */ public function getDisplay(bool $normalize = \false) { if (null === $this->output) { throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?'); } \rewind($this->output->getStream()); $display = \stream_get_contents($this->output->getStream()); if ($normalize) { $display = \str_replace(\PHP_EOL, "\n", $display); } return $display; } /** * Gets the output written to STDERR by the application. * * @param bool $normalize Whether to normalize end of lines to \n or not * * @return string */ public function getErrorOutput(bool $normalize = \false) { if (!$this->captureStreamsIndependently) { throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); } \rewind($this->output->getErrorOutput()->getStream()); $display = \stream_get_contents($this->output->getErrorOutput()->getStream()); if ($normalize) { $display = \str_replace(\PHP_EOL, "\n", $display); } return $display; } /** * Gets the input instance used by the last execution of the command or application. * * @return InputInterface The current input instance */ public function getInput() { return $this->input; } /** * Gets the output instance used by the last execution of the command or application. * * @return OutputInterface The current output instance */ public function getOutput() { return $this->output; } /** * Gets the status code returned by the last execution of the command or application. * * @return int The status code */ public function getStatusCode() { return $this->statusCode; } /** * Sets the user inputs. * * @param array $inputs An array of strings representing each input * passed to the command input stream * * @return $this */ public function setInputs(array $inputs) { $this->inputs = $inputs; return $this; } /** * Initializes the output property. * * Available options: * * * decorated: Sets the output decorated flag * * verbosity: Sets the output verbosity flag * * capture_stderr_separately: Make output of stdOut and stdErr separately available */ private function initOutput(array $options) { $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; if (!$this->captureStreamsIndependently) { $this->output = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\StreamOutput(\fopen('php://memory', 'w', \false)); if (isset($options['decorated'])) { $this->output->setDecorated($options['decorated']); } if (isset($options['verbosity'])) { $this->output->setVerbosity($options['verbosity']); } } else { $this->output = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutput(isset($options['verbosity']) ? $options['verbosity'] : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutput::VERBOSITY_NORMAL, isset($options['decorated']) ? $options['decorated'] : null); $errorOutput = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\StreamOutput(\fopen('php://memory', 'w', \false)); $errorOutput->setFormatter($this->output->getFormatter()); $errorOutput->setVerbosity($this->output->getVerbosity()); $errorOutput->setDecorated($this->output->isDecorated()); $reflectedOutput = new \ReflectionObject($this->output); $strErrProperty = $reflectedOutput->getProperty('stderr'); $strErrProperty->setAccessible(\true); $strErrProperty->setValue($this->output, $errorOutput); $reflectedParent = $reflectedOutput->getParentClass(); $streamProperty = $reflectedParent->getProperty('stream'); $streamProperty->setAccessible(\true); $streamProperty->setValue($this->output, \fopen('php://memory', 'w', \false)); } } /** * @return resource */ private static function createStream(array $inputs) { $stream = \fopen('php://memory', 'r+', \false); foreach ($inputs as $input) { \fwrite($stream, $input . \PHP_EOL); } \rewind($stream); return $stream; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Tester; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Application; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\ArrayInput; /** * Eases the testing of console applications. * * When testing an application, don't forget to disable the auto exit flag: * * $application = new Application(); * $application->setAutoExit(false); * * @author Fabien Potencier */ class ApplicationTester { use TesterTrait; private $application; private $input; private $statusCode; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application) { $this->application = $application; } /** * Executes the application. * * Available options: * * * interactive: Sets the input interactive flag * * decorated: Sets the output decorated flag * * verbosity: Sets the output verbosity flag * * capture_stderr_separately: Make output of stdOut and stdErr separately available * * @return int The command exit code */ public function run(array $input, array $options = []) { $this->input = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\ArrayInput($input); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } if ($this->inputs) { $this->input->setStream(self::createStream($this->inputs)); } $this->initOutput($options); return $this->statusCode = $this->application->run($this->input, $this->output); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * @author Grégoire Pineau */ class SingleCommandApplication extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command { private $version = 'UNKNOWN'; private $running = \false; public function setVersion(string $version) : self { $this->version = $version; return $this; } public function run(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input = null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output = null) : int { if ($this->running) { return parent::run($input, $output); } // We use the command name as the application name $application = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application($this->getName() ?: 'UNKNOWN', $this->version); // Fix the usage of the command displayed with "--help" $this->setName($_SERVER['argv'][0]); $application->add($this); $application->setDefaultCommand($this->getName(), \true); $this->running = \true; try { $ret = $application->run($input, $output); } finally { $this->running = \false; } return $ret ?? 1; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * @author Pierre du Plessis */ final class Cursor { private $output; private $input; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, $input = null) { $this->output = $output; $this->input = $input ?? (\defined('STDIN') ? \STDIN : \fopen('php://input', 'r+')); } public function moveUp(int $lines = 1) : self { $this->output->write(\sprintf("\33[%dA", $lines)); return $this; } public function moveDown(int $lines = 1) : self { $this->output->write(\sprintf("\33[%dB", $lines)); return $this; } public function moveRight(int $columns = 1) : self { $this->output->write(\sprintf("\33[%dC", $columns)); return $this; } public function moveLeft(int $columns = 1) : self { $this->output->write(\sprintf("\33[%dD", $columns)); return $this; } public function moveToColumn(int $column) : self { $this->output->write(\sprintf("\33[%dG", $column)); return $this; } public function moveToPosition(int $column, int $row) : self { $this->output->write(\sprintf("\33[%d;%dH", $row + 1, $column)); return $this; } public function savePosition() : self { $this->output->write("\0337"); return $this; } public function restorePosition() : self { $this->output->write("\338"); return $this; } public function hide() : self { $this->output->write("\33[?25l"); return $this; } public function show() : self { $this->output->write("\33[?25h\33[?0c"); return $this; } /** * Clears all the output from the current line. */ public function clearLine() : self { $this->output->write("\33[2K"); return $this; } /** * Clears all the output from the current line after the current position. */ public function clearLineAfter() : self { $this->output->write("\33[K"); return $this; } /** * Clears all the output from the cursors' current position to the end of the screen. */ public function clearOutput() : self { $this->output->write("\33[0J"); return $this; } /** * Clears the entire screen. */ public function clearScreen() : self { $this->output->write("\33[2J"); return $this; } /** * Returns the current cursor position as x,y coordinates. */ public function getCurrentPosition() : array { static $isTtySupported; if (null === $isTtySupported && \function_exists('proc_open')) { $isTtySupported = (bool) @\proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes); } if (!$isTtySupported) { return [1, 1]; } $sttyMode = \shell_exec('stty -g'); \shell_exec('stty -icanon -echo'); @\fwrite($this->input, "\33[6n"); $code = \trim(\fread($this->input, 1024)); \shell_exec(\sprintf('stty %s', $sttyMode)); \sscanf($code, "\33[%d;%dR", $row, $col); return [$col, $row]; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception; /** * @author Jérôme Tamarelle */ class LogicException extends \LogicException implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception; /** * Represents an incorrect option name typed in the console. * * @author Jérôme Tamarelle */ class InvalidOptionException extends \InvalidArgumentException implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception; /** * Represents an incorrect namespace typed in the console. * * @author Pierre du Plessis */ class NamespaceNotFoundException extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception; /** * Represents an incorrect command name typed in the console. * * @author Jérôme Tamarelle */ class CommandNotFoundException extends \InvalidArgumentException implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface { private $alternatives; /** * @param string $message Exception message to throw * @param array $alternatives List of similar defined names * @param int $code Exception code * @param \Throwable $previous Previous exception used for the exception chaining */ public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) { parent::__construct($message, $code, $previous); $this->alternatives = $alternatives; } /** * @return array A list of similar defined names */ public function getAlternatives() { return $this->alternatives; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception; /** * ExceptionInterface. * * @author Jérôme Tamarelle */ interface ExceptionInterface extends \Throwable { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception; /** * Represents failure to read input from stdin. * * @author Gabriel Ostrolucký */ class MissingInputException extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception; /** * @author Jérôme Tamarelle */ class RuntimeException extends \RuntimeException implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception; /** * @author Jérôme Tamarelle */ class InvalidArgumentException extends \InvalidArgumentException implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Style; /** * Output style helpers. * * @author Kevin Bond */ interface StyleInterface { /** * Formats a command title. */ public function title(string $message); /** * Formats a section title. */ public function section(string $message); /** * Formats a list. */ public function listing(array $elements); /** * Formats informational text. * * @param string|array $message */ public function text($message); /** * Formats a success result bar. * * @param string|array $message */ public function success($message); /** * Formats an error result bar. * * @param string|array $message */ public function error($message); /** * Formats an warning result bar. * * @param string|array $message */ public function warning($message); /** * Formats a note admonition. * * @param string|array $message */ public function note($message); /** * Formats a caution admonition. * * @param string|array $message */ public function caution($message); /** * Formats a table. */ public function table(array $headers, array $rows); /** * Asks a question. * * @return mixed */ public function ask(string $question, ?string $default = null, callable $validator = null); /** * Asks a question with the user input hidden. * * @return mixed */ public function askHidden(string $question, callable $validator = null); /** * Asks for confirmation. * * @return bool */ public function confirm(string $question, bool $default = \true); /** * Asks a choice question. * * @param string|int|null $default * * @return mixed */ public function choice(string $question, array $choices, $default = null); /** * Add newline(s). */ public function newLine(int $count = 1); /** * Starts the progress output. */ public function progressStart(int $max = 0); /** * Advances the progress output X steps. */ public function progressAdvance(int $step = 1); /** * Finishes the progress output. */ public function progressFinish(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Style; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\ProgressBar; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * Decorates output to add console style guide helpers. * * @author Kevin Bond */ abstract class OutputStyle implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Style\StyleInterface { private $output; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { $this->output = $output; } /** * {@inheritdoc} */ public function newLine(int $count = 1) { $this->output->write(\str_repeat(\PHP_EOL, $count)); } /** * @return ProgressBar */ public function createProgressBar(int $max = 0) { return new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\ProgressBar($this->output, $max); } /** * {@inheritdoc} */ public function write($messages, bool $newline = \false, int $type = self::OUTPUT_NORMAL) { $this->output->write($messages, $newline, $type); } /** * {@inheritdoc} */ public function writeln($messages, int $type = self::OUTPUT_NORMAL) { $this->output->writeln($messages, $type); } /** * {@inheritdoc} */ public function setVerbosity(int $level) { $this->output->setVerbosity($level); } /** * {@inheritdoc} */ public function getVerbosity() { return $this->output->getVerbosity(); } /** * {@inheritdoc} */ public function setDecorated(bool $decorated) { $this->output->setDecorated($decorated); } /** * {@inheritdoc} */ public function isDecorated() { return $this->output->isDecorated(); } /** * {@inheritdoc} */ public function setFormatter(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface $formatter) { $this->output->setFormatter($formatter); } /** * {@inheritdoc} */ public function getFormatter() { return $this->output->getFormatter(); } /** * {@inheritdoc} */ public function isQuiet() { return $this->output->isQuiet(); } /** * {@inheritdoc} */ public function isVerbose() { return $this->output->isVerbose(); } /** * {@inheritdoc} */ public function isVeryVerbose() { return $this->output->isVeryVerbose(); } /** * {@inheritdoc} */ public function isDebug() { return $this->output->isDebug(); } protected function getErrorOutput() { if (!$this->output instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\ConsoleOutputInterface) { return $this->output; } return $this->output->getErrorOutput(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Style; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\ProgressBar; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\SymfonyQuestionHelper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Table; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\BufferedOutput; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ConfirmationQuestion; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal; /** * Output decorator helpers for the Symfony Style Guide. * * @author Kevin Bond */ class SymfonyStyle extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Style\OutputStyle { const MAX_LINE_LENGTH = 120; private $input; private $questionHelper; private $progressBar; private $lineLength; private $bufferedOutput; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { $this->input = $input; $this->bufferedOutput = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\BufferedOutput($output->getVerbosity(), \false, clone $output->getFormatter()); // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not. $width = (new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Terminal())->getWidth() ?: self::MAX_LINE_LENGTH; $this->lineLength = \min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH); parent::__construct($output); } /** * Formats a message as a block of text. * * @param string|array $messages The message to write in the block */ public function block($messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \true) { $messages = \is_array($messages) ? \array_values($messages) : [$messages]; $this->autoPrependBlock(); $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape)); $this->newLine(); } /** * {@inheritdoc} */ public function title(string $message) { $this->autoPrependBlock(); $this->writeln([\sprintf('%s', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escapeTrailingBackslash($message)), \sprintf('%s', \str_repeat('=', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->getFormatter(), $message)))]); $this->newLine(); } /** * {@inheritdoc} */ public function section(string $message) { $this->autoPrependBlock(); $this->writeln([\sprintf('%s', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escapeTrailingBackslash($message)), \sprintf('%s', \str_repeat('-', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->getFormatter(), $message)))]); $this->newLine(); } /** * {@inheritdoc} */ public function listing(array $elements) { $this->autoPrependText(); $elements = \array_map(function ($element) { return \sprintf(' * %s', $element); }, $elements); $this->writeln($elements); $this->newLine(); } /** * {@inheritdoc} */ public function text($message) { $this->autoPrependText(); $messages = \is_array($message) ? \array_values($message) : [$message]; foreach ($messages as $message) { $this->writeln(\sprintf(' %s', $message)); } } /** * Formats a command comment. * * @param string|array $message */ public function comment($message) { $this->block($message, null, null, ' // ', \false, \false); } /** * {@inheritdoc} */ public function success($message) { $this->block($message, 'OK', 'fg=black;bg=green', ' ', \true); } /** * {@inheritdoc} */ public function error($message) { $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', \true); } /** * {@inheritdoc} */ public function warning($message) { $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', \true); } /** * {@inheritdoc} */ public function note($message) { $this->block($message, 'NOTE', 'fg=yellow', ' ! '); } /** * {@inheritdoc} */ public function caution($message) { $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', \true); } /** * {@inheritdoc} */ public function table(array $headers, array $rows) { $style = clone \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Table::getStyleDefinition('symfony-style-guide'); $style->setCellHeaderFormat('%s'); $table = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Table($this); $table->setHeaders($headers); $table->setRows($rows); $table->setStyle($style); $table->render(); $this->newLine(); } /** * Formats a horizontal table. */ public function horizontalTable(array $headers, array $rows) { $style = clone \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Table::getStyleDefinition('symfony-style-guide'); $style->setCellHeaderFormat('%s'); $table = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Table($this); $table->setHeaders($headers); $table->setRows($rows); $table->setStyle($style); $table->setHorizontal(\true); $table->render(); $this->newLine(); } /** * Formats a list of key/value horizontally. * * Each row can be one of: * * 'A title' * * ['key' => 'value'] * * new TableSeparator() * * @param string|array|TableSeparator ...$list */ public function definitionList(...$list) { $style = clone \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Table::getStyleDefinition('symfony-style-guide'); $style->setCellHeaderFormat('%s'); $table = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Table($this); $headers = []; $row = []; foreach ($list as $value) { if ($value instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableSeparator) { $headers[] = $value; $row[] = $value; continue; } if (\is_string($value)) { $headers[] = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\TableCell($value, ['colspan' => 2]); $row[] = null; continue; } if (!\is_array($value)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.'); } $headers[] = \key($value); $row[] = \current($value); } $table->setHeaders($headers); $table->setRows([$row]); $table->setHorizontal(); $table->setStyle($style); $table->render(); $this->newLine(); } /** * {@inheritdoc} */ public function ask(string $question, ?string $default = null, $validator = null) { $question = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question($question, $default); $question->setValidator($validator); return $this->askQuestion($question); } /** * {@inheritdoc} */ public function askHidden(string $question, $validator = null) { $question = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question($question); $question->setHidden(\true); $question->setValidator($validator); return $this->askQuestion($question); } /** * {@inheritdoc} */ public function confirm($question, $default = \true) { return $this->askQuestion(new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ConfirmationQuestion($question, $default)); } /** * {@inheritdoc} */ public function choice(string $question, array $choices, $default = null) { if (null !== $default) { $values = \array_flip($choices); $default = isset($values[$default]) ? $values[$default] : $default; } return $this->askQuestion(new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\ChoiceQuestion($question, $choices, $default)); } /** * {@inheritdoc} */ public function progressStart(int $max = 0) { $this->progressBar = $this->createProgressBar($max); $this->progressBar->start(); } /** * {@inheritdoc} */ public function progressAdvance(int $step = 1) { $this->getProgressBar()->advance($step); } /** * {@inheritdoc} */ public function progressFinish() { $this->getProgressBar()->finish(); $this->newLine(2); $this->progressBar = null; } /** * {@inheritdoc} */ public function createProgressBar(int $max = 0) { $progressBar = parent::createProgressBar($max); if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === \getenv('TERM_PROGRAM')) { $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 $progressBar->setProgressCharacter(''); $progressBar->setBarCharacter('▓'); // dark shade character \u2593 } return $progressBar; } /** * @return mixed */ public function askQuestion(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Question\Question $question) { if ($this->input->isInteractive()) { $this->autoPrependBlock(); } if (!$this->questionHelper) { $this->questionHelper = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\SymfonyQuestionHelper(); } $answer = $this->questionHelper->ask($this->input, $this, $question); if ($this->input->isInteractive()) { $this->newLine(); $this->bufferedOutput->write("\n"); } return $answer; } /** * {@inheritdoc} */ public function writeln($messages, int $type = self::OUTPUT_NORMAL) { if (!\is_iterable($messages)) { $messages = [$messages]; } foreach ($messages as $message) { parent::writeln($message, $type); $this->writeBuffer($message, \true, $type); } } /** * {@inheritdoc} */ public function write($messages, bool $newline = \false, int $type = self::OUTPUT_NORMAL) { if (!\is_iterable($messages)) { $messages = [$messages]; } foreach ($messages as $message) { parent::write($message, $newline, $type); $this->writeBuffer($message, $newline, $type); } } /** * {@inheritdoc} */ public function newLine(int $count = 1) { parent::newLine($count); $this->bufferedOutput->write(\str_repeat("\n", $count)); } /** * Returns a new instance which makes use of stderr if available. * * @return self */ public function getErrorStyle() { return new self($this->input, $this->getErrorOutput()); } private function getProgressBar() : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\ProgressBar { if (!$this->progressBar) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException('The ProgressBar is not started.'); } return $this->progressBar; } private function autoPrependBlock() : void { $chars = \substr(\str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); if (!isset($chars[0])) { $this->newLine(); //empty history, so we should start with a new line. return; } //Prepend new line for each non LF chars (This means no blank line was output before) $this->newLine(2 - \substr_count($chars, "\n")); } private function autoPrependText() : void { $fetched = $this->bufferedOutput->fetch(); //Prepend new line if last char isn't EOL: if ("\n" !== \substr($fetched, -1)) { $this->newLine(); } } private function writeBuffer(string $message, bool $newLine, int $type) : void { // We need to know if the two last chars are PHP_EOL // Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer $this->bufferedOutput->write(\substr($message, -4), $newLine, $type); } private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \false) : array { $indentLength = 0; $prefixLength = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); $lines = []; if (null !== $type) { $type = \sprintf('[%s] ', $type); $indentLength = \strlen($type); $lineIndentation = \str_repeat(' ', $indentLength); } // wrap and add newlines for each element foreach ($messages as $key => $message) { if ($escape) { $message = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape($message); } $lines = \array_merge($lines, \explode(\PHP_EOL, \wordwrap($message, $this->lineLength - $prefixLength - $indentLength, \PHP_EOL, \true))); if (\count($messages) > 1 && $key < \count($messages) - 1) { $lines[] = ''; } } $firstLineIndex = 0; if ($padding && $this->isDecorated()) { $firstLineIndex = 1; \array_unshift($lines, ''); $lines[] = ''; } foreach ($lines as $i => &$line) { if (null !== $type) { $line = $firstLineIndex === $i ? $type . $line : $lineIndentation . $line; } $line = $prefix . $line; $line .= \str_repeat(' ', $this->lineLength - \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlenWithoutDecoration($this->getFormatter(), $line)); if ($style) { $line = \sprintf('<%s>%s', $style, $line); } } return $lines; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\EventListener; use _HumbugBoxd02f763d3c56\Psr\Log\LoggerInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\ConsoleEvents; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleErrorEvent; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleEvent; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleTerminateEvent; use _HumbugBoxd02f763d3c56\Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * @author James Halsall * @author Robin Chalas */ class ErrorListener implements \_HumbugBoxd02f763d3c56\Symfony\Component\EventDispatcher\EventSubscriberInterface { private $logger; public function __construct(\_HumbugBoxd02f763d3c56\Psr\Log\LoggerInterface $logger = null) { $this->logger = $logger; } public function onConsoleError(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleErrorEvent $event) { if (null === $this->logger) { return; } $error = $event->getError(); if (!($inputString = $this->getInputString($event))) { $this->logger->error('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]); return; } $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]); } public function onConsoleTerminate(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleTerminateEvent $event) { if (null === $this->logger) { return; } $exitCode = $event->getExitCode(); if (0 === $exitCode) { return; } if (!($inputString = $this->getInputString($event))) { $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]); return; } $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]); } public static function getSubscribedEvents() { return [\_HumbugBoxd02f763d3c56\Symfony\Component\Console\ConsoleEvents::ERROR => ['onConsoleError', -128], \_HumbugBoxd02f763d3c56\Symfony\Component\Console\ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128]]; } private static function getInputString(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleEvent $event) : ?string { $commandName = $event->getCommand() ? $event->getCommand()->getName() : null; $input = $event->getInput(); if (\method_exists($input, '__toString')) { if ($commandName) { return \str_replace(["'{$commandName}'", "\"{$commandName}\""], $commandName, (string) $input); } return (string) $input; } return $commandName; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\DescriptorHelper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * ListCommand displays the list of all available commands for the application. * * @author Fabien Potencier */ class ListCommand extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command { /** * {@inheritdoc} */ protected function configure() { $this->setName('list')->setDefinition($this->createDefinition())->setDescription('Lists commands')->setHelp(<<<'EOF' The %command.name% command lists all commands: php %command.full_name% You can also display the commands for a specific namespace: php %command.full_name% test You can also output the information in other formats by using the --format option: php %command.full_name% --format=xml It's also possible to get raw list of commands (useful for embedding command runner): php %command.full_name% --raw EOF ); } /** * {@inheritdoc} */ public function getNativeDefinition() { return $this->createDefinition(); } /** * {@inheritdoc} */ protected function execute(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { $helper = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\DescriptorHelper(); $helper->describe($output, $this->getApplication(), ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'namespace' => $input->getArgument('namespace')]); return 0; } private function createDefinition() : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition { return new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition([new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument('namespace', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'The namespace name'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('raw', null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'To output raw command list'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('format', null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt')]); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Application; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\HelperSet; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * Base class for all commands. * * @author Fabien Potencier */ class Command { public const SUCCESS = 0; public const FAILURE = 1; /** * @var string|null The default command name */ protected static $defaultName; private $application; private $name; private $processTitle; private $aliases = []; private $definition; private $hidden = \false; private $help = ''; private $description = ''; private $ignoreValidationErrors = \false; private $applicationDefinitionMerged = \false; private $applicationDefinitionMergedWithArgs = \false; private $code; private $synopsis = []; private $usages = []; private $helperSet; /** * @return string|null The default command name or null when no default name is set */ public static function getDefaultName() { $class = static::class; $r = new \ReflectionProperty($class, 'defaultName'); return $class === $r->class ? static::$defaultName : null; } /** * @param string|null $name The name of the command; passing null means it must be set in configure() * * @throws LogicException When the command name is empty */ public function __construct(string $name = null) { $this->definition = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition(); if (null !== $name || null !== ($name = static::getDefaultName())) { $this->setName($name); } $this->configure(); } /** * Ignores validation errors. * * This is mainly useful for the help command. */ public function ignoreValidationErrors() { $this->ignoreValidationErrors = \true; } public function setApplication(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application = null) { $this->application = $application; if ($application) { $this->setHelperSet($application->getHelperSet()); } else { $this->helperSet = null; } } public function setHelperSet(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\HelperSet $helperSet) { $this->helperSet = $helperSet; } /** * Gets the helper set. * * @return HelperSet|null A HelperSet instance */ public function getHelperSet() { return $this->helperSet; } /** * Gets the application instance for this command. * * @return Application|null An Application instance */ public function getApplication() { return $this->application; } /** * Checks whether the command is enabled or not in the current environment. * * Override this to check for x or y and return false if the command can not * run properly under the current conditions. * * @return bool */ public function isEnabled() { return \true; } /** * Configures the current command. */ protected function configure() { } /** * Executes the current command. * * This method is not abstract because you can use this class * as a concrete class. In this case, instead of defining the * execute() method, you set the code to execute by passing * a Closure to the setCode() method. * * @return int 0 if everything went fine, or an exit code * * @throws LogicException When this abstract method is not implemented * * @see setCode() */ protected function execute(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('You must override the execute() method in the concrete command class.'); } /** * Interacts with the user. * * This method is executed before the InputDefinition is validated. * This means that this is the only place where the command can * interactively ask for values of missing required arguments. */ protected function interact(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { } /** * Initializes the command after the input has been bound and before the input * is validated. * * This is mainly useful when a lot of commands extends one main command * where some things need to be initialized based on the input arguments and options. * * @see InputInterface::bind() * @see InputInterface::validate() */ protected function initialize(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { } /** * Runs the command. * * The code to execute is either defined directly with the * setCode() method or by overriding the execute() method * in a sub-class. * * @return int The command exit code * * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}. * * @see setCode() * @see execute() */ public function run(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { // force the creation of the synopsis before the merge with the app definition $this->getSynopsis(\true); $this->getSynopsis(\false); // add the application arguments and options $this->mergeApplicationDefinition(); // bind the input against the command specific arguments/options try { $input->bind($this->definition); } catch (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\ExceptionInterface $e) { if (!$this->ignoreValidationErrors) { throw $e; } } $this->initialize($input, $output); if (null !== $this->processTitle) { if (\function_exists('cli_set_process_title')) { if (!@\cli_set_process_title($this->processTitle)) { if ('Darwin' === \PHP_OS) { $output->writeln('Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE); } else { \cli_set_process_title($this->processTitle); } } } elseif (\function_exists('_HumbugBoxd02f763d3c56\\setproctitle')) { setproctitle($this->processTitle); } elseif (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) { $output->writeln('Install the proctitle PECL to be able to change the process title.'); } } if ($input->isInteractive()) { $this->interact($input, $output); } // The command name argument is often omitted when a command is executed directly with its run() method. // It would fail the validation if we didn't make sure the command argument is present, // since it's required by the application. if ($input->hasArgument('command') && null === $input->getArgument('command')) { $input->setArgument('command', $this->getName()); } $input->validate(); if ($this->code) { $statusCode = ($this->code)($input, $output); } else { $statusCode = $this->execute($input, $output); if (!\is_int($statusCode)) { throw new \TypeError(\sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, \get_debug_type($statusCode))); } } return \is_numeric($statusCode) ? (int) $statusCode : 0; } /** * Sets the code to execute when running this command. * * If this method is used, it overrides the code defined * in the execute() method. * * @param callable $code A callable(InputInterface $input, OutputInterface $output) * * @return $this * * @throws InvalidArgumentException * * @see execute() */ public function setCode(callable $code) { if ($code instanceof \Closure) { $r = new \ReflectionFunction($code); if (null === $r->getClosureThis()) { $code = \Closure::bind($code, $this); } } $this->code = $code; return $this; } /** * Merges the application definition with the command definition. * * This method is not part of public API and should not be used directly. * * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments */ public function mergeApplicationDefinition(bool $mergeArgs = \true) { if (null === $this->application || \true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs)) { return; } $this->definition->addOptions($this->application->getDefinition()->getOptions()); $this->applicationDefinitionMerged = \true; if ($mergeArgs) { $currentArguments = $this->definition->getArguments(); $this->definition->setArguments($this->application->getDefinition()->getArguments()); $this->definition->addArguments($currentArguments); $this->applicationDefinitionMergedWithArgs = \true; } } /** * Sets an array of argument and option instances. * * @param array|InputDefinition $definition An array of argument and option instances or a definition instance * * @return $this */ public function setDefinition($definition) { if ($definition instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition) { $this->definition = $definition; } else { $this->definition->setDefinition($definition); } $this->applicationDefinitionMerged = \false; return $this; } /** * Gets the InputDefinition attached to this Command. * * @return InputDefinition An InputDefinition instance */ public function getDefinition() { if (null === $this->definition) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException(\sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class)); } return $this->definition; } /** * Gets the InputDefinition to be used to create representations of this Command. * * Can be overridden to provide the original command representation when it would otherwise * be changed by merging with the application InputDefinition. * * This method is not part of public API and should not be used directly. * * @return InputDefinition An InputDefinition instance */ public function getNativeDefinition() { return $this->getDefinition(); } /** * Adds an argument. * * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL * @param string|string[]|null $default The default value (for InputArgument::OPTIONAL mode only) * * @throws InvalidArgumentException When argument mode is not valid * * @return $this */ public function addArgument(string $name, int $mode = null, string $description = '', $default = null) { $this->definition->addArgument(new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument($name, $mode, $description, $default)); return $this; } /** * Adds an option. * * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants * @param string|string[]|int|bool|null $default The default value (must be null for InputOption::VALUE_NONE) * * @throws InvalidArgumentException If option mode is invalid or incompatible * * @return $this */ public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) { $this->definition->addOption(new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption($name, $shortcut, $mode, $description, $default)); return $this; } /** * Sets the name of the command. * * This method can set both the namespace and the name if * you separate them by a colon (:) * * $command->setName('foo:bar'); * * @return $this * * @throws InvalidArgumentException When the name is invalid */ public function setName(string $name) { $this->validateName($name); $this->name = $name; return $this; } /** * Sets the process title of the command. * * This feature should be used only when creating a long process command, * like a daemon. * * @return $this */ public function setProcessTitle(string $title) { $this->processTitle = $title; return $this; } /** * Returns the command name. * * @return string|null */ public function getName() { return $this->name; } /** * @param bool $hidden Whether or not the command should be hidden from the list of commands * The default value will be true in Symfony 6.0 * * @return Command The current instance * * @final since Symfony 5.1 */ public function setHidden(bool $hidden) { $this->hidden = $hidden; return $this; } /** * @return bool whether the command should be publicly shown or not */ public function isHidden() { return $this->hidden; } /** * Sets the description for the command. * * @return $this */ public function setDescription(string $description) { $this->description = $description; return $this; } /** * Returns the description for the command. * * @return string The description for the command */ public function getDescription() { return $this->description; } /** * Sets the help for the command. * * @return $this */ public function setHelp(string $help) { $this->help = $help; return $this; } /** * Returns the help for the command. * * @return string The help for the command */ public function getHelp() { return $this->help; } /** * Returns the processed help for the command replacing the %command.name% and * %command.full_name% patterns with the real values dynamically. * * @return string The processed help for the command */ public function getProcessedHelp() { $name = $this->name; $isSingleCommand = $this->application && $this->application->isSingleCommand(); $placeholders = ['%command.name%', '%command.full_name%']; $replacements = [$name, $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'] . ' ' . $name]; return \str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription()); } /** * Sets the aliases for the command. * * @param string[] $aliases An array of aliases for the command * * @return $this * * @throws InvalidArgumentException When an alias is invalid */ public function setAliases(iterable $aliases) { foreach ($aliases as $alias) { $this->validateName($alias); } $this->aliases = $aliases; return $this; } /** * Returns the aliases for the command. * * @return array An array of aliases for the command */ public function getAliases() { return $this->aliases; } /** * Returns the synopsis for the command. * * @param bool $short Whether to show the short version of the synopsis (with options folded) or not * * @return string The synopsis */ public function getSynopsis(bool $short = \false) { $key = $short ? 'short' : 'long'; if (!isset($this->synopsis[$key])) { $this->synopsis[$key] = \trim(\sprintf('%s %s', $this->name, $this->definition->getSynopsis($short))); } return $this->synopsis[$key]; } /** * Add a command usage example, it'll be prefixed with the command name. * * @return $this */ public function addUsage(string $usage) { if (0 !== \strpos($usage, $this->name)) { $usage = \sprintf('%s %s', $this->name, $usage); } $this->usages[] = $usage; return $this; } /** * Returns alternative usages of the command. * * @return array */ public function getUsages() { return $this->usages; } /** * Gets a helper instance by name. * * @return mixed The helper value * * @throws LogicException if no HelperSet is defined * @throws InvalidArgumentException if the helper is not defined */ public function getHelper(string $name) { if (null === $this->helperSet) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException(\sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name)); } return $this->helperSet->get($name); } /** * Validates a command name. * * It must be non-empty and parts can optionally be separated by ":". * * @throws InvalidArgumentException When the name is invalid */ private function validateName(string $name) { if (!\preg_match('/^[^\\:]++(\\:[^\\:]++)*$/', $name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Command name "%s" is invalid.', $name)); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; use _HumbugBoxd02f763d3c56\Symfony\Component\Lock\Lock; use _HumbugBoxd02f763d3c56\Symfony\Component\Lock\LockFactory; use _HumbugBoxd02f763d3c56\Symfony\Component\Lock\Store\FlockStore; use _HumbugBoxd02f763d3c56\Symfony\Component\Lock\Store\SemaphoreStore; /** * Basic lock feature for commands. * * @author Geoffrey Brier */ trait LockableTrait { /** @var Lock */ private $lock; /** * Locks a command. */ private function lock(string $name = null, bool $blocking = \false) : bool { if (!\class_exists(\_HumbugBoxd02f763d3c56\Symfony\Component\Lock\Store\SemaphoreStore::class)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('To enable the locking feature you must install the symfony/lock component.'); } if (null !== $this->lock) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('A lock is already in place.'); } if (\_HumbugBoxd02f763d3c56\Symfony\Component\Lock\Store\SemaphoreStore::isSupported()) { $store = new \_HumbugBoxd02f763d3c56\Symfony\Component\Lock\Store\SemaphoreStore(); } else { $store = new \_HumbugBoxd02f763d3c56\Symfony\Component\Lock\Store\FlockStore(); } $this->lock = (new \_HumbugBoxd02f763d3c56\Symfony\Component\Lock\LockFactory($store))->createLock($name ?: $this->getName()); if (!$this->lock->acquire($blocking)) { $this->lock = null; return \false; } return \true; } /** * Releases the command lock if there is one. */ private function release() { if ($this->lock) { $this->lock->release(); $this->lock = null; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\DescriptorHelper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * HelpCommand displays the help for a given command. * * @author Fabien Potencier */ class HelpCommand extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command { private $command; /** * {@inheritdoc} */ protected function configure() { $this->ignoreValidationErrors(); $this->setName('help')->setDefinition([new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument('command_name', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument::OPTIONAL, 'The command name', 'help'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('format', null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('raw', null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_NONE, 'To output raw command help')])->setDescription('Displays help for a command')->setHelp(<<<'EOF' The %command.name% command displays help for a given command: php %command.full_name% list You can also output the help in other formats by using the --format option: php %command.full_name% --format=xml list To display the list of available commands, please use the list command. EOF ); } public function setCommand(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command) { $this->command = $command; } /** * {@inheritdoc} */ protected function execute(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { if (null === $this->command) { $this->command = $this->getApplication()->find($input->getArgument('command_name')); } $helper = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\DescriptorHelper(); $helper->describe($output, $this->command, ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw')]); $this->command = null; return 0; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\DependencyInjection; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\CommandLoader\ContainerCommandLoader; use _HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use _HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\ContainerBuilder; use _HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\TypedReference; /** * Registers console commands. * * @author Grégoire Pineau */ class AddConsoleCommandPass implements \_HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface { private $commandLoaderServiceId; private $commandTag; private $noPreloadTag; public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command', string $noPreloadTag = 'container.no_preload') { $this->commandLoaderServiceId = $commandLoaderServiceId; $this->commandTag = $commandTag; $this->noPreloadTag = $noPreloadTag; } public function process(\_HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\ContainerBuilder $container) { $commandServices = $container->findTaggedServiceIds($this->commandTag, \true); $lazyCommandMap = []; $lazyCommandRefs = []; $serviceIds = []; foreach ($commandServices as $id => $tags) { $definition = $container->getDefinition($id); $definition->addTag($this->noPreloadTag); $class = $container->getParameterBag()->resolveValue($definition->getClass()); if (isset($tags[0]['command'])) { $commandName = $tags[0]['command']; } else { if (!($r = $container->getReflectionClass($class))) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } if (!$r->isSubclassOf(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command::class)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command::class)); } $commandName = $class::getDefaultName(); } if (null === $commandName) { if (!$definition->isPublic() || $definition->isPrivate()) { $commandId = 'console.command.public_alias.' . $id; $container->setAlias($commandId, $id)->setPublic(\true); $id = $commandId; } $serviceIds[] = $id; continue; } unset($tags[0]); $lazyCommandMap[$commandName] = $id; $lazyCommandRefs[$id] = new \_HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\TypedReference($id, $class); $aliases = []; foreach ($tags as $tag) { if (isset($tag['command'])) { $aliases[] = $tag['command']; $lazyCommandMap[$tag['command']] = $id; } } $definition->addMethodCall('setName', [$commandName]); if ($aliases) { $definition->addMethodCall('setAliases', [$aliases]); } } $container->register($this->commandLoaderServiceId, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\CommandLoader\ContainerCommandLoader::class)->setPublic(\true)->addTag($this->noPreloadTag)->setArguments([\_HumbugBoxd02f763d3c56\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]); $container->setParameter('console.command.ids', $serviceIds); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console; class Terminal { private static $width; private static $height; private static $stty; /** * Gets the terminal width. * * @return int */ public function getWidth() { $width = \getenv('COLUMNS'); if (\false !== $width) { return (int) \trim($width); } if (null === self::$width) { self::initDimensions(); } return self::$width ?: 80; } /** * Gets the terminal height. * * @return int */ public function getHeight() { $height = \getenv('LINES'); if (\false !== $height) { return (int) \trim($height); } if (null === self::$height) { self::initDimensions(); } return self::$height ?: 50; } /** * @internal * * @return bool */ public static function hasSttyAvailable() { if (null !== self::$stty) { return self::$stty; } // skip check if exec function is disabled if (!\function_exists('exec')) { return \false; } \exec('stty 2>&1', $output, $exitcode); return self::$stty = 0 === $exitcode; } private static function initDimensions() { if ('\\' === \DIRECTORY_SEPARATOR) { if (\preg_match('/^(\\d+)x(\\d+)(?: \\((\\d+)x(\\d+)\\))?$/', \trim(\getenv('ANSICON')), $matches)) { // extract [w, H] from "wxh (WxH)" // or [w, h] from "wxh" self::$width = (int) $matches[1]; self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash) // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT self::initDimensionsUsingStty(); } elseif (null !== ($dimensions = self::getConsoleMode())) { // extract [w, h] from "wxh" self::$width = (int) $dimensions[0]; self::$height = (int) $dimensions[1]; } } else { self::initDimensionsUsingStty(); } } /** * Returns whether STDOUT has vt100 support (some Windows 10+ configurations). */ private static function hasVt100Support() : bool { return \function_exists('sapi_windows_vt100_support') && \sapi_windows_vt100_support(\fopen('php://stdout', 'w')); } /** * Initializes dimensions using the output of an stty columns line. */ private static function initDimensionsUsingStty() { if ($sttyString = self::getSttyColumns()) { if (\preg_match('/rows.(\\d+);.columns.(\\d+);/i', $sttyString, $matches)) { // extract [w, h] from "rows h; columns w;" self::$width = (int) $matches[2]; self::$height = (int) $matches[1]; } elseif (\preg_match('/;.(\\d+).rows;.(\\d+).columns/i', $sttyString, $matches)) { // extract [w, h] from "; h rows; w columns" self::$width = (int) $matches[2]; self::$height = (int) $matches[1]; } } } /** * Runs and parses mode CON if it's available, suppressing any error output. * * @return int[]|null An array composed of the width and the height or null if it could not be parsed */ private static function getConsoleMode() : ?array { $info = self::readFromProcess('mode CON'); if (null === $info || !\preg_match('/--------+\\r?\\n.+?(\\d+)\\r?\\n.+?(\\d+)\\r?\\n/', $info, $matches)) { return null; } return [(int) $matches[2], (int) $matches[1]]; } /** * Runs and parses stty -a if it's available, suppressing any error output. */ private static function getSttyColumns() : ?string { return self::readFromProcess('stty -a | grep columns'); } private static function readFromProcess(string $command) : ?string { if (!\function_exists('proc_open')) { return null; } $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']]; $process = \proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => \true]); if (!\is_resource($process)) { return null; } $info = \stream_get_contents($pipes[1]); \fclose($pipes[1]); \fclose($pipes[2]); \proc_close($process); return $info; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console; /** * Contains all events dispatched by an Application. * * @author Francesco Levorato */ final class ConsoleEvents { /** * The COMMAND event allows you to attach listeners before any command is * executed by the console. It also allows you to modify the command, input and output * before they are handled to the command. * * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent") */ const COMMAND = 'console.command'; /** * The TERMINATE event allows you to attach listeners after a command is * executed by the console. * * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent") */ const TERMINATE = 'console.terminate'; /** * The ERROR event occurs when an uncaught exception or error appears. * * This event allows you to deal with the exception/error or * to modify the thrown exception. * * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent") */ const ERROR = 'console.error'; } Copyright (c) 2004-2020 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter; /** * Formatter style interface for defining styles. * * @author Konstantin Kudryashov */ interface OutputFormatterStyleInterface { /** * Sets style foreground color. */ public function setForeground(string $color = null); /** * Sets style background color. */ public function setBackground(string $color = null); /** * Sets some specific style option. */ public function setOption(string $option); /** * Unsets some specific style option. */ public function unsetOption(string $option); /** * Sets multiple style options at once. */ public function setOptions(array $options); /** * Applies the style to a given text. * * @return string */ public function apply(string $text); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter; /** * @author Tien Xuan Vo */ final class NullOutputFormatter implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface { private $style; /** * {@inheritdoc} */ public function format(?string $message) : void { // do nothing } /** * {@inheritdoc} */ public function getStyle(string $name) : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface { if ($this->style) { return $this->style; } // to comply with the interface we must return a OutputFormatterStyleInterface return $this->style = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\NullOutputFormatterStyle(); } /** * {@inheritdoc} */ public function hasStyle(string $name) : bool { return \false; } /** * {@inheritdoc} */ public function isDecorated() : bool { return \false; } /** * {@inheritdoc} */ public function setDecorated(bool $decorated) : void { // do nothing } /** * {@inheritdoc} */ public function setStyle(string $name, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $style) : void { // do nothing } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter; /** * @author Tien Xuan Vo */ final class NullOutputFormatterStyle implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface { /** * {@inheritdoc} */ public function apply(string $text) : string { return $text; } /** * {@inheritdoc} */ public function setBackground(string $color = null) : void { // do nothing } /** * {@inheritdoc} */ public function setForeground(string $color = null) : void { // do nothing } /** * {@inheritdoc} */ public function setOption(string $option) : void { // do nothing } /** * {@inheritdoc} */ public function setOptions(array $options) : void { // do nothing } /** * {@inheritdoc} */ public function unsetOption(string $option) : void { // do nothing } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; /** * Formatter style class for defining styles. * * @author Konstantin Kudryashov */ class OutputFormatterStyle implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface { private static $availableForegroundColors = ['black' => ['set' => 30, 'unset' => 39], 'red' => ['set' => 31, 'unset' => 39], 'green' => ['set' => 32, 'unset' => 39], 'yellow' => ['set' => 33, 'unset' => 39], 'blue' => ['set' => 34, 'unset' => 39], 'magenta' => ['set' => 35, 'unset' => 39], 'cyan' => ['set' => 36, 'unset' => 39], 'white' => ['set' => 37, 'unset' => 39], 'default' => ['set' => 39, 'unset' => 39]]; private static $availableBackgroundColors = ['black' => ['set' => 40, 'unset' => 49], 'red' => ['set' => 41, 'unset' => 49], 'green' => ['set' => 42, 'unset' => 49], 'yellow' => ['set' => 43, 'unset' => 49], 'blue' => ['set' => 44, 'unset' => 49], 'magenta' => ['set' => 45, 'unset' => 49], 'cyan' => ['set' => 46, 'unset' => 49], 'white' => ['set' => 47, 'unset' => 49], 'default' => ['set' => 49, 'unset' => 49]]; private static $availableOptions = ['bold' => ['set' => 1, 'unset' => 22], 'underscore' => ['set' => 4, 'unset' => 24], 'blink' => ['set' => 5, 'unset' => 25], 'reverse' => ['set' => 7, 'unset' => 27], 'conceal' => ['set' => 8, 'unset' => 28]]; private $foreground; private $background; private $href; private $options = []; private $handlesHrefGracefully; /** * Initializes output formatter style. * * @param string|null $foreground The style foreground color name * @param string|null $background The style background color name */ public function __construct(string $foreground = null, string $background = null, array $options = []) { if (null !== $foreground) { $this->setForeground($foreground); } if (null !== $background) { $this->setBackground($background); } if (\count($options)) { $this->setOptions($options); } } /** * {@inheritdoc} */ public function setForeground(string $color = null) { if (null === $color) { $this->foreground = null; return; } if (!isset(static::$availableForegroundColors[$color])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Invalid foreground color specified: "%s". Expected one of (%s).', $color, \implode(', ', \array_keys(static::$availableForegroundColors)))); } $this->foreground = static::$availableForegroundColors[$color]; } /** * {@inheritdoc} */ public function setBackground(string $color = null) { if (null === $color) { $this->background = null; return; } if (!isset(static::$availableBackgroundColors[$color])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Invalid background color specified: "%s". Expected one of (%s).', $color, \implode(', ', \array_keys(static::$availableBackgroundColors)))); } $this->background = static::$availableBackgroundColors[$color]; } public function setHref(string $url) : void { $this->href = $url; } /** * {@inheritdoc} */ public function setOption(string $option) { if (!isset(static::$availableOptions[$option])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, \implode(', ', \array_keys(static::$availableOptions)))); } if (!\in_array(static::$availableOptions[$option], $this->options)) { $this->options[] = static::$availableOptions[$option]; } } /** * {@inheritdoc} */ public function unsetOption(string $option) { if (!isset(static::$availableOptions[$option])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, \implode(', ', \array_keys(static::$availableOptions)))); } $pos = \array_search(static::$availableOptions[$option], $this->options); if (\false !== $pos) { unset($this->options[$pos]); } } /** * {@inheritdoc} */ public function setOptions(array $options) { $this->options = []; foreach ($options as $option) { $this->setOption($option); } } /** * {@inheritdoc} */ public function apply(string $text) { $setCodes = []; $unsetCodes = []; if (null === $this->handlesHrefGracefully) { $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== \getenv('TERMINAL_EMULATOR') && !\getenv('KONSOLE_VERSION'); } if (null !== $this->foreground) { $setCodes[] = $this->foreground['set']; $unsetCodes[] = $this->foreground['unset']; } if (null !== $this->background) { $setCodes[] = $this->background['set']; $unsetCodes[] = $this->background['unset']; } foreach ($this->options as $option) { $setCodes[] = $option['set']; $unsetCodes[] = $option['unset']; } if (null !== $this->href && $this->handlesHrefGracefully) { $text = "\33]8;;{$this->href}\33\\{$text}\33]8;;\33\\"; } if (0 === \count($setCodes)) { return $text; } return \sprintf("\33[%sm%s\33[%sm", \implode(';', $setCodes), $text, \implode(';', $unsetCodes)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter; /** * Formatter interface for console output. * * @author Konstantin Kudryashov */ interface OutputFormatterInterface { /** * Sets the decorated flag. */ public function setDecorated(bool $decorated); /** * Gets the decorated flag. * * @return bool true if the output will decorate messages, false otherwise */ public function isDecorated(); /** * Sets a new style. */ public function setStyle(string $name, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $style); /** * Checks if output formatter has style with specified name. * * @return bool */ public function hasStyle(string $name); /** * Gets style options from style with specified name. * * @return OutputFormatterStyleInterface * * @throws \InvalidArgumentException When style isn't defined */ public function getStyle(string $name); /** * Formats a message according to the given styles. */ public function format(?string $message); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter; /** * Formatter interface for console output that supports word wrapping. * * @author Roland Franssen */ interface WrappableOutputFormatterInterface extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterInterface { /** * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping). */ public function formatAndWrap(?string $message, int $width); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; /** * Formatter class for console output. * * @author Konstantin Kudryashov * @author Roland Franssen */ class OutputFormatter implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface { private $decorated; private $styles = []; private $styleStack; /** * Escapes "<" special char in given text. * * @return string Escaped text */ public static function escape(string $text) { $text = \preg_replace('/([^\\\\]?) FormatterStyle" instances */ public function __construct(bool $decorated = \false, array $styles = []) { $this->decorated = $decorated; $this->setStyle('error', new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyle('white', 'red')); $this->setStyle('info', new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyle('green')); $this->setStyle('comment', new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyle('yellow')); $this->setStyle('question', new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyle('black', 'cyan')); foreach ($styles as $name => $style) { $this->setStyle($name, $style); } $this->styleStack = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleStack(); } /** * {@inheritdoc} */ public function setDecorated(bool $decorated) { $this->decorated = $decorated; } /** * {@inheritdoc} */ public function isDecorated() { return $this->decorated; } /** * {@inheritdoc} */ public function setStyle(string $name, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $style) { $this->styles[\strtolower($name)] = $style; } /** * {@inheritdoc} */ public function hasStyle(string $name) { return isset($this->styles[\strtolower($name)]); } /** * {@inheritdoc} */ public function getStyle(string $name) { if (!$this->hasStyle($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Undefined style: "%s".', $name)); } return $this->styles[\strtolower($name)]; } /** * {@inheritdoc} */ public function format(?string $message) { return $this->formatAndWrap($message, 0); } /** * {@inheritdoc} */ public function formatAndWrap(?string $message, int $width) { $offset = 0; $output = ''; $tagRegex = '[a-z][^<>]*+'; $currentLineLength = 0; \preg_match_all("#<(({$tagRegex}) | /({$tagRegex})?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; $text = $match[0]; if (0 != $pos && '\\' == $message[$pos - 1]) { continue; } // add the text up to the next tag $output .= $this->applyCurrentStyle(\substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); $offset = $pos + \strlen($text); // opening tag? if ($open = '/' != $text[1]) { $tag = $matches[1][$i][0]; } else { $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : ''; } if (!$open && !$tag) { // $this->styleStack->pop(); } elseif (null === ($style = $this->createStyleFromString($tag))) { $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength); } elseif ($open) { $this->styleStack->push($style); } else { $this->styleStack->pop($style); } } $output .= $this->applyCurrentStyle(\substr($message, $offset), $output, $width, $currentLineLength); if (\false !== \strpos($output, "\0")) { return \strtr($output, ["\0" => '\\', '\\<' => '<']); } return \str_replace('\\<', '<', $output); } /** * @return OutputFormatterStyleStack */ public function getStyleStack() { return $this->styleStack; } /** * Tries to create new style instance from string. */ private function createStyleFromString(string $string) : ?\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface { if (isset($this->styles[$string])) { return $this->styles[$string]; } if (!\preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) { return null; } $style = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyle(); foreach ($matches as $match) { \array_shift($match); $match[0] = \strtolower($match[0]); if ('fg' == $match[0]) { $style->setForeground(\strtolower($match[1])); } elseif ('bg' == $match[0]) { $style->setBackground(\strtolower($match[1])); } elseif ('href' === $match[0]) { $style->setHref($match[1]); } elseif ('options' === $match[0]) { \preg_match_all('([^,;]+)', \strtolower($match[1]), $options); $options = \array_shift($options); foreach ($options as $option) { $style->setOption($option); } } else { return null; } } return $style; } /** * Applies current style from stack to text, if must be applied. */ private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength) : string { if ('' === $text) { return ''; } if (!$width) { return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text; } if (!$currentLineLength && '' !== $current) { $text = \ltrim($text); } if ($currentLineLength) { $prefix = \substr($text, 0, $i = $width - $currentLineLength) . "\n"; $text = \substr($text, $i); } else { $prefix = ''; } \preg_match('~(\\n)$~', $text, $matches); $text = $prefix . \preg_replace('~([^\\n]{' . $width . '})\\ *~', "\$1\n", $text); $text = \rtrim($text, "\n") . ($matches[1] ?? ''); if (!$currentLineLength && '' !== $current && "\n" !== \substr($current, -1)) { $text = "\n" . $text; } $lines = \explode("\n", $text); foreach ($lines as $line) { $currentLineLength += \strlen($line); if ($width <= $currentLineLength) { $currentLineLength = 0; } } if ($this->isDecorated()) { foreach ($lines as $i => $line) { $lines[$i] = $this->styleStack->getCurrent()->apply($line); } } return \implode("\n", $lines); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Contracts\Service\ResetInterface; /** * @author Jean-François Simon */ class OutputFormatterStyleStack implements \_HumbugBoxd02f763d3c56\Symfony\Contracts\Service\ResetInterface { /** * @var OutputFormatterStyleInterface[] */ private $styles; private $emptyStyle; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $emptyStyle = null) { $this->emptyStyle = $emptyStyle ?: new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyle(); $this->reset(); } /** * Resets stack (ie. empty internal arrays). */ public function reset() { $this->styles = []; } /** * Pushes a style in the stack. */ public function push(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $style) { $this->styles[] = $style; } /** * Pops a style from the stack. * * @return OutputFormatterStyleInterface * * @throws InvalidArgumentException When style tags incorrectly nested */ public function pop(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $style = null) { if (empty($this->styles)) { return $this->emptyStyle; } if (null === $style) { return \array_pop($this->styles); } foreach (\array_reverse($this->styles, \true) as $index => $stackedStyle) { if ($style->apply('') === $stackedStyle->apply('')) { $this->styles = \array_slice($this->styles, 0, $index); return $stackedStyle; } } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('Incorrectly nested style tag found.'); } /** * Computes current style with stacks top codes. * * @return OutputFormatterStyle */ public function getCurrent() { if (empty($this->styles)) { return $this->emptyStyle; } return $this->styles[\count($this->styles) - 1]; } /** * @return $this */ public function setEmptyStyle(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatterStyleInterface $emptyStyle) { $this->emptyStyle = $emptyStyle; return $this; } /** * @return OutputFormatterStyleInterface */ public function getEmptyStyle() { return $this->emptyStyle; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Application; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption; /** * JSON descriptor. * * @author Jean-François Simon * * @internal */ class JsonDescriptor extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument $argument, array $options = []) { $this->writeData($this->getInputArgumentData($argument), $options); } /** * {@inheritdoc} */ protected function describeInputOption(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption $option, array $options = []) { $this->writeData($this->getInputOptionData($option), $options); } /** * {@inheritdoc} */ protected function describeInputDefinition(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition, array $options = []) { $this->writeData($this->getInputDefinitionData($definition), $options); } /** * {@inheritdoc} */ protected function describeCommand(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command, array $options = []) { $this->writeData($this->getCommandData($command), $options); } /** * {@inheritdoc} */ protected function describeApplication(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application, array $options = []) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\ApplicationDescription($application, $describedNamespace, \true); $commands = []; foreach ($description->getCommands() as $command) { $commands[] = $this->getCommandData($command); } $data = []; if ('UNKNOWN' !== $application->getName()) { $data['application']['name'] = $application->getName(); if ('UNKNOWN' !== $application->getVersion()) { $data['application']['version'] = $application->getVersion(); } } $data['commands'] = $commands; if ($describedNamespace) { $data['namespace'] = $describedNamespace; } else { $data['namespaces'] = \array_values($description->getNamespaces()); } $this->writeData($data, $options); } /** * Writes data as json. */ private function writeData(array $data, array $options) { $flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0; $this->write(\json_encode($data, $flags)); } private function getInputArgumentData(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument $argument) : array { return ['name' => $argument->getName(), 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => \preg_replace('/\\s*[\\r\\n]\\s*/', ' ', $argument->getDescription()), 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault()]; } private function getInputOptionData(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption $option) : array { return ['name' => '--' . $option->getName(), 'shortcut' => $option->getShortcut() ? '-' . \str_replace('|', '|-', $option->getShortcut()) : '', 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => \preg_replace('/\\s*[\\r\\n]\\s*/', ' ', $option->getDescription()), 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault()]; } private function getInputDefinitionData(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition) : array { $inputArguments = []; foreach ($definition->getArguments() as $name => $argument) { $inputArguments[$name] = $this->getInputArgumentData($argument); } $inputOptions = []; foreach ($definition->getOptions() as $name => $option) { $inputOptions[$name] = $this->getInputOptionData($option); } return ['arguments' => $inputArguments, 'options' => $inputOptions]; } private function getCommandData(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command) : array { $command->getSynopsis(); $command->mergeApplicationDefinition(\false); return ['name' => $command->getName(), 'usage' => \array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), 'description' => $command->getDescription(), 'help' => $command->getProcessedHelp(), 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), 'hidden' => $command->isHidden()]; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * Descriptor interface. * * @author Jean-François Simon */ interface DescriptorInterface { /** * Describes an object if supported. * * @param object $object */ public function describe(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, $object, array $options = []); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Application; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException; /** * @author Jean-François Simon * * @internal */ class ApplicationDescription { const GLOBAL_NAMESPACE = '_global'; private $application; private $namespace; private $showHidden; /** * @var array */ private $namespaces; /** * @var Command[] */ private $commands; /** * @var Command[] */ private $aliases; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application, string $namespace = null, bool $showHidden = \false) { $this->application = $application; $this->namespace = $namespace; $this->showHidden = $showHidden; } public function getNamespaces() : array { if (null === $this->namespaces) { $this->inspectApplication(); } return $this->namespaces; } /** * @return Command[] */ public function getCommands() : array { if (null === $this->commands) { $this->inspectApplication(); } return $this->commands; } /** * @throws CommandNotFoundException */ public function getCommand(string $name) : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command { if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name)); } return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; } private function inspectApplication() { $this->commands = []; $this->namespaces = []; $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); foreach ($this->sortCommands($all) as $namespace => $commands) { $names = []; /** @var Command $command */ foreach ($commands as $name => $command) { if (!$command->getName() || !$this->showHidden && $command->isHidden()) { continue; } if ($command->getName() === $name) { $this->commands[$name] = $command; } else { $this->aliases[$name] = $command; } $names[] = $name; } $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names]; } } private function sortCommands(array $commands) : array { $namespacedCommands = []; $globalCommands = []; $sortedCommands = []; foreach ($commands as $name => $command) { $key = $this->application->extractNamespace($name, 1); if (\in_array($key, ['', self::GLOBAL_NAMESPACE], \true)) { $globalCommands[$name] = $command; } else { $namespacedCommands[$key][$name] = $command; } } if ($globalCommands) { \ksort($globalCommands); $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands; } if ($namespacedCommands) { \ksort($namespacedCommands); foreach ($namespacedCommands as $key => $commandsSet) { \ksort($commandsSet); $sortedCommands[$key] = $commandsSet; } } return $sortedCommands; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Application; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption; /** * XML descriptor. * * @author Jean-François Simon * * @internal */ class XmlDescriptor extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\Descriptor { public function getInputDefinitionDocument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition) : \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($definitionXML = $dom->createElement('definition')); $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); foreach ($definition->getArguments() as $argument) { $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); } $definitionXML->appendChild($optionsXML = $dom->createElement('options')); foreach ($definition->getOptions() as $option) { $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); } return $dom; } public function getCommandDocument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command) : \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($commandXML = $dom->createElement('command')); $command->getSynopsis(); $command->mergeApplicationDefinition(\false); $commandXML->setAttribute('id', $command->getName()); $commandXML->setAttribute('name', $command->getName()); $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0); $commandXML->appendChild($usagesXML = $dom->createElement('usages')); foreach (\array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) { $usagesXML->appendChild($dom->createElement('usage', $usage)); } $commandXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode(\str_replace("\n", "\n ", $command->getDescription()))); $commandXML->appendChild($helpXML = $dom->createElement('help')); $helpXML->appendChild($dom->createTextNode(\str_replace("\n", "\n ", $command->getProcessedHelp()))); $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition()); $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); return $dom; } public function getApplicationDocument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application, string $namespace = null) : \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($rootXml = $dom->createElement('symfony')); if ('UNKNOWN' !== $application->getName()) { $rootXml->setAttribute('name', $application->getName()); if ('UNKNOWN' !== $application->getVersion()) { $rootXml->setAttribute('version', $application->getVersion()); } } $rootXml->appendChild($commandsXML = $dom->createElement('commands')); $description = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\ApplicationDescription($application, $namespace, \true); if ($namespace) { $commandsXML->setAttribute('namespace', $namespace); } foreach ($description->getCommands() as $command) { $this->appendDocument($commandsXML, $this->getCommandDocument($command)); } if (!$namespace) { $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); foreach ($description->getNamespaces() as $namespaceDescription) { $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); foreach ($namespaceDescription['commands'] as $name) { $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); $commandXML->appendChild($dom->createTextNode($name)); } } } return $dom; } /** * {@inheritdoc} */ protected function describeInputArgument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument $argument, array $options = []) { $this->writeDocument($this->getInputArgumentDocument($argument)); } /** * {@inheritdoc} */ protected function describeInputOption(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption $option, array $options = []) { $this->writeDocument($this->getInputOptionDocument($option)); } /** * {@inheritdoc} */ protected function describeInputDefinition(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition, array $options = []) { $this->writeDocument($this->getInputDefinitionDocument($definition)); } /** * {@inheritdoc} */ protected function describeCommand(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command, array $options = []) { $this->writeDocument($this->getCommandDocument($command)); } /** * {@inheritdoc} */ protected function describeApplication(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application, array $options = []) { $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); } /** * Appends document children to parent node. */ private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) { foreach ($importedParent->childNodes as $childNode) { $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, \true)); } } /** * Writes DOM document. */ private function writeDocument(\DOMDocument $dom) { $dom->formatOutput = \true; $this->write($dom->saveXML()); } private function getInputArgumentDocument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument $argument) : \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($objectXML = $dom->createElement('argument')); $objectXML->setAttribute('name', $argument->getName()); $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); $objectXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [\var_export($argument->getDefault(), \true)] : ($argument->getDefault() ? [$argument->getDefault()] : [])); foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); } return $dom; } private function getInputOptionDocument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption $option) : \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($objectXML = $dom->createElement('option')); $objectXML->setAttribute('name', '--' . $option->getName()); $pos = \strpos($option->getShortcut(), '|'); if (\false !== $pos) { $objectXML->setAttribute('shortcut', '-' . \substr($option->getShortcut(), 0, $pos)); $objectXML->setAttribute('shortcuts', '-' . \str_replace('|', '|-', $option->getShortcut())); } else { $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-' . $option->getShortcut() : ''); } $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); $objectXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); if ($option->acceptValue()) { $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [\var_export($option->getDefault(), \true)] : ($option->getDefault() ? [$option->getDefault()] : [])); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); if (!empty($defaults)) { foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); } } } return $dom; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Application; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption; /** * Text descriptor. * * @author Jean-François Simon * * @internal */ class TextDescriptor extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument $argument, array $options = []) { if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { $default = \sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault())); } else { $default = ''; } $totalWidth = isset($options['total_width']) ? $options['total_width'] : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($argument->getName()); $spacingWidth = $totalWidth - \strlen($argument->getName()); $this->writeText(\sprintf( ' %s %s%s%s', $argument->getName(), \str_repeat(' ', $spacingWidth), // + 4 = 2 spaces before , 2 spaces after \preg_replace('/\\s*[\\r\\n]\\s*/', "\n" . \str_repeat(' ', $totalWidth + 4), $argument->getDescription()), $default ), $options); } /** * {@inheritdoc} */ protected function describeInputOption(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption $option, array $options = []) { if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { $default = \sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault())); } else { $default = ''; } $value = ''; if ($option->acceptValue()) { $value = '=' . \strtoupper($option->getName()); if ($option->isValueOptional()) { $value = '[' . $value . ']'; } } $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions([$option]); $synopsis = \sprintf('%s%s', $option->getShortcut() ? \sprintf('-%s, ', $option->getShortcut()) : ' ', \sprintf('--%s%s', $option->getName(), $value)); $spacingWidth = $totalWidth - \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($synopsis); $this->writeText(\sprintf( ' %s %s%s%s%s', $synopsis, \str_repeat(' ', $spacingWidth), // + 4 = 2 spaces before , 2 spaces after \preg_replace('/\\s*[\\r\\n]\\s*/', "\n" . \str_repeat(' ', $totalWidth + 4), $option->getDescription()), $default, $option->isArray() ? ' (multiple values allowed)' : '' ), $options); } /** * {@inheritdoc} */ protected function describeInputDefinition(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition, array $options = []) { $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); foreach ($definition->getArguments() as $argument) { $totalWidth = \max($totalWidth, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($argument->getName())); } if ($definition->getArguments()) { $this->writeText('Arguments:', $options); $this->writeText("\n"); foreach ($definition->getArguments() as $argument) { $this->describeInputArgument($argument, \array_merge($options, ['total_width' => $totalWidth])); $this->writeText("\n"); } } if ($definition->getArguments() && $definition->getOptions()) { $this->writeText("\n"); } if ($definition->getOptions()) { $laterOptions = []; $this->writeText('Options:', $options); foreach ($definition->getOptions() as $option) { if (\strlen($option->getShortcut()) > 1) { $laterOptions[] = $option; continue; } $this->writeText("\n"); $this->describeInputOption($option, \array_merge($options, ['total_width' => $totalWidth])); } foreach ($laterOptions as $option) { $this->writeText("\n"); $this->describeInputOption($option, \array_merge($options, ['total_width' => $totalWidth])); } } } /** * {@inheritdoc} */ protected function describeCommand(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command, array $options = []) { $command->getSynopsis(\true); $command->getSynopsis(\false); $command->mergeApplicationDefinition(\false); if ($description = $command->getDescription()) { $this->writeText('Description:', $options); $this->writeText("\n"); $this->writeText(' ' . $description); $this->writeText("\n\n"); } $this->writeText('Usage:', $options); foreach (\array_merge([$command->getSynopsis(\true)], $command->getAliases(), $command->getUsages()) as $usage) { $this->writeText("\n"); $this->writeText(' ' . \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape($usage), $options); } $this->writeText("\n"); $definition = $command->getNativeDefinition(); if ($definition->getOptions() || $definition->getArguments()) { $this->writeText("\n"); $this->describeInputDefinition($definition, $options); $this->writeText("\n"); } $help = $command->getProcessedHelp(); if ($help && $help !== $description) { $this->writeText("\n"); $this->writeText('Help:', $options); $this->writeText("\n"); $this->writeText(' ' . \str_replace("\n", "\n ", $help), $options); $this->writeText("\n"); } } /** * {@inheritdoc} */ protected function describeApplication(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application, array $options = []) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\ApplicationDescription($application, $describedNamespace); if (isset($options['raw_text']) && $options['raw_text']) { $width = $this->getColumnWidth($description->getCommands()); foreach ($description->getCommands() as $command) { $this->writeText(\sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); $this->writeText("\n"); } } else { if ('' != ($help = $application->getHelp())) { $this->writeText("{$help}\n\n", $options); } $this->writeText("Usage:\n", $options); $this->writeText(" command [options] [arguments]\n\n", $options); $this->describeInputDefinition(new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition($application->getDefinition()->getOptions()), $options); $this->writeText("\n"); $this->writeText("\n"); $commands = $description->getCommands(); $namespaces = $description->getNamespaces(); if ($describedNamespace && $namespaces) { // make sure all alias commands are included when describing a specific namespace $describedNamespaceInfo = \reset($namespaces); foreach ($describedNamespaceInfo['commands'] as $name) { $commands[$name] = $description->getCommand($name); } } // calculate max. width based on available commands per namespace $width = $this->getColumnWidth(\array_merge(...\array_values(\array_map(function ($namespace) use($commands) { return \array_intersect($namespace['commands'], \array_keys($commands)); }, \array_values($namespaces))))); if ($describedNamespace) { $this->writeText(\sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); } else { $this->writeText('Available commands:', $options); } foreach ($namespaces as $namespace) { $namespace['commands'] = \array_filter($namespace['commands'], function ($name) use($commands) { return isset($commands[$name]); }); if (!$namespace['commands']) { continue; } if (!$describedNamespace && \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { $this->writeText("\n"); $this->writeText(' ' . $namespace['id'] . '', $options); } foreach ($namespace['commands'] as $name) { $this->writeText("\n"); $spacingWidth = $width - \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($name); $command = $commands[$name]; $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; $this->writeText(\sprintf(' %s%s%s', $name, \str_repeat(' ', $spacingWidth), $commandAliases . $command->getDescription()), $options); } } $this->writeText("\n"); } } /** * {@inheritdoc} */ private function writeText(string $content, array $options = []) { $this->write(isset($options['raw_text']) && $options['raw_text'] ? \strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : \true); } /** * Formats command aliases to show them in the command description. */ private function getCommandAliasesText(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command) : string { $text = ''; $aliases = $command->getAliases(); if ($aliases) { $text = '[' . \implode('|', $aliases) . '] '; } return $text; } /** * Formats input option/argument default value. * * @param mixed $default */ private function formatDefaultValue($default) : string { if (\INF === $default) { return 'INF'; } if (\is_string($default)) { $default = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape($default); } elseif (\is_array($default)) { foreach ($default as $key => $value) { if (\is_string($value)) { $default[$key] = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Formatter\OutputFormatter::escape($value); } } } return \str_replace('\\\\', '\\', \json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); } /** * @param (Command|string)[] $commands */ private function getColumnWidth(array $commands) : int { $widths = []; foreach ($commands as $command) { if ($command instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command) { $widths[] = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($command->getName()); foreach ($command->getAliases() as $alias) { $widths[] = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($alias); } } else { $widths[] = \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($command); } } return $widths ? \max($widths) + 2 : 0; } /** * @param InputOption[] $options */ private function calculateTotalWidthForOptions(array $options) : int { $totalWidth = 0; foreach ($options as $option) { // "-" + shortcut + ", --" + name $nameLength = 1 + \max(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($option->getShortcut()), 1) + 4 + \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($option->getName()); if ($option->acceptValue()) { $valueLength = 1 + \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($option->getName()); // = + value $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] $nameLength += $valueLength; } $totalWidth = \max($totalWidth, $nameLength); } return $totalWidth; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Application; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * @author Jean-François Simon * * @internal */ abstract class Descriptor implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\DescriptorInterface { /** * @var OutputInterface */ protected $output; /** * {@inheritdoc} */ public function describe(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, $object, array $options = []) { $this->output = $output; switch (\true) { case $object instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument: $this->describeInputArgument($object, $options); break; case $object instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption: $this->describeInputOption($object, $options); break; case $object instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition: $this->describeInputDefinition($object, $options); break; case $object instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command: $this->describeCommand($object, $options); break; case $object instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application: $this->describeApplication($object, $options); break; default: throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Object of type "%s" is not describable.', \get_debug_type($object))); } } /** * Writes content to output. */ protected function write(string $content, bool $decorated = \false) { $this->output->write($content, \false, $decorated ? \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::OUTPUT_NORMAL : \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface::OUTPUT_RAW); } /** * Describes an InputArgument instance. * * @return string|mixed */ protected abstract function describeInputArgument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument $argument, array $options = []); /** * Describes an InputOption instance. * * @return string|mixed */ protected abstract function describeInputOption(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption $option, array $options = []); /** * Describes an InputDefinition instance. * * @return string|mixed */ protected abstract function describeInputDefinition(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition, array $options = []); /** * Describes a Command instance. * * @return string|mixed */ protected abstract function describeCommand(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command, array $options = []); /** * Describes an Application instance. * * @return string|mixed */ protected abstract function describeApplication(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application, array $options = []); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Application; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * Markdown descriptor. * * @author Jean-François Simon * * @internal */ class MarkdownDescriptor extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\Descriptor { /** * {@inheritdoc} */ public function describe(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, $object, array $options = []) { $decorated = $output->isDecorated(); $output->setDecorated(\false); parent::describe($output, $object, $options); $output->setDecorated($decorated); } /** * {@inheritdoc} */ protected function write(string $content, bool $decorated = \true) { parent::write($content, $decorated); } /** * {@inheritdoc} */ protected function describeInputArgument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument $argument, array $options = []) { $this->write('#### `' . ($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)) . '`'); } /** * {@inheritdoc} */ protected function describeInputOption(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption $option, array $options = []) { $name = '--' . $option->getName(); if ($option->getShortcut()) { $name .= '|-' . \str_replace('|', '|-', $option->getShortcut()) . ''; } $this->write('#### `' . $name . '`' . "\n\n" . ($option->getDescription() ? \preg_replace('/\\s*[\\r\\n]\\s*/', "\n", $option->getDescription()) . "\n\n" : '') . '* Accept value: ' . ($option->acceptValue() ? 'yes' : 'no') . "\n" . '* Is value required: ' . ($option->isValueRequired() ? 'yes' : 'no') . "\n" . '* Is multiple: ' . ($option->isArray() ? 'yes' : 'no') . "\n" . '* Default: `' . \str_replace("\n", '', \var_export($option->getDefault(), \true)) . '`'); } /** * {@inheritdoc} */ protected function describeInputDefinition(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition, array $options = []) { 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); } } } if (\count($definition->getOptions()) > 0) { if ($showArguments) { $this->write("\n\n"); } $this->write('### Options'); foreach ($definition->getOptions() as $option) { $this->write("\n\n"); if (null !== ($describeInputOption = $this->describeInputOption($option))) { $this->write($describeInputOption); } } } } /** * {@inheritdoc} */ protected function describeCommand(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command, array $options = []) { $command->getSynopsis(); $command->mergeApplicationDefinition(\false); $this->write('`' . $command->getName() . "`\n" . \str_repeat('-', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($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"; })); if ($help = $command->getProcessedHelp()) { $this->write("\n"); $this->write($help); } if ($command->getNativeDefinition()) { $this->write("\n\n"); $this->describeInputDefinition($command->getNativeDefinition()); } } /** * {@inheritdoc} */ protected function describeApplication(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application, array $options = []) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\ApplicationDescription($application, $describedNamespace); $title = $this->getApplicationTitle($application); $this->write($title . "\n" . \str_repeat('=', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Helper::strlen($title))); foreach ($description->getNamespaces() as $namespace) { if (\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Descriptor\ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { $this->write("\n\n"); $this->write('**' . $namespace['id'] . ':**'); } $this->write("\n\n"); $this->write(\implode("\n", \array_map(function ($commandName) use($description) { return \sprintf('* [`%s`](#%s)', $commandName, \str_replace(':', '', $description->getCommand($commandName)->getName())); }, $namespace['commands']))); } foreach ($description->getCommands() as $command) { $this->write("\n\n"); if (null !== ($describeCommand = $this->describeCommand($command))) { $this->write($describeCommand); } } } private function getApplicationTitle(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Application $application) : string { if ('UNKNOWN' !== $application->getName()) { if ('UNKNOWN' !== $application->getVersion()) { return \sprintf('%s %s', $application->getName(), $application->getVersion()); } return $application->getName(); } return 'Console Tool'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException; /** * Input is the base class for all concrete Input classes. * * Three concrete classes are provided by default: * * * `ArgvInput`: The input comes from the CLI arguments (argv) * * `StringInput`: The input is provided as a string * * `ArrayInput`: The input is provided as an array * * @author Fabien Potencier */ abstract class Input implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\StreamableInputInterface { protected $definition; protected $stream; protected $options = []; protected $arguments = []; protected $interactive = \true; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition = null) { if (null === $definition) { $this->definition = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition(); } else { $this->bind($definition); $this->validate(); } } /** * {@inheritdoc} */ public function bind(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition) { $this->arguments = []; $this->options = []; $this->definition = $definition; $this->parse(); } /** * Processes command line arguments. */ protected abstract function parse(); /** * {@inheritdoc} */ public function validate() { $definition = $this->definition; $givenArguments = $this->arguments; $missingArguments = \array_filter(\array_keys($definition->getArguments()), function ($argument) use($definition, $givenArguments) { return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); }); if (\count($missingArguments) > 0) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException(\sprintf('Not enough arguments (missing: "%s").', \implode(', ', $missingArguments))); } } /** * {@inheritdoc} */ public function isInteractive() { return $this->interactive; } /** * {@inheritdoc} */ public function setInteractive(bool $interactive) { $this->interactive = $interactive; } /** * {@inheritdoc} */ public function getArguments() { return \array_merge($this->definition->getArgumentDefaults(), $this->arguments); } /** * {@inheritdoc} */ public function getArgument(string $name) { if (!$this->definition->hasArgument($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name)); } return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); } /** * {@inheritdoc} */ public function setArgument(string $name, $value) { if (!$this->definition->hasArgument($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; } /** * {@inheritdoc} */ public function hasArgument($name) { return $this->definition->hasArgument($name); } /** * {@inheritdoc} */ public function getOptions() { return \array_merge($this->definition->getOptionDefaults(), $this->options); } /** * {@inheritdoc} */ public function getOption(string $name) { if (!$this->definition->hasOption($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name)); } return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); } /** * {@inheritdoc} */ public function setOption(string $name, $value) { if (!$this->definition->hasOption($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name)); } $this->options[$name] = $value; } /** * {@inheritdoc} */ public function hasOption(string $name) { return $this->definition->hasOption($name); } /** * Escapes a token through escapeshellarg if it contains unsafe chars. * * @return string */ public function escapeToken(string $token) { return \preg_match('{^[\\w-]+$}', $token) ? $token : \escapeshellarg($token); } /** * {@inheritdoc} */ public function setStream($stream) { $this->stream = $stream; } /** * {@inheritdoc} */ public function getStream() { return $this->stream; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; /** * A InputDefinition represents a set of valid command line arguments and options. * * Usage: * * $definition = new InputDefinition([ * new InputArgument('name', InputArgument::REQUIRED), * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), * ]); * * @author Fabien Potencier */ class InputDefinition { private $arguments; private $requiredCount; private $hasAnArrayArgument = \false; private $hasOptional; private $options; private $shortcuts; /** * @param array $definition An array of InputArgument and InputOption instance */ public function __construct(array $definition = []) { $this->setDefinition($definition); } /** * Sets the definition of the input. */ public function setDefinition(array $definition) { $arguments = []; $options = []; foreach ($definition as $item) { if ($item instanceof \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption) { $options[] = $item; } else { $arguments[] = $item; } } $this->setArguments($arguments); $this->setOptions($options); } /** * Sets the InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects */ public function setArguments(array $arguments = []) { $this->arguments = []; $this->requiredCount = 0; $this->hasOptional = \false; $this->hasAnArrayArgument = \false; $this->addArguments($arguments); } /** * Adds an array of InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects */ public function addArguments(?array $arguments = []) { if (null !== $arguments) { foreach ($arguments as $argument) { $this->addArgument($argument); } } } /** * @throws LogicException When incorrect argument is given */ public function addArgument(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument $argument) { if (isset($this->arguments[$argument->getName()])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException(\sprintf('An argument with name "%s" already exists.', $argument->getName())); } if ($this->hasAnArrayArgument) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('Cannot add an argument after an array argument.'); } if ($argument->isRequired() && $this->hasOptional) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('Cannot add a required argument after an optional one.'); } if ($argument->isArray()) { $this->hasAnArrayArgument = \true; } if ($argument->isRequired()) { ++$this->requiredCount; } else { $this->hasOptional = \true; } $this->arguments[$argument->getName()] = $argument; } /** * Returns an InputArgument by name or by position. * * @param string|int $name The InputArgument name or position * * @return InputArgument An InputArgument object * * @throws InvalidArgumentException When argument given doesn't exist */ public function getArgument($name) { if (!$this->hasArgument($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name)); } $arguments = \is_int($name) ? \array_values($this->arguments) : $this->arguments; return $arguments[$name]; } /** * Returns true if an InputArgument object exists by name or position. * * @param string|int $name The InputArgument name or position * * @return bool true if the InputArgument object exists, false otherwise */ public function hasArgument($name) { $arguments = \is_int($name) ? \array_values($this->arguments) : $this->arguments; return isset($arguments[$name]); } /** * Gets the array of InputArgument objects. * * @return InputArgument[] An array of InputArgument objects */ public function getArguments() { return $this->arguments; } /** * Returns the number of InputArguments. * * @return int The number of InputArguments */ public function getArgumentCount() { return $this->hasAnArrayArgument ? \PHP_INT_MAX : \count($this->arguments); } /** * Returns the number of required InputArguments. * * @return int The number of required InputArguments */ public function getArgumentRequiredCount() { return $this->requiredCount; } /** * Gets the default values. * * @return array An array of default values */ public function getArgumentDefaults() { $values = []; foreach ($this->arguments as $argument) { $values[$argument->getName()] = $argument->getDefault(); } return $values; } /** * Sets the InputOption objects. * * @param InputOption[] $options An array of InputOption objects */ public function setOptions(array $options = []) { $this->options = []; $this->shortcuts = []; $this->addOptions($options); } /** * Adds an array of InputOption objects. * * @param InputOption[] $options An array of InputOption objects */ public function addOptions(array $options = []) { foreach ($options as $option) { $this->addOption($option); } } /** * @throws LogicException When option given already exist */ public function addOption(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption $option) { if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException(\sprintf('An option named "%s" already exists.', $option->getName())); } if ($option->getShortcut()) { foreach (\explode('|', $option->getShortcut()) as $shortcut) { if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException(\sprintf('An option with shortcut "%s" already exists.', $shortcut)); } } } $this->options[$option->getName()] = $option; if ($option->getShortcut()) { foreach (\explode('|', $option->getShortcut()) as $shortcut) { $this->shortcuts[$shortcut] = $option->getName(); } } } /** * Returns an InputOption by name. * * @return InputOption A InputOption object * * @throws InvalidArgumentException When option given doesn't exist */ public function getOption(string $name) { if (!$this->hasOption($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $name)); } return $this->options[$name]; } /** * Returns true if an InputOption object exists by name. * * This method can't be used to check if the user included the option when * executing the command (use getOption() instead). * * @return bool true if the InputOption object exists, false otherwise */ public function hasOption(string $name) { return isset($this->options[$name]); } /** * Gets the array of InputOption objects. * * @return InputOption[] An array of InputOption objects */ public function getOptions() { return $this->options; } /** * Returns true if an InputOption object exists by shortcut. * * @return bool true if the InputOption object exists, false otherwise */ public function hasShortcut(string $name) { return isset($this->shortcuts[$name]); } /** * Gets an InputOption by shortcut. * * @return InputOption An InputOption object */ public function getOptionForShortcut(string $shortcut) { return $this->getOption($this->shortcutToName($shortcut)); } /** * Gets an array of default values. * * @return array An array of all default values */ public function getOptionDefaults() { $values = []; foreach ($this->options as $option) { $values[$option->getName()] = $option->getDefault(); } return $values; } /** * Returns the InputOption name given a shortcut. * * @throws InvalidArgumentException When option given does not exist * * @internal */ public function shortcutToName(string $shortcut) : string { if (!isset($this->shortcuts[$shortcut])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The "-%s" option does not exist.', $shortcut)); } return $this->shortcuts[$shortcut]; } /** * Gets the synopsis. * * @return string The synopsis */ public function getSynopsis(bool $short = \false) { $elements = []; if ($short && $this->getOptions()) { $elements[] = '[options]'; } elseif (!$short) { foreach ($this->getOptions() as $option) { $value = ''; if ($option->acceptValue()) { $value = \sprintf(' %s%s%s', $option->isValueOptional() ? '[' : '', \strtoupper($option->getName()), $option->isValueOptional() ? ']' : ''); } $shortcut = $option->getShortcut() ? \sprintf('-%s|', $option->getShortcut()) : ''; $elements[] = \sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value); } } if (\count($elements) && $this->getArguments()) { $elements[] = '[--]'; } $tail = ''; foreach ($this->getArguments() as $argument) { $element = '<' . $argument->getName() . '>'; if ($argument->isArray()) { $element .= '...'; } if (!$argument->isRequired()) { $element = '[' . $element; $tail .= ']'; } $elements[] = $element; } return \implode(' ', $elements) . $tail; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidOptionException; /** * ArrayInput represents an input provided as an array. * * Usage: * * $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']); * * @author Fabien Potencier */ class ArrayInput extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\Input { private $parameters; public function __construct(array $parameters, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition = null) { $this->parameters = $parameters; parent::__construct($definition); } /** * {@inheritdoc} */ public function getFirstArgument() { foreach ($this->parameters as $param => $value) { if ($param && \is_string($param) && '-' === $param[0]) { continue; } return $value; } return null; } /** * {@inheritdoc} */ public function hasParameterOption($values, bool $onlyParams = \false) { $values = (array) $values; foreach ($this->parameters as $k => $v) { if (!\is_int($k)) { $v = $k; } if ($onlyParams && '--' === $v) { return \false; } if (\in_array($v, $values)) { return \true; } } return \false; } /** * {@inheritdoc} */ public function getParameterOption($values, $default = \false, bool $onlyParams = \false) { $values = (array) $values; foreach ($this->parameters as $k => $v) { if ($onlyParams && ('--' === $k || \is_int($k) && '--' === $v)) { return $default; } if (\is_int($k)) { if (\in_array($v, $values)) { return \true; } } elseif (\in_array($k, $values)) { return $v; } } return $default; } /** * Returns a stringified representation of the args passed to the command. * * @return string */ public function __toString() { $params = []; foreach ($this->parameters as $param => $val) { if ($param && \is_string($param) && '-' === $param[0]) { if (\is_array($val)) { foreach ($val as $v) { $params[] = $param . ('' != $v ? '=' . $this->escapeToken($v) : ''); } } else { $params[] = $param . ('' != $val ? '=' . $this->escapeToken($val) : ''); } } else { $params[] = \is_array($val) ? \implode(' ', \array_map([$this, 'escapeToken'], $val)) : $this->escapeToken($val); } } return \implode(' ', $params); } /** * {@inheritdoc} */ protected function parse() { foreach ($this->parameters as $key => $value) { if ('--' === $key) { return; } if (0 === \strpos($key, '--')) { $this->addLongOption(\substr($key, 2), $value); } elseif (0 === \strpos($key, '-')) { $this->addShortOption(\substr($key, 1), $value); } else { $this->addArgument($key, $value); } } } /** * Adds a short option value. * * @throws InvalidOptionException When option given doesn't exist */ private function addShortOption(string $shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidOptionException(\sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); } /** * Adds a long option value. * * @throws InvalidOptionException When option given doesn't exist * @throws InvalidOptionException When a required value is missing */ private function addLongOption(string $name, $value) { if (!$this->definition->hasOption($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidOptionException(\sprintf('The "--%s" option does not exist.', $name)); } $option = $this->definition->getOption($name); if (null === $value) { if ($option->isValueRequired()) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidOptionException(\sprintf('The "--%s" option requires a value.', $name)); } if (!$option->isValueOptional()) { $value = \true; } } $this->options[$name] = $value; } /** * Adds an argument value. * * @param string|int $name The argument name * @param mixed $value The value for the argument * * @throws InvalidArgumentException When argument given doesn't exist */ private function addArgument($name, $value) { if (!$this->definition->hasArgument($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; /** * Represents a command line option. * * @author Fabien Potencier */ class InputOption { const VALUE_NONE = 1; const VALUE_REQUIRED = 2; const VALUE_OPTIONAL = 4; const VALUE_IS_ARRAY = 8; private $name; private $shortcut; private $mode; private $default; private $description; /** * @param string $name The option name * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts * @param int|null $mode The option mode: One of the VALUE_* constants * @param string $description A description text * @param string|string[]|int|bool|null $default The default value (must be null for self::VALUE_NONE) * * @throws InvalidArgumentException If option mode is invalid or incompatible */ public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) { if (0 === \strpos($name, '--')) { $name = \substr($name, 2); } if (empty($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('An option name cannot be empty.'); } if (empty($shortcut)) { $shortcut = null; } if (null !== $shortcut) { if (\is_array($shortcut)) { $shortcut = \implode('|', $shortcut); } $shortcuts = \preg_split('{(\\|)-?}', \ltrim($shortcut, '-')); $shortcuts = \array_filter($shortcuts); $shortcut = \implode('|', $shortcuts); if (empty($shortcut)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('An option shortcut cannot be empty.'); } } if (null === $mode) { $mode = self::VALUE_NONE; } elseif ($mode > 15 || $mode < 1) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Option mode "%s" is not valid.', $mode)); } $this->name = $name; $this->shortcut = $shortcut; $this->mode = $mode; $this->description = $description; if ($this->isArray() && !$this->acceptValue()) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); } $this->setDefault($default); } /** * Returns the option shortcut. * * @return string|null The shortcut */ public function getShortcut() { return $this->shortcut; } /** * Returns the option name. * * @return string The name */ public function getName() { return $this->name; } /** * Returns true if the option accepts a value. * * @return bool true if value mode is not self::VALUE_NONE, false otherwise */ public function acceptValue() { return $this->isValueRequired() || $this->isValueOptional(); } /** * Returns true if the option requires a value. * * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise */ public function isValueRequired() { return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); } /** * Returns true if the option takes an optional value. * * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise */ public function isValueOptional() { return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); } /** * Returns true if the option can take multiple values. * * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise */ public function isArray() { return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); } /** * Sets the default value. * * @param string|string[]|int|bool|null $default The default value * * @throws LogicException When incorrect default value is given */ public function setDefault($default = null) { if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); } if ($this->isArray()) { if (null === $default) { $default = []; } elseif (!\is_array($default)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('A default value for an array option must be an array.'); } } $this->default = $this->acceptValue() ? $default : \false; } /** * Returns the default value. * * @return string|string[]|int|bool|null The default value */ public function getDefault() { return $this->default; } /** * Returns the description text. * * @return string The description text */ public function getDescription() { return $this->description; } /** * Checks whether the given option equals this one. * * @return bool */ public function equals(self $option) { return $option->getName() === $this->getName() && $option->getShortcut() === $this->getShortcut() && $option->getDefault() === $this->getDefault() && $option->isArray() === $this->isArray() && $option->isValueRequired() === $this->isValueRequired() && $option->isValueOptional() === $this->isValueOptional(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; /** * StreamableInputInterface is the interface implemented by all input classes * that have an input stream. * * @author Robin Chalas */ interface StreamableInputInterface extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface { /** * Sets the input stream to read from when interacting with the user. * * This is mainly useful for testing purpose. * * @param resource $stream The input stream */ public function setStream($stream); /** * Returns the input stream. * * @return resource|null */ public function getStream(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException; /** * InputInterface is the interface implemented by all input classes. * * @author Fabien Potencier */ interface InputInterface { /** * Returns the first argument from the raw parameters (not parsed). * * @return string|null The value of the first argument or null otherwise */ public function getFirstArgument(); /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * Does not necessarily return the correct result for short options * when multiple flags are combined in the same option. * * @param string|array $values The values to look for in the raw parameters (can be an array) * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal * * @return bool true if the value is contained in the raw parameters */ public function hasParameterOption($values, bool $onlyParams = \false); /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * Does not necessarily return the correct result for short options * when multiple flags are combined in the same option. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal * * @return mixed The option value */ public function getParameterOption($values, $default = \false, bool $onlyParams = \false); /** * Binds the current Input instance with the given arguments and options. * * @throws RuntimeException */ public function bind(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition); /** * Validates the input. * * @throws RuntimeException When not enough arguments are given */ public function validate(); /** * Returns all the given arguments merged with the default values. * * @return array */ public function getArguments(); /** * Returns the argument value for a given argument name. * * @return string|string[]|null The argument value * * @throws InvalidArgumentException When argument given doesn't exist */ public function getArgument(string $name); /** * Sets an argument value by name. * * @param string|string[]|null $value The argument value * * @throws InvalidArgumentException When argument given doesn't exist */ public function setArgument(string $name, $value); /** * Returns true if an InputArgument object exists by name or position. * * @param string|int $name The InputArgument name or position * * @return bool true if the InputArgument object exists, false otherwise */ public function hasArgument($name); /** * Returns all the given options merged with the default values. * * @return array */ public function getOptions(); /** * Returns the option value for a given option name. * * @return string|string[]|bool|null The option value * * @throws InvalidArgumentException When option given doesn't exist */ public function getOption(string $name); /** * Sets an option value by name. * * @param string|string[]|bool|null $value The option value * * @throws InvalidArgumentException When option given doesn't exist */ public function setOption(string $name, $value); /** * Returns true if an InputOption object exists by name. * * @return bool true if the InputOption object exists, false otherwise */ public function hasOption(string $name); /** * Is this input means interactive? * * @return bool */ public function isInteractive(); /** * Sets the input interactivity. */ public function setInteractive(bool $interactive); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException; /** * Represents a command line argument. * * @author Fabien Potencier */ class InputArgument { const REQUIRED = 1; const OPTIONAL = 2; const IS_ARRAY = 4; private $name; private $mode; private $default; private $description; /** * @param string $name The argument name * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param string $description A description text * @param string|string[]|null $default The default value (for self::OPTIONAL mode only) * * @throws InvalidArgumentException When argument mode is not valid */ public function __construct(string $name, int $mode = null, string $description = '', $default = null) { if (null === $mode) { $mode = self::OPTIONAL; } elseif ($mode > 7 || $mode < 1) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Argument mode "%s" is not valid.', $mode)); } $this->name = $name; $this->mode = $mode; $this->description = $description; $this->setDefault($default); } /** * Returns the argument name. * * @return string The argument name */ public function getName() { return $this->name; } /** * Returns true if the argument is required. * * @return bool true if parameter mode is self::REQUIRED, false otherwise */ public function isRequired() { return self::REQUIRED === (self::REQUIRED & $this->mode); } /** * Returns true if the argument can take multiple values. * * @return bool true if mode is self::IS_ARRAY, false otherwise */ public function isArray() { return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); } /** * Sets the default value. * * @param string|string[]|null $default The default value * * @throws LogicException When incorrect default value is given */ public function setDefault($default = null) { if (self::REQUIRED === $this->mode && null !== $default) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.'); } if ($this->isArray()) { if (null === $default) { $default = []; } elseif (!\is_array($default)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\LogicException('A default value for an array argument must be an array.'); } } $this->default = $default; } /** * Returns the default value. * * @return string|string[]|null The default value */ public function getDefault() { return $this->default; } /** * Returns the description text. * * @return string The description text */ public function getDescription() { return $this->description; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException; /** * StringInput represents an input provided as a string. * * Usage: * * $input = new StringInput('foo --bar="foobar"'); * * @author Fabien Potencier */ class StringInput extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\ArgvInput { const REGEX_STRING = '([^\\s]+?)(?:\\s|(?setTokens($this->tokenize($input)); } /** * Tokenizes a string. * * @throws InvalidArgumentException When unable to parse input (should never happen) */ private function tokenize(string $input) : array { $tokens = []; $length = \strlen($input); $cursor = 0; while ($cursor < $length) { if (\preg_match('/\\s+/A', $input, $match, null, $cursor)) { } elseif (\preg_match('/([^="\'\\s]+?)(=?)(' . self::REGEX_QUOTED_STRING . '+)/A', $input, $match, null, $cursor)) { $tokens[] = $match[1] . $match[2] . \stripcslashes(\str_replace(['"\'', '\'"', '\'\'', '""'], '', \substr($match[3], 1, \strlen($match[3]) - 2))); } elseif (\preg_match('/' . self::REGEX_QUOTED_STRING . '/A', $input, $match, null, $cursor)) { $tokens[] = \stripcslashes(\substr($match[0], 1, \strlen($match[0]) - 2)); } elseif (\preg_match('/' . self::REGEX_STRING . '/A', $input, $match, null, $cursor)) { $tokens[] = \stripcslashes($match[1]); } else { // should never happen throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\InvalidArgumentException(\sprintf('Unable to parse input near "... %s ...".', \substr($input, $cursor, 10))); } $cursor += \strlen($match[0]); } return $tokens; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException; /** * ArgvInput represents an input coming from the CLI arguments. * * Usage: * * $input = new ArgvInput(); * * By default, the `$_SERVER['argv']` array is used for the input values. * * This can be overridden by explicitly passing the input values in the constructor: * * $input = new ArgvInput($_SERVER['argv']); * * If you pass it yourself, don't forget that the first element of the array * is the name of the running application. * * When passing an argument to the constructor, be sure that it respects * the same rules as the argv one. It's almost always better to use the * `StringInput` when you want to provide your own input. * * @author Fabien Potencier * * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 */ class ArgvInput extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\Input { private $tokens; private $parsed; public function __construct(array $argv = null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputDefinition $definition = null) { $argv = $argv ?? $_SERVER['argv'] ?? []; // strip the application name \array_shift($argv); $this->tokens = $argv; parent::__construct($definition); } protected function setTokens(array $tokens) { $this->tokens = $tokens; } /** * {@inheritdoc} */ protected function parse() { $parseOptions = \true; $this->parsed = $this->tokens; while (null !== ($token = \array_shift($this->parsed))) { if ($parseOptions && '' == $token) { $this->parseArgument($token); } elseif ($parseOptions && '--' == $token) { $parseOptions = \false; } elseif ($parseOptions && 0 === \strpos($token, '--')) { $this->parseLongOption($token); } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { $this->parseShortOption($token); } else { $this->parseArgument($token); } } } /** * Parses a short option. */ private function parseShortOption(string $token) { $name = \substr($token, 1); if (\strlen($name) > 1) { if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { // an option with a value (with no space) $this->addShortOption($name[0], \substr($name, 1)); } else { $this->parseShortOptionSet($name); } } else { $this->addShortOption($name, null); } } /** * Parses a short option set. * * @throws RuntimeException When option given doesn't exist */ private function parseShortOptionSet(string $name) { $len = \strlen($name); for ($i = 0; $i < $len; ++$i) { if (!$this->definition->hasShortcut($name[$i])) { $encoding = \mb_detect_encoding($name, null, \true); throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException(\sprintf('The "-%s" option does not exist.', \false === $encoding ? $name[$i] : \mb_substr($name, $i, 1, $encoding))); } $option = $this->definition->getOptionForShortcut($name[$i]); if ($option->acceptValue()) { $this->addLongOption($option->getName(), $i === $len - 1 ? null : \substr($name, $i + 1)); break; } else { $this->addLongOption($option->getName(), null); } } } /** * Parses a long option. */ private function parseLongOption(string $token) { $name = \substr($token, 2); if (\false !== ($pos = \strpos($name, '='))) { if (0 === \strlen($value = \substr($name, $pos + 1))) { \array_unshift($this->parsed, $value); } $this->addLongOption(\substr($name, 0, $pos), $value); } else { $this->addLongOption($name, null); } } /** * Parses an argument. * * @throws RuntimeException When too many arguments are given */ private function parseArgument(string $token) { $c = \count($this->arguments); // if input is expecting another argument, add it if ($this->definition->hasArgument($c)) { $arg = $this->definition->getArgument($c); $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token; // if last argument isArray(), append token to last argument } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { $arg = $this->definition->getArgument($c - 1); $this->arguments[$arg->getName()][] = $token; // unexpected argument } else { $all = $this->definition->getArguments(); if (\count($all)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException(\sprintf('Too many arguments, expected arguments "%s".', \implode('" "', \array_keys($all)))); } throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException(\sprintf('No arguments expected, got "%s".', $token)); } } /** * Adds a short option value. * * @throws RuntimeException When option given doesn't exist */ private function addShortOption(string $shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException(\sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); } /** * Adds a long option value. * * @throws RuntimeException When option given doesn't exist */ private function addLongOption(string $name, $value) { if (!$this->definition->hasOption($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException(\sprintf('The "--%s" option does not exist.', $name)); } $option = $this->definition->getOption($name); if (null !== $value && !$option->acceptValue()) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name)); } if (\in_array($value, ['', null], \true) && $option->acceptValue() && \count($this->parsed)) { // if option accepts an optional or mandatory argument // let's see if there is one provided $next = \array_shift($this->parsed); if (isset($next[0]) && '-' !== $next[0] || \in_array($next, ['', null], \true)) { $value = $next; } else { \array_unshift($this->parsed, $next); } } if (null === $value) { if ($option->isValueRequired()) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\RuntimeException(\sprintf('The "--%s" option requires a value.', $name)); } if (!$option->isArray() && !$option->isValueOptional()) { $value = \true; } } if ($option->isArray()) { $this->options[$name][] = $value; } else { $this->options[$name] = $value; } } /** * {@inheritdoc} */ public function getFirstArgument() { $isOption = \false; foreach ($this->tokens as $i => $token) { if ($token && '-' === $token[0]) { if (\false !== \strpos($token, '=') || !isset($this->tokens[$i + 1])) { continue; } // If it's a long option, consider that everything after "--" is the option name. // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator) $name = '-' === $token[1] ? \substr($token, 2) : \substr($token, -1); if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) { // noop } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) { $isOption = \true; } continue; } if ($isOption) { $isOption = \false; continue; } return $token; } return null; } /** * {@inheritdoc} */ public function hasParameterOption($values, bool $onlyParams = \false) { $values = (array) $values; foreach ($this->tokens as $token) { if ($onlyParams && '--' === $token) { return \false; } foreach ($values as $value) { // Options with values: // For long options, test for '--option=' at beginning // For short options, test for '-o' at beginning $leading = 0 === \strpos($value, '--') ? $value . '=' : $value; if ($token === $value || '' !== $leading && 0 === \strpos($token, $leading)) { return \true; } } } return \false; } /** * {@inheritdoc} */ public function getParameterOption($values, $default = \false, bool $onlyParams = \false) { $values = (array) $values; $tokens = $this->tokens; while (0 < \count($tokens)) { $token = \array_shift($tokens); if ($onlyParams && '--' === $token) { return $default; } foreach ($values as $value) { if ($token === $value) { return \array_shift($tokens); } // Options with values: // For long options, test for '--option=' at beginning // For short options, test for '-o' at beginning $leading = 0 === \strpos($value, '--') ? $value . '=' : $value; if ('' !== $leading && 0 === \strpos($token, $leading)) { return \substr($token, \strlen($leading)); } } } return $default; } /** * Returns a stringified representation of the args passed to the command. * * @return string */ public function __toString() { $tokens = \array_map(function ($token) { if (\preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { return $match[1] . $this->escapeToken($match[2]); } if ($token && '-' !== $token[0]) { return $this->escapeToken($token); } return $token; }, $this->tokens); return \implode(' ', $tokens); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input; /** * InputAwareInterface should be implemented by classes that depends on the * Console Input. * * @author Wouter J */ interface InputAwareInterface { /** * Sets the Console Input. */ public function setInput(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\CommandLoader; use _HumbugBoxd02f763d3c56\Psr\Container\ContainerInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException; /** * Loads commands from a PSR-11 container. * * @author Robin Chalas */ class ContainerCommandLoader implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\CommandLoader\CommandLoaderInterface { private $container; private $commandMap; /** * @param array $commandMap An array with command names as keys and service ids as values */ public function __construct(\_HumbugBoxd02f763d3c56\Psr\Container\ContainerInterface $container, array $commandMap) { $this->container = $container; $this->commandMap = $commandMap; } /** * {@inheritdoc} */ public function get(string $name) { if (!$this->has($name)) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name)); } return $this->container->get($this->commandMap[$name]); } /** * {@inheritdoc} */ public function has(string $name) { return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]); } /** * {@inheritdoc} */ public function getNames() { return \array_keys($this->commandMap); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\CommandLoader; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException; /** * A simple command loader using factories to instantiate commands lazily. * * @author Maxime Steinhausser */ class FactoryCommandLoader implements \_HumbugBoxd02f763d3c56\Symfony\Component\Console\CommandLoader\CommandLoaderInterface { private $factories; /** * @param callable[] $factories Indexed by command names */ public function __construct(array $factories) { $this->factories = $factories; } /** * {@inheritdoc} */ public function has(string $name) { return isset($this->factories[$name]); } /** * {@inheritdoc} */ public function get(string $name) { if (!isset($this->factories[$name])) { throw new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name)); } $factory = $this->factories[$name]; return $factory(); } /** * {@inheritdoc} */ public function getNames() { return \array_keys($this->factories); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\CommandLoader; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Exception\CommandNotFoundException; /** * @author Robin Chalas */ interface CommandLoaderInterface { /** * Loads a command. * * @return Command * * @throws CommandNotFoundException */ public function get(string $name); /** * Checks if a command exists. * * @return bool */ public function has(string $name); /** * @return string[] All registered command names */ public function getNames(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event; /** * Allows to do things before the command is executed, like skipping the command or changing the input. * * @author Fabien Potencier */ final class ConsoleCommandEvent extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleEvent { /** * The return code for skipped commands, this will also be passed into the terminate event. */ const RETURN_CODE_DISABLED = 113; /** * Indicates if the command should be run or skipped. */ private $commandShouldRun = \true; /** * Disables the command, so it won't be run. */ public function disableCommand() : bool { return $this->commandShouldRun = \false; } public function enableCommand() : bool { return $this->commandShouldRun = \true; } /** * Returns true if the command is runnable, false otherwise. */ public function commandShouldRun() : bool { return $this->commandShouldRun; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; use _HumbugBoxd02f763d3c56\Symfony\Contracts\EventDispatcher\Event; /** * Allows to inspect input and output of a command. * * @author Francesco Levorato */ class ConsoleEvent extends \_HumbugBoxd02f763d3c56\Symfony\Contracts\EventDispatcher\Event { protected $command; private $input; private $output; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command = null, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) { $this->command = $command; $this->input = $input; $this->output = $output; } /** * Gets the command that is executed. * * @return Command|null A Command instance */ public function getCommand() { return $this->command; } /** * Gets the input instance. * * @return InputInterface An InputInterface instance */ public function getInput() { return $this->input; } /** * Gets the output instance. * * @return OutputInterface An OutputInterface instance */ public function getOutput() { return $this->output; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * Allows to handle throwables thrown while running a command. * * @author Wouter de Jong */ final class ConsoleErrorEvent extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleEvent { private $error; private $exitCode; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, \Throwable $error, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command = null) { parent::__construct($command, $input, $output); $this->error = $error; } public function getError() : \Throwable { return $this->error; } public function setError(\Throwable $error) : void { $this->error = $error; } public function setExitCode(int $exitCode) : void { $this->exitCode = $exitCode; $r = new \ReflectionProperty($this->error, 'code'); $r->setAccessible(\true); $r->setValue($this->error, $this->exitCode); } public function getExitCode() : int { return null !== $this->exitCode ? $this->exitCode : (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Component\Console\Event; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface; use _HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface; /** * Allows to manipulate the exit code of a command after its execution. * * @author Francesco Levorato */ final class ConsoleTerminateEvent extends \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Event\ConsoleEvent { private $exitCode; public function __construct(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Command\Command $command, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output, int $exitCode) { parent::__construct($command, $input, $output); $this->setExitCode($exitCode); } public function setExitCode(int $exitCode) : void { $this->exitCode = $exitCode; } public function getExitCode() : int { return $this->exitCode; } } MZ@ !L!This program cannot be run in DOS mode. $,;B;B;B2מ:B2-B2ƞ9B2ў?Ba98B;CB2Ȟ:B2֞:B2Ӟ:BRich;BPELMoO  8 @`?@"P@ Pp!8!@ .text   `.rdata @@.data0@.rsrc @@@.relocP"@Bj$@xj @eEPV @EЃPV @MX @eEP5H @L @YY5\ @EP5` @D @YYP @MMT @3H; 0@uh@l3@$40@5h3@40@h$0@h(0@h 0@ @00@}jYjh"@3ۉ]dp]俀3@SVW0 @;t;u3Fuh4 @3F|3@;u j\Y;|3@u,5|3@h @h @YYtE5<0@|3@;uh @h @lYY|3@9]uSW8 @93@th3@Yt SjS3@$0@ @5$0@5(0@5 0@ 80@9,0@u7P @E MPQYYËeE80@39,0@uPh @9<0@u @E80@øMZf9@t3M<@@8PEuH t uՃv39xtv39j,0@p @jl @YY3@3@ @ t3@ @ p3@ @x3@V=0@u h@ @Yg=0@u j @Y3{U(H1@ D1@@1@<1@581@=41@f`1@f T1@f01@f,1@f%(1@f-$1@X1@EL1@EP1@E\1@0@P1@L0@@0@ D0@0@0@ @0@j?Yj @h!@$ @=0@ujYh ( @P, @ËUE8csmu*xu$@= t=!t="t=@u3]hH@ @3% @jh("@b53@5 @YEu u @YgjYe53@։E53@YYEEPEPu5l @YPUEu֣3@uփ3@E EjYËUuNYH]ËV!@!@W;stЃ;r_^ËV"@"@W;stЃ;r_^% @̋UMMZf9t3]ËA<8PEu3ҹ f9H‹]̋UEH<ASVq3WDv} H ;r X;r B(;r3_^[]̋UjhH"@he@dPSVW0@1E3PEdeEh@*tUE-@Ph@Pt;@$ЃEMd Y_^[]ËE3=‹ËeE3Md Y_^[]% @% @he@d5D$l$l$+SVW0@1E3PeuEEEEdËMd Y__^[]QËUuuu uh@h0@]ËVhh3V t VVVVV^3ËU0@eeSWN@;t t У0@`VEP< @u3u @3 @3 @3EP @E3E3;uO@ u 50@։50@^_[%t @%x @%| @% @% @% @% @% @% @Pd5D$ +d$ SVW(0@3PEuEEdËMd Y__^[]QËM3M%T @T$B J3J3l"@s###)r)b)H)4))(((((()#$%%&d&&$('''''(((6('H(Z(t(('''''l'^'R'F'>'>(0'')@W@@MoOl!@0@0@bad allocationH0@!@RSDSьJ!LZc:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdbe@@:@@@@"d"@"# $#&D H#(h ###)r)b)H)4))(((((()#$%%&d&&$('''''(((6('H(Z(t(('''''l'^'R'F'>'>(0'')GetConsoleModeSetConsoleMode;GetStdHandleKERNEL32.dll??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@AJ?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ{??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@ZMSVCP90.dll_amsg_exit__getmainargs,_cexit|_exitf_XcptFilterexit__initenv_initterm_initterm_e<_configthreadlocale__setusermatherr _adjust_fdiv__p__commode__p__fmodej_encode_pointer__set_app_typeK_crt_debugger_hookC?terminate@@YAXXZMSVCR90.dll_unlock__dllonexitv_lock_onexit`_decode_pointers_except_handler4_common _invoke_watson?_controlfp_sInterlockedExchange!SleepInterlockedCompareExchange-TerminateProcessGetCurrentProcess>UnhandledExceptionFilterSetUnhandledExceptionFilterIsDebuggerPresentTQueryPerformanceCounterfGetTickCountGetCurrentThreadIdGetCurrentProcessIdOGetSystemTimeAsFileTimes__CxxFrameHandler3N@D$!@ 8Ph  @(CV(4VS_VERSION_INFOStringFileInfob040904b0QFileDescriptionReads from stdin without leaking info to the terminal and outputs back to stdout6 FileVersion1, 0, 0, 08 InternalNamehiddeninputPLegalCopyrightJordi Boggiano - 2012HOriginalFilenamehiddeninput.exe: ProductNameHidden Input: ProductVersion1, 0, 0, 0DVarFileInfo$Translation  PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING@00!0/080F0L0T0^0d0n0{000000000000001#1-1@1J1O1T1v1{1111111111111112"2*23292A2M2_2j2p222222222222 333%303N3T3Z3`3f3l3s3z333333333333333334444%4;4B444444444445!5^5c5555H6M6_6}66677 7*7w7|777778 88=8E8P8V8\8b8h8n8t8z88889 $0001 1t1x12 2@2\2`2h2t20 0 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring; /** * Partial mbstring implementation in PHP, iconv based, UTF-8 centric. * * Implemented: * - mb_chr - Returns a specific character from its Unicode code point * - mb_convert_encoding - Convert character encoding * - mb_convert_variables - Convert character code in variable(s) * - mb_decode_mimeheader - Decode string in MIME header field * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED * - mb_decode_numericentity - Decode HTML numeric string reference to character * - mb_encode_numericentity - Encode character to HTML numeric string reference * - mb_convert_case - Perform case folding on a string * - mb_detect_encoding - Detect character encoding * - mb_get_info - Get internal settings of mbstring * - mb_http_input - Detect HTTP input character encoding * - mb_http_output - Set/Get HTTP output character encoding * - mb_internal_encoding - Set/Get internal character encoding * - mb_list_encodings - Returns an array of all supported encodings * - mb_ord - Returns the Unicode code point of a character * - mb_output_handler - Callback function converts character encoding in output buffer * - mb_scrub - Replaces ill-formed byte sequences with substitute characters * - mb_strlen - Get string length * - mb_strpos - Find position of first occurrence of string in a string * - mb_strrpos - Find position of last occurrence of a string in a string * - mb_str_split - Convert a string to an array * - mb_strtolower - Make a string lowercase * - mb_strtoupper - Make a string uppercase * - mb_substitute_character - Set/Get substitution character * - mb_substr - Get part of string * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive * - mb_stristr - Finds first occurrence of a string within another, case insensitive * - mb_strrchr - Finds the last occurrence of a character in a string within another * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive * - mb_strstr - Finds first occurrence of a string within another * - mb_strwidth - Return width of string * - mb_substr_count - Count the number of substring occurrences * * Not implemented: * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) * - mb_ereg_* - Regular expression with multibyte support * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable * - mb_preferred_mime_name - Get MIME charset string * - mb_regex_encoding - Returns current encoding for multibyte regex as string * - mb_regex_set_options - Set/Get the default options for mbregex functions * - mb_send_mail - Send encoded mail * - mb_split - Split multibyte string using regular expression * - mb_strcut - Get part of string * - mb_strimwidth - Get truncated string with specified width * * @author Nicolas Grekas * * @internal */ final class Mbstring { const MB_CASE_FOLD = \PHP_INT_MAX; private static $encodingList = array('ASCII', 'UTF-8'); private static $language = 'neutral'; private static $internalEncoding = 'UTF-8'; private static $caseFold = array(array('µ', 'ſ', "ͅ", 'ς', "ϐ", "ϑ", "ϕ", "ϖ", "ϰ", "ϱ", "ϵ", "ẛ", "ι"), array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "ṡ", 'ι')); public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) { if (\is_array($fromEncoding) || \false !== \strpos($fromEncoding, ',')) { $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); } else { $fromEncoding = self::getEncoding($fromEncoding); } $toEncoding = self::getEncoding($toEncoding); if ('BASE64' === $fromEncoding) { $s = \base64_decode($s); $fromEncoding = $toEncoding; } if ('BASE64' === $toEncoding) { return \base64_encode($s); } if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) { if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) { $fromEncoding = 'Windows-1252'; } if ('UTF-8' !== $fromEncoding) { $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s); } return \preg_replace_callback('/[\\x80-\\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s); } if ('HTML-ENTITIES' === $fromEncoding) { $s = \html_entity_decode($s, \ENT_COMPAT, 'UTF-8'); $fromEncoding = 'UTF-8'; } return \iconv($fromEncoding, $toEncoding . '//IGNORE', $s); } public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { $vars = array(&$a, &$b, &$c, &$d, &$e, &$f); $ok = \true; \array_walk_recursive($vars, function (&$v) use(&$ok, $toEncoding, $fromEncoding) { if (\false === ($v = \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding))) { $ok = \false; } }); return $ok ? $fromEncoding : \false; } public static function mb_decode_mimeheader($s) { return \iconv_mime_decode($s, 2, self::$internalEncoding); } public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) { \trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING); } public static function mb_decode_numericentity($s, $convmap, $encoding = null) { if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { \trigger_error('mb_decode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING); return null; } if (!\is_array($convmap) || !$convmap) { return \false; } if (null !== $encoding && !\is_scalar($encoding)) { \trigger_error('mb_decode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING); return ''; // Instead of null (cf. mb_encode_numericentity). } $s = (string) $s; if ('' === $s) { return ''; } $encoding = self::getEncoding($encoding); if ('UTF-8' === $encoding) { $encoding = null; if (!\preg_match('//u', $s)) { $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } $cnt = \floor(\count($convmap) / 4) * 4; for ($i = 0; $i < $cnt; $i += 4) { // collector_decode_htmlnumericentity ignores $convmap[$i + 3] $convmap[$i] += $convmap[$i + 2]; $convmap[$i + 1] += $convmap[$i + 2]; } $s = \preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use($cnt, $convmap) { $c = isset($m[2]) ? (int) \hexdec($m[2]) : $m[1]; for ($i = 0; $i < $cnt; $i += 4) { if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_chr($c - $convmap[$i + 2]); } } return $m[0]; }, $s); if (null === $encoding) { return $s; } return \iconv('UTF-8', $encoding . '//IGNORE', $s); } public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = \false) { if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { \trigger_error('mb_encode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING); return null; } if (!\is_array($convmap) || !$convmap) { return \false; } if (null !== $encoding && !\is_scalar($encoding)) { \trigger_error('mb_encode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING); return null; // Instead of '' (cf. mb_decode_numericentity). } if (null !== $is_hex && !\is_scalar($is_hex)) { \trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, ' . \gettype($s) . ' given', \E_USER_WARNING); return null; } $s = (string) $s; if ('' === $s) { return ''; } $encoding = self::getEncoding($encoding); if ('UTF-8' === $encoding) { $encoding = null; if (!\preg_match('//u', $s)) { $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } static $ulenMask = array("" => 2, "" => 2, "" => 3, "" => 4); $cnt = \floor(\count($convmap) / 4) * 4; $i = 0; $len = \strlen($s); $result = ''; while ($i < $len) { $ulen = $s[$i] < "" ? 1 : $ulenMask[$s[$i] & ""]; $uchr = \substr($s, $i, $ulen); $i += $ulen; $c = self::mb_ord($uchr); for ($j = 0; $j < $cnt; $j += 4) { if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { $cOffset = $c + $convmap[$j + 2] & $convmap[$j + 3]; $result .= $is_hex ? \sprintf('&#x%X;', $cOffset) : '&#' . $cOffset . ';'; continue 2; } } $result .= $uchr; } if (null === $encoding) { return $result; } return \iconv('UTF-8', $encoding . '//IGNORE', $result); } public static function mb_convert_case($s, $mode, $encoding = null) { $s = (string) $s; if ('' === $s) { return ''; } $encoding = self::getEncoding($encoding); if ('UTF-8' === $encoding) { $encoding = null; if (!\preg_match('//u', $s)) { $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } if (\MB_CASE_TITLE == $mode) { static $titleRegexp = null; if (null === $titleRegexp) { $titleRegexp = self::getData('titleCaseRegexp'); } $s = \preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s); } else { if (\MB_CASE_UPPER == $mode) { static $upper = null; if (null === $upper) { $upper = self::getData('upperCase'); } $map = $upper; } else { if (self::MB_CASE_FOLD === $mode) { $s = \str_replace(self::$caseFold[0], self::$caseFold[1], $s); } static $lower = null; if (null === $lower) { $lower = self::getData('lowerCase'); } $map = $lower; } static $ulenMask = array("" => 2, "" => 2, "" => 3, "" => 4); $i = 0; $len = \strlen($s); while ($i < $len) { $ulen = $s[$i] < "" ? 1 : $ulenMask[$s[$i] & ""]; $uchr = \substr($s, $i, $ulen); $i += $ulen; if (isset($map[$uchr])) { $uchr = $map[$uchr]; $nlen = \strlen($uchr); if ($nlen == $ulen) { $nlen = $i; do { $s[--$nlen] = $uchr[--$ulen]; } while ($ulen); } else { $s = \substr_replace($s, $uchr, $i - $ulen, $ulen); $len += $nlen - $ulen; $i += $nlen - $ulen; } } } } if (null === $encoding) { return $s; } return \iconv('UTF-8', $encoding . '//IGNORE', $s); } public static function mb_internal_encoding($encoding = null) { if (null === $encoding) { return self::$internalEncoding; } $encoding = self::getEncoding($encoding); if ('UTF-8' === $encoding || \false !== @\iconv($encoding, $encoding, ' ')) { self::$internalEncoding = $encoding; return \true; } return \false; } public static function mb_language($lang = null) { if (null === $lang) { return self::$language; } switch ($lang = \strtolower($lang)) { case 'uni': case 'neutral': self::$language = $lang; return \true; } return \false; } public static function mb_list_encodings() { return array('UTF-8'); } public static function mb_encoding_aliases($encoding) { switch (\strtoupper($encoding)) { case 'UTF8': case 'UTF-8': return array('utf8'); } return \false; } public static function mb_check_encoding($var = null, $encoding = null) { if (null === $encoding) { if (null === $var) { return \false; } $encoding = self::$internalEncoding; } return self::mb_detect_encoding($var, array($encoding)) || \false !== @\iconv($encoding, $encoding, $var); } public static function mb_detect_encoding($str, $encodingList = null, $strict = \false) { if (null === $encodingList) { $encodingList = self::$encodingList; } else { if (!\is_array($encodingList)) { $encodingList = \array_map('trim', \explode(',', $encodingList)); } $encodingList = \array_map('strtoupper', $encodingList); } foreach ($encodingList as $enc) { switch ($enc) { case 'ASCII': if (!\preg_match('/[\\x80-\\xFF]/', $str)) { return $enc; } break; case 'UTF8': case 'UTF-8': if (\preg_match('//u', $str)) { return 'UTF-8'; } break; default: if (0 === \strncmp($enc, 'ISO-8859-', 9)) { return $enc; } } } return \false; } public static function mb_detect_order($encodingList = null) { if (null === $encodingList) { return self::$encodingList; } if (!\is_array($encodingList)) { $encodingList = \array_map('trim', \explode(',', $encodingList)); } $encodingList = \array_map('strtoupper', $encodingList); foreach ($encodingList as $enc) { switch ($enc) { default: if (\strncmp($enc, 'ISO-8859-', 9)) { return \false; } // no break case 'ASCII': case 'UTF8': case 'UTF-8': } } self::$encodingList = $encodingList; return \true; } public static function mb_strlen($s, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { return \strlen($s); } return @\iconv_strlen($s, $encoding); } public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { return \strpos($haystack, $needle, $offset); } $needle = (string) $needle; if ('' === $needle) { \trigger_error(__METHOD__ . ': Empty delimiter', \E_USER_WARNING); return \false; } return \iconv_strpos($haystack, $needle, $offset, $encoding); } public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { return \strrpos($haystack, $needle, $offset); } if ($offset != (int) $offset) { $offset = 0; } elseif ($offset = (int) $offset) { if ($offset < 0) { if (0 > ($offset += self::mb_strlen($needle))) { $haystack = self::mb_substr($haystack, 0, $offset, $encoding); } $offset = 0; } else { $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); } } $pos = \iconv_strrpos($haystack, $needle, $encoding); return \false !== $pos ? $offset + $pos : \false; } public static function mb_str_split($string, $split_length = 1, $encoding = null) { if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) { \trigger_error('mb_str_split() expects parameter 1 to be string, ' . \gettype($string) . ' given', \E_USER_WARNING); return null; } if (1 > ($split_length = (int) $split_length)) { \trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING); return \false; } if (null === $encoding) { $encoding = \mb_internal_encoding(); } if ('UTF-8' === ($encoding = self::getEncoding($encoding))) { $rx = '/('; while (65535 < $split_length) { $rx .= '.{65535}'; $split_length -= 65535; } $rx .= '.{' . $split_length . '})/us'; return \preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); } $result = array(); $length = \mb_strlen($string, $encoding); for ($i = 0; $i < $length; $i += $split_length) { $result[] = \mb_substr($string, $i, $split_length, $encoding); } return $result; } public static function mb_strtolower($s, $encoding = null) { return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding); } public static function mb_strtoupper($s, $encoding = null) { return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding); } public static function mb_substitute_character($c = null) { if (0 === \strcasecmp($c, 'none')) { return \true; } return null !== $c ? \false : 'none'; } public static function mb_substr($s, $start, $length = null, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { return (string) \substr($s, $start, null === $length ? 2147483647 : $length); } if ($start < 0) { $start = \iconv_strlen($s, $encoding) + $start; if ($start < 0) { $start = 0; } } if (null === $length) { $length = 2147483647; } elseif ($length < 0) { $length = \iconv_strlen($s, $encoding) + $length - $start; if ($length < 0) { return ''; } } return (string) \iconv_substr($s, $start, $length, $encoding); } public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); return self::mb_strpos($haystack, $needle, $offset, $encoding); } public static function mb_stristr($haystack, $needle, $part = \false, $encoding = null) { $pos = self::mb_stripos($haystack, $needle, 0, $encoding); return self::getSubpart($pos, $part, $haystack, $encoding); } public static function mb_strrchr($haystack, $needle, $part = \false, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { return \strrchr($haystack, $needle, $part); } $needle = self::mb_substr($needle, 0, 1, $encoding); $pos = \iconv_strrpos($haystack, $needle, $encoding); return self::getSubpart($pos, $part, $haystack, $encoding); } public static function mb_strrichr($haystack, $needle, $part = \false, $encoding = null) { $needle = self::mb_substr($needle, 0, 1, $encoding); $pos = self::mb_strripos($haystack, $needle, $encoding); return self::getSubpart($pos, $part, $haystack, $encoding); } public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); return self::mb_strrpos($haystack, $needle, $offset, $encoding); } public static function mb_strstr($haystack, $needle, $part = \false, $encoding = null) { $pos = \strpos($haystack, $needle); if (\false === $pos) { return \false; } if ($part) { return \substr($haystack, 0, $pos); } return \substr($haystack, $pos); } public static function mb_get_info($type = 'all') { $info = array('internal_encoding' => self::$internalEncoding, 'http_output' => 'pass', 'http_output_conv_mimetypes' => '^(text/|application/xhtml\\+xml)', 'func_overload' => 0, 'func_overload_list' => 'no overload', 'mail_charset' => 'UTF-8', 'mail_header_encoding' => 'BASE64', 'mail_body_encoding' => 'BASE64', 'illegal_chars' => 0, 'encoding_translation' => 'Off', 'language' => self::$language, 'detect_order' => self::$encodingList, 'substitute_character' => 'none', 'strict_detection' => 'Off'); if ('all' === $type) { return $info; } if (isset($info[$type])) { return $info[$type]; } return \false; } public static function mb_http_input($type = '') { return \false; } public static function mb_http_output($encoding = null) { return null !== $encoding ? 'pass' === $encoding : 'pass'; } public static function mb_strwidth($s, $encoding = null) { $encoding = self::getEncoding($encoding); if ('UTF-8' !== $encoding) { $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } $s = \preg_replace('/[\\x{1100}-\\x{115F}\\x{2329}\\x{232A}\\x{2E80}-\\x{303E}\\x{3040}-\\x{A4CF}\\x{AC00}-\\x{D7A3}\\x{F900}-\\x{FAFF}\\x{FE10}-\\x{FE19}\\x{FE30}-\\x{FE6F}\\x{FF00}-\\x{FF60}\\x{FFE0}-\\x{FFE6}\\x{20000}-\\x{2FFFD}\\x{30000}-\\x{3FFFD}]/u', '', $s, -1, $wide); return ($wide << 1) + \iconv_strlen($s, 'UTF-8'); } public static function mb_substr_count($haystack, $needle, $encoding = null) { return \substr_count($haystack, $needle); } public static function mb_output_handler($contents, $status) { return $contents; } public static function mb_chr($code, $encoding = null) { if (0x80 > ($code %= 0x200000)) { $s = \chr($code); } elseif (0x800 > $code) { $s = \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f); } elseif (0x10000 > $code) { $s = \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f); } else { $s = \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f); } if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) { $s = \mb_convert_encoding($s, $encoding, 'UTF-8'); } return $s; } public static function mb_ord($s, $encoding = null) { if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) { $s = \mb_convert_encoding($s, 'UTF-8', $encoding); } if (1 === \strlen($s)) { return \ord($s); } $code = ($s = \unpack('C*', \substr($s, 0, 4))) ? $s[1] : 0; if (0xf0 <= $code) { return ($code - 0xf0 << 18) + ($s[2] - 0x80 << 12) + ($s[3] - 0x80 << 6) + $s[4] - 0x80; } if (0xe0 <= $code) { return ($code - 0xe0 << 12) + ($s[2] - 0x80 << 6) + $s[3] - 0x80; } if (0xc0 <= $code) { return ($code - 0xc0 << 6) + $s[2] - 0x80; } return $code; } private static function getSubpart($pos, $part, $haystack, $encoding) { if (\false === $pos) { return \false; } if ($part) { return self::mb_substr($haystack, 0, $pos, $encoding); } return self::mb_substr($haystack, $pos, null, $encoding); } private static function html_encoding_callback(array $m) { $i = 1; $entities = ''; $m = \unpack('C*', \htmlentities($m[0], \ENT_COMPAT, 'UTF-8')); while (isset($m[$i])) { if (0x80 > $m[$i]) { $entities .= \chr($m[$i++]); continue; } if (0xf0 <= $m[$i]) { $c = ($m[$i++] - 0xf0 << 18) + ($m[$i++] - 0x80 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80; } elseif (0xe0 <= $m[$i]) { $c = ($m[$i++] - 0xe0 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80; } else { $c = ($m[$i++] - 0xc0 << 6) + $m[$i++] - 0x80; } $entities .= '&#' . $c . ';'; } return $entities; } private static function title_case(array $s) { return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8') . self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8'); } private static function getData($file) { if (\file_exists($file = __DIR__ . '/Resources/unidata/' . $file . '.php')) { return require $file; } return \false; } private static function getEncoding($encoding) { if (null === $encoding) { return self::$internalEncoding; } if ('UTF-8' === $encoding) { return 'UTF-8'; } $encoding = \strtoupper($encoding); if ('8BIT' === $encoding || 'BINARY' === $encoding) { return 'CP850'; } if ('UTF8' === $encoding) { return 'UTF-8'; } return $encoding; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use _HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring as p; if (!\function_exists('mb_convert_encoding')) { function mb_convert_encoding($s, $to, $from = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_convert_encoding($s, $to, $from); } } if (!\function_exists('mb_decode_mimeheader')) { function mb_decode_mimeheader($s) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_decode_mimeheader($s); } } if (!\function_exists('mb_encode_mimeheader')) { function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); } } if (!\function_exists('mb_decode_numericentity')) { function mb_decode_numericentity($s, $convmap, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_decode_numericentity($s, $convmap, $enc); } } if (!\function_exists('mb_encode_numericentity')) { function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = \false) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); } } if (!\function_exists('mb_convert_case')) { function mb_convert_case($s, $mode, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_convert_case($s, $mode, $enc); } } if (!\function_exists('mb_internal_encoding')) { function mb_internal_encoding($enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_internal_encoding($enc); } } if (!\function_exists('mb_language')) { function mb_language($lang = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_language($lang); } } if (!\function_exists('mb_list_encodings')) { function mb_list_encodings() { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_list_encodings(); } } if (!\function_exists('mb_encoding_aliases')) { function mb_encoding_aliases($encoding) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_encoding_aliases($encoding); } } if (!\function_exists('mb_check_encoding')) { function mb_check_encoding($var = null, $encoding = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_check_encoding($var, $encoding); } } if (!\function_exists('mb_detect_encoding')) { function mb_detect_encoding($str, $encodingList = null, $strict = \false) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_detect_encoding($str, $encodingList, $strict); } } if (!\function_exists('mb_detect_order')) { function mb_detect_order($encodingList = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_detect_order($encodingList); } } if (!\function_exists('mb_parse_str')) { function mb_parse_str($s, &$result = array()) { \parse_str($s, $result); } } if (!\function_exists('mb_strlen')) { function mb_strlen($s, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strlen($s, $enc); } } if (!\function_exists('mb_strpos')) { function mb_strpos($s, $needle, $offset = 0, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strpos($s, $needle, $offset, $enc); } } if (!\function_exists('mb_strtolower')) { function mb_strtolower($s, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strtolower($s, $enc); } } if (!\function_exists('mb_strtoupper')) { function mb_strtoupper($s, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strtoupper($s, $enc); } } if (!\function_exists('mb_substitute_character')) { function mb_substitute_character($char = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_substitute_character($char); } } if (!\function_exists('mb_substr')) { function mb_substr($s, $start, $length = 2147483647, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_substr($s, $start, $length, $enc); } } if (!\function_exists('mb_stripos')) { function mb_stripos($s, $needle, $offset = 0, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_stripos($s, $needle, $offset, $enc); } } if (!\function_exists('mb_stristr')) { function mb_stristr($s, $needle, $part = \false, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_stristr($s, $needle, $part, $enc); } } if (!\function_exists('mb_strrchr')) { function mb_strrchr($s, $needle, $part = \false, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strrchr($s, $needle, $part, $enc); } } if (!\function_exists('mb_strrichr')) { function mb_strrichr($s, $needle, $part = \false, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strrichr($s, $needle, $part, $enc); } } if (!\function_exists('mb_strripos')) { function mb_strripos($s, $needle, $offset = 0, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strripos($s, $needle, $offset, $enc); } } if (!\function_exists('mb_strrpos')) { function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strrpos($s, $needle, $offset, $enc); } } if (!\function_exists('mb_strstr')) { function mb_strstr($s, $needle, $part = \false, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strstr($s, $needle, $part, $enc); } } if (!\function_exists('mb_get_info')) { function mb_get_info($type = 'all') { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_get_info($type); } } if (!\function_exists('mb_http_output')) { function mb_http_output($enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_http_output($enc); } } if (!\function_exists('mb_strwidth')) { function mb_strwidth($s, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_strwidth($s, $enc); } } if (!\function_exists('mb_substr_count')) { function mb_substr_count($haystack, $needle, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_substr_count($haystack, $needle, $enc); } } if (!\function_exists('mb_output_handler')) { function mb_output_handler($contents, $status) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_output_handler($contents, $status); } } if (!\function_exists('mb_http_input')) { function mb_http_input($type = '') { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_http_input($type); } } if (!\function_exists('mb_convert_variables')) { function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); } } if (!\function_exists('mb_ord')) { function mb_ord($s, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_ord($s, $enc); } } if (!\function_exists('mb_chr')) { function mb_chr($code, $enc = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_chr($code, $enc); } } if (!\function_exists('mb_scrub')) { function mb_scrub($s, $enc = null) { $enc = null === $enc ? \mb_internal_encoding() : $enc; return \mb_convert_encoding($s, $enc, $enc); } } if (!\function_exists('mb_str_split')) { function mb_str_split($string, $split_length = 1, $encoding = null) { return \_HumbugBoxd02f763d3c56\Symfony\Polyfill\Mbstring\Mbstring::mb_str_split($string, $split_length, $encoding); } } if (\extension_loaded('mbstring')) { return; } if (!\defined('MB_CASE_UPPER')) { \define('MB_CASE_UPPER', 0); } if (!\defined('MB_CASE_LOWER')) { \define('MB_CASE_LOWER', 1); } if (!\defined('MB_CASE_TITLE')) { \define('MB_CASE_TITLE', 2); } Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e', 'F' => 'f', 'G' => 'g', 'H' => 'h', 'I' => 'i', 'J' => 'j', 'K' => 'k', 'L' => 'l', 'M' => 'm', 'N' => 'n', 'O' => 'o', 'P' => 'p', 'Q' => 'q', 'R' => 'r', 'S' => 's', 'T' => 't', 'U' => 'u', 'V' => 'v', 'W' => 'w', 'X' => 'x', 'Y' => 'y', 'Z' => 'z', 'À' => 'à', 'Á' => 'á', 'Â' => 'â', 'Ã' => 'ã', 'Ä' => 'ä', 'Å' => 'å', 'Æ' => 'æ', 'Ç' => 'ç', 'È' => 'è', 'É' => 'é', 'Ê' => 'ê', 'Ë' => 'ë', 'Ì' => 'ì', 'Í' => 'í', 'Î' => 'î', 'Ï' => 'ï', 'Ð' => 'ð', 'Ñ' => 'ñ', 'Ò' => 'ò', 'Ó' => 'ó', 'Ô' => 'ô', 'Õ' => 'õ', 'Ö' => 'ö', 'Ø' => 'ø', 'Ù' => 'ù', 'Ú' => 'ú', 'Û' => 'û', 'Ü' => 'ü', 'Ý' => 'ý', 'Þ' => 'þ', 'Ā' => 'ā', 'Ă' => 'ă', 'Ą' => 'ą', 'Ć' => 'ć', 'Ĉ' => 'ĉ', 'Ċ' => 'ċ', 'Č' => 'č', 'Ď' => 'ď', 'Đ' => 'đ', 'Ē' => 'ē', 'Ĕ' => 'ĕ', 'Ė' => 'ė', 'Ę' => 'ę', 'Ě' => 'ě', 'Ĝ' => 'ĝ', 'Ğ' => 'ğ', 'Ġ' => 'ġ', 'Ģ' => 'ģ', 'Ĥ' => 'ĥ', 'Ħ' => 'ħ', 'Ĩ' => 'ĩ', 'Ī' => 'ī', 'Ĭ' => 'ĭ', 'Į' => 'į', 'İ' => 'i', 'IJ' => 'ij', 'Ĵ' => 'ĵ', 'Ķ' => 'ķ', 'Ĺ' => 'ĺ', 'Ļ' => 'ļ', 'Ľ' => 'ľ', 'Ŀ' => 'ŀ', 'Ł' => 'ł', 'Ń' => 'ń', 'Ņ' => 'ņ', 'Ň' => 'ň', 'Ŋ' => 'ŋ', 'Ō' => 'ō', 'Ŏ' => 'ŏ', 'Ő' => 'ő', 'Œ' => 'œ', 'Ŕ' => 'ŕ', 'Ŗ' => 'ŗ', 'Ř' => 'ř', 'Ś' => 'ś', 'Ŝ' => 'ŝ', 'Ş' => 'ş', 'Š' => 'š', 'Ţ' => 'ţ', 'Ť' => 'ť', 'Ŧ' => 'ŧ', 'Ũ' => 'ũ', 'Ū' => 'ū', 'Ŭ' => 'ŭ', 'Ů' => 'ů', 'Ű' => 'ű', 'Ų' => 'ų', 'Ŵ' => 'ŵ', 'Ŷ' => 'ŷ', 'Ÿ' => 'ÿ', 'Ź' => 'ź', 'Ż' => 'ż', 'Ž' => 'ž', 'Ɓ' => 'ɓ', 'Ƃ' => 'ƃ', 'Ƅ' => 'ƅ', 'Ɔ' => 'ɔ', 'Ƈ' => 'ƈ', 'Ɖ' => 'ɖ', 'Ɗ' => 'ɗ', 'Ƌ' => 'ƌ', 'Ǝ' => 'ǝ', 'Ə' => 'ə', 'Ɛ' => 'ɛ', 'Ƒ' => 'ƒ', 'Ɠ' => 'ɠ', 'Ɣ' => 'ɣ', 'Ɩ' => 'ɩ', 'Ɨ' => 'ɨ', 'Ƙ' => 'ƙ', 'Ɯ' => 'ɯ', 'Ɲ' => 'ɲ', 'Ɵ' => 'ɵ', 'Ơ' => 'ơ', 'Ƣ' => 'ƣ', 'Ƥ' => 'ƥ', 'Ʀ' => 'ʀ', 'Ƨ' => 'ƨ', 'Ʃ' => 'ʃ', 'Ƭ' => 'ƭ', 'Ʈ' => 'ʈ', 'Ư' => 'ư', 'Ʊ' => 'ʊ', 'Ʋ' => 'ʋ', 'Ƴ' => 'ƴ', 'Ƶ' => 'ƶ', 'Ʒ' => 'ʒ', 'Ƹ' => 'ƹ', 'Ƽ' => 'ƽ', 'DŽ' => 'dž', 'Dž' => 'dž', 'LJ' => 'lj', 'Lj' => 'lj', 'NJ' => 'nj', 'Nj' => 'nj', 'Ǎ' => 'ǎ', 'Ǐ' => 'ǐ', 'Ǒ' => 'ǒ', 'Ǔ' => 'ǔ', 'Ǖ' => 'ǖ', 'Ǘ' => 'ǘ', 'Ǚ' => 'ǚ', 'Ǜ' => 'ǜ', 'Ǟ' => 'ǟ', 'Ǡ' => 'ǡ', 'Ǣ' => 'ǣ', 'Ǥ' => 'ǥ', 'Ǧ' => 'ǧ', 'Ǩ' => 'ǩ', 'Ǫ' => 'ǫ', 'Ǭ' => 'ǭ', 'Ǯ' => 'ǯ', 'DZ' => 'dz', 'Dz' => 'dz', 'Ǵ' => 'ǵ', 'Ƕ' => 'ƕ', 'Ƿ' => 'ƿ', 'Ǹ' => 'ǹ', 'Ǻ' => 'ǻ', 'Ǽ' => 'ǽ', 'Ǿ' => 'ǿ', 'Ȁ' => 'ȁ', 'Ȃ' => 'ȃ', 'Ȅ' => 'ȅ', 'Ȇ' => 'ȇ', 'Ȉ' => 'ȉ', 'Ȋ' => 'ȋ', 'Ȍ' => 'ȍ', 'Ȏ' => 'ȏ', 'Ȑ' => 'ȑ', 'Ȓ' => 'ȓ', 'Ȕ' => 'ȕ', 'Ȗ' => 'ȗ', 'Ș' => 'ș', 'Ț' => 'ț', 'Ȝ' => 'ȝ', 'Ȟ' => 'ȟ', 'Ƞ' => 'ƞ', 'Ȣ' => 'ȣ', 'Ȥ' => 'ȥ', 'Ȧ' => 'ȧ', 'Ȩ' => 'ȩ', 'Ȫ' => 'ȫ', 'Ȭ' => 'ȭ', 'Ȯ' => 'ȯ', 'Ȱ' => 'ȱ', 'Ȳ' => 'ȳ', 'Ⱥ' => 'ⱥ', 'Ȼ' => 'ȼ', 'Ƚ' => 'ƚ', 'Ⱦ' => 'ⱦ', 'Ɂ' => 'ɂ', 'Ƀ' => 'ƀ', 'Ʉ' => 'ʉ', 'Ʌ' => 'ʌ', 'Ɇ' => 'ɇ', 'Ɉ' => 'ɉ', 'Ɋ' => 'ɋ', 'Ɍ' => 'ɍ', 'Ɏ' => 'ɏ', 'Ͱ' => 'ͱ', 'Ͳ' => 'ͳ', 'Ͷ' => 'ͷ', 'Ϳ' => 'ϳ', 'Ά' => 'ά', 'Έ' => 'έ', 'Ή' => 'ή', 'Ί' => 'ί', 'Ό' => 'ό', 'Ύ' => 'ύ', 'Ώ' => 'ώ', 'Α' => 'α', 'Β' => 'β', 'Γ' => 'γ', 'Δ' => 'δ', 'Ε' => 'ε', 'Ζ' => 'ζ', 'Η' => 'η', 'Θ' => 'θ', 'Ι' => 'ι', 'Κ' => 'κ', 'Λ' => 'λ', 'Μ' => 'μ', 'Ν' => 'ν', 'Ξ' => 'ξ', 'Ο' => 'ο', 'Π' => 'π', 'Ρ' => 'ρ', 'Σ' => 'σ', 'Τ' => 'τ', 'Υ' => 'υ', 'Φ' => 'φ', 'Χ' => 'χ', 'Ψ' => 'ψ', 'Ω' => 'ω', 'Ϊ' => 'ϊ', 'Ϋ' => 'ϋ', 'Ϗ' => 'ϗ', 'Ϙ' => 'ϙ', 'Ϛ' => 'ϛ', 'Ϝ' => 'ϝ', 'Ϟ' => 'ϟ', 'Ϡ' => 'ϡ', 'Ϣ' => 'ϣ', 'Ϥ' => 'ϥ', 'Ϧ' => 'ϧ', 'Ϩ' => 'ϩ', 'Ϫ' => 'ϫ', 'Ϭ' => 'ϭ', 'Ϯ' => 'ϯ', 'ϴ' => 'θ', 'Ϸ' => 'ϸ', 'Ϲ' => 'ϲ', 'Ϻ' => 'ϻ', 'Ͻ' => 'ͻ', 'Ͼ' => 'ͼ', 'Ͽ' => 'ͽ', 'Ѐ' => 'ѐ', 'Ё' => 'ё', 'Ђ' => 'ђ', 'Ѓ' => 'ѓ', 'Є' => 'є', 'Ѕ' => 'ѕ', 'І' => 'і', 'Ї' => 'ї', 'Ј' => 'ј', 'Љ' => 'љ', 'Њ' => 'њ', 'Ћ' => 'ћ', 'Ќ' => 'ќ', 'Ѝ' => 'ѝ', 'Ў' => 'ў', 'Џ' => 'џ', 'А' => 'а', 'Б' => 'б', 'В' => 'в', 'Г' => 'г', 'Д' => 'д', 'Е' => 'е', 'Ж' => 'ж', 'З' => 'з', 'И' => 'и', 'Й' => 'й', 'К' => 'к', 'Л' => 'л', 'М' => 'м', 'Н' => 'н', 'О' => 'о', 'П' => 'п', 'Р' => 'р', 'С' => 'с', 'Т' => 'т', 'У' => 'у', 'Ф' => 'ф', 'Х' => 'х', 'Ц' => 'ц', 'Ч' => 'ч', 'Ш' => 'ш', 'Щ' => 'щ', 'Ъ' => 'ъ', 'Ы' => 'ы', 'Ь' => 'ь', 'Э' => 'э', 'Ю' => 'ю', 'Я' => 'я', 'Ѡ' => 'ѡ', 'Ѣ' => 'ѣ', 'Ѥ' => 'ѥ', 'Ѧ' => 'ѧ', 'Ѩ' => 'ѩ', 'Ѫ' => 'ѫ', 'Ѭ' => 'ѭ', 'Ѯ' => 'ѯ', 'Ѱ' => 'ѱ', 'Ѳ' => 'ѳ', 'Ѵ' => 'ѵ', 'Ѷ' => 'ѷ', 'Ѹ' => 'ѹ', 'Ѻ' => 'ѻ', 'Ѽ' => 'ѽ', 'Ѿ' => 'ѿ', 'Ҁ' => 'ҁ', 'Ҋ' => 'ҋ', 'Ҍ' => 'ҍ', 'Ҏ' => 'ҏ', 'Ґ' => 'ґ', 'Ғ' => 'ғ', 'Ҕ' => 'ҕ', 'Җ' => 'җ', 'Ҙ' => 'ҙ', 'Қ' => 'қ', 'Ҝ' => 'ҝ', 'Ҟ' => 'ҟ', 'Ҡ' => 'ҡ', 'Ң' => 'ң', 'Ҥ' => 'ҥ', 'Ҧ' => 'ҧ', 'Ҩ' => 'ҩ', 'Ҫ' => 'ҫ', 'Ҭ' => 'ҭ', 'Ү' => 'ү', 'Ұ' => 'ұ', 'Ҳ' => 'ҳ', 'Ҵ' => 'ҵ', 'Ҷ' => 'ҷ', 'Ҹ' => 'ҹ', 'Һ' => 'һ', 'Ҽ' => 'ҽ', 'Ҿ' => 'ҿ', 'Ӏ' => 'ӏ', 'Ӂ' => 'ӂ', 'Ӄ' => 'ӄ', 'Ӆ' => 'ӆ', 'Ӈ' => 'ӈ', 'Ӊ' => 'ӊ', 'Ӌ' => 'ӌ', 'Ӎ' => 'ӎ', 'Ӑ' => 'ӑ', 'Ӓ' => 'ӓ', 'Ӕ' => 'ӕ', 'Ӗ' => 'ӗ', 'Ә' => 'ә', 'Ӛ' => 'ӛ', 'Ӝ' => 'ӝ', 'Ӟ' => 'ӟ', 'Ӡ' => 'ӡ', 'Ӣ' => 'ӣ', 'Ӥ' => 'ӥ', 'Ӧ' => 'ӧ', 'Ө' => 'ө', 'Ӫ' => 'ӫ', 'Ӭ' => 'ӭ', 'Ӯ' => 'ӯ', 'Ӱ' => 'ӱ', 'Ӳ' => 'ӳ', 'Ӵ' => 'ӵ', 'Ӷ' => 'ӷ', 'Ӹ' => 'ӹ', 'Ӻ' => 'ӻ', 'Ӽ' => 'ӽ', 'Ӿ' => 'ӿ', 'Ԁ' => 'ԁ', 'Ԃ' => 'ԃ', 'Ԅ' => 'ԅ', 'Ԇ' => 'ԇ', 'Ԉ' => 'ԉ', 'Ԋ' => 'ԋ', 'Ԍ' => 'ԍ', 'Ԏ' => 'ԏ', 'Ԑ' => 'ԑ', 'Ԓ' => 'ԓ', 'Ԕ' => 'ԕ', 'Ԗ' => 'ԗ', 'Ԙ' => 'ԙ', 'Ԛ' => 'ԛ', 'Ԝ' => 'ԝ', 'Ԟ' => 'ԟ', 'Ԡ' => 'ԡ', 'Ԣ' => 'ԣ', 'Ԥ' => 'ԥ', 'Ԧ' => 'ԧ', 'Ԩ' => 'ԩ', 'Ԫ' => 'ԫ', 'Ԭ' => 'ԭ', 'Ԯ' => 'ԯ', 'Ա' => 'ա', 'Բ' => 'բ', 'Գ' => 'գ', 'Դ' => 'դ', 'Ե' => 'ե', 'Զ' => 'զ', 'Է' => 'է', 'Ը' => 'ը', 'Թ' => 'թ', 'Ժ' => 'ժ', 'Ի' => 'ի', 'Լ' => 'լ', 'Խ' => 'խ', 'Ծ' => 'ծ', 'Կ' => 'կ', 'Հ' => 'հ', 'Ձ' => 'ձ', 'Ղ' => 'ղ', 'Ճ' => 'ճ', 'Մ' => 'մ', 'Յ' => 'յ', 'Ն' => 'ն', 'Շ' => 'շ', 'Ո' => 'ո', 'Չ' => 'չ', 'Պ' => 'պ', 'Ջ' => 'ջ', 'Ռ' => 'ռ', 'Ս' => 'ս', 'Վ' => 'վ', 'Տ' => 'տ', 'Ր' => 'ր', 'Ց' => 'ց', 'Ւ' => 'ւ', 'Փ' => 'փ', 'Ք' => 'ք', 'Օ' => 'օ', 'Ֆ' => 'ֆ', 'Ⴀ' => 'ⴀ', 'Ⴁ' => 'ⴁ', 'Ⴂ' => 'ⴂ', 'Ⴃ' => 'ⴃ', 'Ⴄ' => 'ⴄ', 'Ⴅ' => 'ⴅ', 'Ⴆ' => 'ⴆ', 'Ⴇ' => 'ⴇ', 'Ⴈ' => 'ⴈ', 'Ⴉ' => 'ⴉ', 'Ⴊ' => 'ⴊ', 'Ⴋ' => 'ⴋ', 'Ⴌ' => 'ⴌ', 'Ⴍ' => 'ⴍ', 'Ⴎ' => 'ⴎ', 'Ⴏ' => 'ⴏ', 'Ⴐ' => 'ⴐ', 'Ⴑ' => 'ⴑ', 'Ⴒ' => 'ⴒ', 'Ⴓ' => 'ⴓ', 'Ⴔ' => 'ⴔ', 'Ⴕ' => 'ⴕ', 'Ⴖ' => 'ⴖ', 'Ⴗ' => 'ⴗ', 'Ⴘ' => 'ⴘ', 'Ⴙ' => 'ⴙ', 'Ⴚ' => 'ⴚ', 'Ⴛ' => 'ⴛ', 'Ⴜ' => 'ⴜ', 'Ⴝ' => 'ⴝ', 'Ⴞ' => 'ⴞ', 'Ⴟ' => 'ⴟ', 'Ⴠ' => 'ⴠ', 'Ⴡ' => 'ⴡ', 'Ⴢ' => 'ⴢ', 'Ⴣ' => 'ⴣ', 'Ⴤ' => 'ⴤ', 'Ⴥ' => 'ⴥ', 'Ⴧ' => 'ⴧ', 'Ⴭ' => 'ⴭ', 'Ꭰ' => 'ꭰ', 'Ꭱ' => 'ꭱ', 'Ꭲ' => 'ꭲ', 'Ꭳ' => 'ꭳ', 'Ꭴ' => 'ꭴ', 'Ꭵ' => 'ꭵ', 'Ꭶ' => 'ꭶ', 'Ꭷ' => 'ꭷ', 'Ꭸ' => 'ꭸ', 'Ꭹ' => 'ꭹ', 'Ꭺ' => 'ꭺ', 'Ꭻ' => 'ꭻ', 'Ꭼ' => 'ꭼ', 'Ꭽ' => 'ꭽ', 'Ꭾ' => 'ꭾ', 'Ꭿ' => 'ꭿ', 'Ꮀ' => 'ꮀ', 'Ꮁ' => 'ꮁ', 'Ꮂ' => 'ꮂ', 'Ꮃ' => 'ꮃ', 'Ꮄ' => 'ꮄ', 'Ꮅ' => 'ꮅ', 'Ꮆ' => 'ꮆ', 'Ꮇ' => 'ꮇ', 'Ꮈ' => 'ꮈ', 'Ꮉ' => 'ꮉ', 'Ꮊ' => 'ꮊ', 'Ꮋ' => 'ꮋ', 'Ꮌ' => 'ꮌ', 'Ꮍ' => 'ꮍ', 'Ꮎ' => 'ꮎ', 'Ꮏ' => 'ꮏ', 'Ꮐ' => 'ꮐ', 'Ꮑ' => 'ꮑ', 'Ꮒ' => 'ꮒ', 'Ꮓ' => 'ꮓ', 'Ꮔ' => 'ꮔ', 'Ꮕ' => 'ꮕ', 'Ꮖ' => 'ꮖ', 'Ꮗ' => 'ꮗ', 'Ꮘ' => 'ꮘ', 'Ꮙ' => 'ꮙ', 'Ꮚ' => 'ꮚ', 'Ꮛ' => 'ꮛ', 'Ꮜ' => 'ꮜ', 'Ꮝ' => 'ꮝ', 'Ꮞ' => 'ꮞ', 'Ꮟ' => 'ꮟ', 'Ꮠ' => 'ꮠ', 'Ꮡ' => 'ꮡ', 'Ꮢ' => 'ꮢ', 'Ꮣ' => 'ꮣ', 'Ꮤ' => 'ꮤ', 'Ꮥ' => 'ꮥ', 'Ꮦ' => 'ꮦ', 'Ꮧ' => 'ꮧ', 'Ꮨ' => 'ꮨ', 'Ꮩ' => 'ꮩ', 'Ꮪ' => 'ꮪ', 'Ꮫ' => 'ꮫ', 'Ꮬ' => 'ꮬ', 'Ꮭ' => 'ꮭ', 'Ꮮ' => 'ꮮ', 'Ꮯ' => 'ꮯ', 'Ꮰ' => 'ꮰ', 'Ꮱ' => 'ꮱ', 'Ꮲ' => 'ꮲ', 'Ꮳ' => 'ꮳ', 'Ꮴ' => 'ꮴ', 'Ꮵ' => 'ꮵ', 'Ꮶ' => 'ꮶ', 'Ꮷ' => 'ꮷ', 'Ꮸ' => 'ꮸ', 'Ꮹ' => 'ꮹ', 'Ꮺ' => 'ꮺ', 'Ꮻ' => 'ꮻ', 'Ꮼ' => 'ꮼ', 'Ꮽ' => 'ꮽ', 'Ꮾ' => 'ꮾ', 'Ꮿ' => 'ꮿ', 'Ᏸ' => 'ᏸ', 'Ᏹ' => 'ᏹ', 'Ᏺ' => 'ᏺ', 'Ᏻ' => 'ᏻ', 'Ᏼ' => 'ᏼ', 'Ᏽ' => 'ᏽ', 'Ა' => 'ა', 'Ბ' => 'ბ', 'Გ' => 'გ', 'Დ' => 'დ', 'Ე' => 'ე', 'Ვ' => 'ვ', 'Ზ' => 'ზ', 'Თ' => 'თ', 'Ი' => 'ი', 'Კ' => 'კ', 'Ლ' => 'ლ', 'Მ' => 'მ', 'Ნ' => 'ნ', 'Ო' => 'ო', 'Პ' => 'პ', 'Ჟ' => 'ჟ', 'Რ' => 'რ', 'Ს' => 'ს', 'Ტ' => 'ტ', 'Უ' => 'უ', 'Ფ' => 'ფ', 'Ქ' => 'ქ', 'Ღ' => 'ღ', 'Ყ' => 'ყ', 'Შ' => 'შ', 'Ჩ' => 'ჩ', 'Ც' => 'ც', 'Ძ' => 'ძ', 'Წ' => 'წ', 'Ჭ' => 'ჭ', 'Ხ' => 'ხ', 'Ჯ' => 'ჯ', 'Ჰ' => 'ჰ', 'Ჱ' => 'ჱ', 'Ჲ' => 'ჲ', 'Ჳ' => 'ჳ', 'Ჴ' => 'ჴ', 'Ჵ' => 'ჵ', 'Ჶ' => 'ჶ', 'Ჷ' => 'ჷ', 'Ჸ' => 'ჸ', 'Ჹ' => 'ჹ', 'Ჺ' => 'ჺ', 'Ჽ' => 'ჽ', 'Ჾ' => 'ჾ', 'Ჿ' => 'ჿ', 'Ḁ' => 'ḁ', 'Ḃ' => 'ḃ', 'Ḅ' => 'ḅ', 'Ḇ' => 'ḇ', 'Ḉ' => 'ḉ', 'Ḋ' => 'ḋ', 'Ḍ' => 'ḍ', 'Ḏ' => 'ḏ', 'Ḑ' => 'ḑ', 'Ḓ' => 'ḓ', 'Ḕ' => 'ḕ', 'Ḗ' => 'ḗ', 'Ḙ' => 'ḙ', 'Ḛ' => 'ḛ', 'Ḝ' => 'ḝ', 'Ḟ' => 'ḟ', 'Ḡ' => 'ḡ', 'Ḣ' => 'ḣ', 'Ḥ' => 'ḥ', 'Ḧ' => 'ḧ', 'Ḩ' => 'ḩ', 'Ḫ' => 'ḫ', 'Ḭ' => 'ḭ', 'Ḯ' => 'ḯ', 'Ḱ' => 'ḱ', 'Ḳ' => 'ḳ', 'Ḵ' => 'ḵ', 'Ḷ' => 'ḷ', 'Ḹ' => 'ḹ', 'Ḻ' => 'ḻ', 'Ḽ' => 'ḽ', 'Ḿ' => 'ḿ', 'Ṁ' => 'ṁ', 'Ṃ' => 'ṃ', 'Ṅ' => 'ṅ', 'Ṇ' => 'ṇ', 'Ṉ' => 'ṉ', 'Ṋ' => 'ṋ', 'Ṍ' => 'ṍ', 'Ṏ' => 'ṏ', 'Ṑ' => 'ṑ', 'Ṓ' => 'ṓ', 'Ṕ' => 'ṕ', 'Ṗ' => 'ṗ', 'Ṙ' => 'ṙ', 'Ṛ' => 'ṛ', 'Ṝ' => 'ṝ', 'Ṟ' => 'ṟ', 'Ṡ' => 'ṡ', 'Ṣ' => 'ṣ', 'Ṥ' => 'ṥ', 'Ṧ' => 'ṧ', 'Ṩ' => 'ṩ', 'Ṫ' => 'ṫ', 'Ṭ' => 'ṭ', 'Ṯ' => 'ṯ', 'Ṱ' => 'ṱ', 'Ṳ' => 'ṳ', 'Ṵ' => 'ṵ', 'Ṷ' => 'ṷ', 'Ṹ' => 'ṹ', 'Ṻ' => 'ṻ', 'Ṽ' => 'ṽ', 'Ṿ' => 'ṿ', 'Ẁ' => 'ẁ', 'Ẃ' => 'ẃ', 'Ẅ' => 'ẅ', 'Ẇ' => 'ẇ', 'Ẉ' => 'ẉ', 'Ẋ' => 'ẋ', 'Ẍ' => 'ẍ', 'Ẏ' => 'ẏ', 'Ẑ' => 'ẑ', 'Ẓ' => 'ẓ', 'Ẕ' => 'ẕ', 'ẞ' => 'ß', 'Ạ' => 'ạ', 'Ả' => 'ả', 'Ấ' => 'ấ', 'Ầ' => 'ầ', 'Ẩ' => 'ẩ', 'Ẫ' => 'ẫ', 'Ậ' => 'ậ', 'Ắ' => 'ắ', 'Ằ' => 'ằ', 'Ẳ' => 'ẳ', 'Ẵ' => 'ẵ', 'Ặ' => 'ặ', 'Ẹ' => 'ẹ', 'Ẻ' => 'ẻ', 'Ẽ' => 'ẽ', 'Ế' => 'ế', 'Ề' => 'ề', 'Ể' => 'ể', 'Ễ' => 'ễ', 'Ệ' => 'ệ', 'Ỉ' => 'ỉ', 'Ị' => 'ị', 'Ọ' => 'ọ', 'Ỏ' => 'ỏ', 'Ố' => 'ố', 'Ồ' => 'ồ', 'Ổ' => 'ổ', 'Ỗ' => 'ỗ', 'Ộ' => 'ộ', 'Ớ' => 'ớ', 'Ờ' => 'ờ', 'Ở' => 'ở', 'Ỡ' => 'ỡ', 'Ợ' => 'ợ', 'Ụ' => 'ụ', 'Ủ' => 'ủ', 'Ứ' => 'ứ', 'Ừ' => 'ừ', 'Ử' => 'ử', 'Ữ' => 'ữ', 'Ự' => 'ự', 'Ỳ' => 'ỳ', 'Ỵ' => 'ỵ', 'Ỷ' => 'ỷ', 'Ỹ' => 'ỹ', 'Ỻ' => 'ỻ', 'Ỽ' => 'ỽ', 'Ỿ' => 'ỿ', 'Ἀ' => 'ἀ', 'Ἁ' => 'ἁ', 'Ἂ' => 'ἂ', 'Ἃ' => 'ἃ', 'Ἄ' => 'ἄ', 'Ἅ' => 'ἅ', 'Ἆ' => 'ἆ', 'Ἇ' => 'ἇ', 'Ἐ' => 'ἐ', 'Ἑ' => 'ἑ', 'Ἒ' => 'ἒ', 'Ἓ' => 'ἓ', 'Ἔ' => 'ἔ', 'Ἕ' => 'ἕ', 'Ἠ' => 'ἠ', 'Ἡ' => 'ἡ', 'Ἢ' => 'ἢ', 'Ἣ' => 'ἣ', 'Ἤ' => 'ἤ', 'Ἥ' => 'ἥ', 'Ἦ' => 'ἦ', 'Ἧ' => 'ἧ', 'Ἰ' => 'ἰ', 'Ἱ' => 'ἱ', 'Ἲ' => 'ἲ', 'Ἳ' => 'ἳ', 'Ἴ' => 'ἴ', 'Ἵ' => 'ἵ', 'Ἶ' => 'ἶ', 'Ἷ' => 'ἷ', 'Ὀ' => 'ὀ', 'Ὁ' => 'ὁ', 'Ὂ' => 'ὂ', 'Ὃ' => 'ὃ', 'Ὄ' => 'ὄ', 'Ὅ' => 'ὅ', 'Ὑ' => 'ὑ', 'Ὓ' => 'ὓ', 'Ὕ' => 'ὕ', 'Ὗ' => 'ὗ', 'Ὠ' => 'ὠ', 'Ὡ' => 'ὡ', 'Ὢ' => 'ὢ', 'Ὣ' => 'ὣ', 'Ὤ' => 'ὤ', 'Ὥ' => 'ὥ', 'Ὦ' => 'ὦ', 'Ὧ' => 'ὧ', 'ᾈ' => 'ᾀ', 'ᾉ' => 'ᾁ', 'ᾊ' => 'ᾂ', 'ᾋ' => 'ᾃ', 'ᾌ' => 'ᾄ', 'ᾍ' => 'ᾅ', 'ᾎ' => 'ᾆ', 'ᾏ' => 'ᾇ', 'ᾘ' => 'ᾐ', 'ᾙ' => 'ᾑ', 'ᾚ' => 'ᾒ', 'ᾛ' => 'ᾓ', 'ᾜ' => 'ᾔ', 'ᾝ' => 'ᾕ', 'ᾞ' => 'ᾖ', 'ᾟ' => 'ᾗ', 'ᾨ' => 'ᾠ', 'ᾩ' => 'ᾡ', 'ᾪ' => 'ᾢ', 'ᾫ' => 'ᾣ', 'ᾬ' => 'ᾤ', 'ᾭ' => 'ᾥ', 'ᾮ' => 'ᾦ', 'ᾯ' => 'ᾧ', 'Ᾰ' => 'ᾰ', 'Ᾱ' => 'ᾱ', 'Ὰ' => 'ὰ', 'Ά' => 'ά', 'ᾼ' => 'ᾳ', 'Ὲ' => 'ὲ', 'Έ' => 'έ', 'Ὴ' => 'ὴ', 'Ή' => 'ή', 'ῌ' => 'ῃ', 'Ῐ' => 'ῐ', 'Ῑ' => 'ῑ', 'Ὶ' => 'ὶ', 'Ί' => 'ί', 'Ῠ' => 'ῠ', 'Ῡ' => 'ῡ', 'Ὺ' => 'ὺ', 'Ύ' => 'ύ', 'Ῥ' => 'ῥ', 'Ὸ' => 'ὸ', 'Ό' => 'ό', 'Ὼ' => 'ὼ', 'Ώ' => 'ώ', 'ῼ' => 'ῳ', 'Ω' => 'ω', 'K' => 'k', 'Å' => 'å', 'Ⅎ' => 'ⅎ', 'Ⅰ' => 'ⅰ', 'Ⅱ' => 'ⅱ', 'Ⅲ' => 'ⅲ', 'Ⅳ' => 'ⅳ', 'Ⅴ' => 'ⅴ', 'Ⅵ' => 'ⅵ', 'Ⅶ' => 'ⅶ', 'Ⅷ' => 'ⅷ', 'Ⅸ' => 'ⅸ', 'Ⅹ' => 'ⅹ', 'Ⅺ' => 'ⅺ', 'Ⅻ' => 'ⅻ', 'Ⅼ' => 'ⅼ', 'Ⅽ' => 'ⅽ', 'Ⅾ' => 'ⅾ', 'Ⅿ' => 'ⅿ', 'Ↄ' => 'ↄ', 'Ⓐ' => 'ⓐ', 'Ⓑ' => 'ⓑ', 'Ⓒ' => 'ⓒ', 'Ⓓ' => 'ⓓ', 'Ⓔ' => 'ⓔ', 'Ⓕ' => 'ⓕ', 'Ⓖ' => 'ⓖ', 'Ⓗ' => 'ⓗ', 'Ⓘ' => 'ⓘ', 'Ⓙ' => 'ⓙ', 'Ⓚ' => 'ⓚ', 'Ⓛ' => 'ⓛ', 'Ⓜ' => 'ⓜ', 'Ⓝ' => 'ⓝ', 'Ⓞ' => 'ⓞ', 'Ⓟ' => 'ⓟ', 'Ⓠ' => 'ⓠ', 'Ⓡ' => 'ⓡ', 'Ⓢ' => 'ⓢ', 'Ⓣ' => 'ⓣ', 'Ⓤ' => 'ⓤ', 'Ⓥ' => 'ⓥ', 'Ⓦ' => 'ⓦ', 'Ⓧ' => 'ⓧ', 'Ⓨ' => 'ⓨ', 'Ⓩ' => 'ⓩ', 'Ⰰ' => 'ⰰ', 'Ⰱ' => 'ⰱ', 'Ⰲ' => 'ⰲ', 'Ⰳ' => 'ⰳ', 'Ⰴ' => 'ⰴ', 'Ⰵ' => 'ⰵ', 'Ⰶ' => 'ⰶ', 'Ⰷ' => 'ⰷ', 'Ⰸ' => 'ⰸ', 'Ⰹ' => 'ⰹ', 'Ⰺ' => 'ⰺ', 'Ⰻ' => 'ⰻ', 'Ⰼ' => 'ⰼ', 'Ⰽ' => 'ⰽ', 'Ⰾ' => 'ⰾ', 'Ⰿ' => 'ⰿ', 'Ⱀ' => 'ⱀ', 'Ⱁ' => 'ⱁ', 'Ⱂ' => 'ⱂ', 'Ⱃ' => 'ⱃ', 'Ⱄ' => 'ⱄ', 'Ⱅ' => 'ⱅ', 'Ⱆ' => 'ⱆ', 'Ⱇ' => 'ⱇ', 'Ⱈ' => 'ⱈ', 'Ⱉ' => 'ⱉ', 'Ⱊ' => 'ⱊ', 'Ⱋ' => 'ⱋ', 'Ⱌ' => 'ⱌ', 'Ⱍ' => 'ⱍ', 'Ⱎ' => 'ⱎ', 'Ⱏ' => 'ⱏ', 'Ⱐ' => 'ⱐ', 'Ⱑ' => 'ⱑ', 'Ⱒ' => 'ⱒ', 'Ⱓ' => 'ⱓ', 'Ⱔ' => 'ⱔ', 'Ⱕ' => 'ⱕ', 'Ⱖ' => 'ⱖ', 'Ⱗ' => 'ⱗ', 'Ⱘ' => 'ⱘ', 'Ⱙ' => 'ⱙ', 'Ⱚ' => 'ⱚ', 'Ⱛ' => 'ⱛ', 'Ⱜ' => 'ⱜ', 'Ⱝ' => 'ⱝ', 'Ⱞ' => 'ⱞ', 'Ⱡ' => 'ⱡ', 'Ɫ' => 'ɫ', 'Ᵽ' => 'ᵽ', 'Ɽ' => 'ɽ', 'Ⱨ' => 'ⱨ', 'Ⱪ' => 'ⱪ', 'Ⱬ' => 'ⱬ', 'Ɑ' => 'ɑ', 'Ɱ' => 'ɱ', 'Ɐ' => 'ɐ', 'Ɒ' => 'ɒ', 'Ⱳ' => 'ⱳ', 'Ⱶ' => 'ⱶ', 'Ȿ' => 'ȿ', 'Ɀ' => 'ɀ', 'Ⲁ' => 'ⲁ', 'Ⲃ' => 'ⲃ', 'Ⲅ' => 'ⲅ', 'Ⲇ' => 'ⲇ', 'Ⲉ' => 'ⲉ', 'Ⲋ' => 'ⲋ', 'Ⲍ' => 'ⲍ', 'Ⲏ' => 'ⲏ', 'Ⲑ' => 'ⲑ', 'Ⲓ' => 'ⲓ', 'Ⲕ' => 'ⲕ', 'Ⲗ' => 'ⲗ', 'Ⲙ' => 'ⲙ', 'Ⲛ' => 'ⲛ', 'Ⲝ' => 'ⲝ', 'Ⲟ' => 'ⲟ', 'Ⲡ' => 'ⲡ', 'Ⲣ' => 'ⲣ', 'Ⲥ' => 'ⲥ', 'Ⲧ' => 'ⲧ', 'Ⲩ' => 'ⲩ', 'Ⲫ' => 'ⲫ', 'Ⲭ' => 'ⲭ', 'Ⲯ' => 'ⲯ', 'Ⲱ' => 'ⲱ', 'Ⲳ' => 'ⲳ', 'Ⲵ' => 'ⲵ', 'Ⲷ' => 'ⲷ', 'Ⲹ' => 'ⲹ', 'Ⲻ' => 'ⲻ', 'Ⲽ' => 'ⲽ', 'Ⲿ' => 'ⲿ', 'Ⳁ' => 'ⳁ', 'Ⳃ' => 'ⳃ', 'Ⳅ' => 'ⳅ', 'Ⳇ' => 'ⳇ', 'Ⳉ' => 'ⳉ', 'Ⳋ' => 'ⳋ', 'Ⳍ' => 'ⳍ', 'Ⳏ' => 'ⳏ', 'Ⳑ' => 'ⳑ', 'Ⳓ' => 'ⳓ', 'Ⳕ' => 'ⳕ', 'Ⳗ' => 'ⳗ', 'Ⳙ' => 'ⳙ', 'Ⳛ' => 'ⳛ', 'Ⳝ' => 'ⳝ', 'Ⳟ' => 'ⳟ', 'Ⳡ' => 'ⳡ', 'Ⳣ' => 'ⳣ', 'Ⳬ' => 'ⳬ', 'Ⳮ' => 'ⳮ', 'Ⳳ' => 'ⳳ', 'Ꙁ' => 'ꙁ', 'Ꙃ' => 'ꙃ', 'Ꙅ' => 'ꙅ', 'Ꙇ' => 'ꙇ', 'Ꙉ' => 'ꙉ', 'Ꙋ' => 'ꙋ', 'Ꙍ' => 'ꙍ', 'Ꙏ' => 'ꙏ', 'Ꙑ' => 'ꙑ', 'Ꙓ' => 'ꙓ', 'Ꙕ' => 'ꙕ', 'Ꙗ' => 'ꙗ', 'Ꙙ' => 'ꙙ', 'Ꙛ' => 'ꙛ', 'Ꙝ' => 'ꙝ', 'Ꙟ' => 'ꙟ', 'Ꙡ' => 'ꙡ', 'Ꙣ' => 'ꙣ', 'Ꙥ' => 'ꙥ', 'Ꙧ' => 'ꙧ', 'Ꙩ' => 'ꙩ', 'Ꙫ' => 'ꙫ', 'Ꙭ' => 'ꙭ', 'Ꚁ' => 'ꚁ', 'Ꚃ' => 'ꚃ', 'Ꚅ' => 'ꚅ', 'Ꚇ' => 'ꚇ', 'Ꚉ' => 'ꚉ', 'Ꚋ' => 'ꚋ', 'Ꚍ' => 'ꚍ', 'Ꚏ' => 'ꚏ', 'Ꚑ' => 'ꚑ', 'Ꚓ' => 'ꚓ', 'Ꚕ' => 'ꚕ', 'Ꚗ' => 'ꚗ', 'Ꚙ' => 'ꚙ', 'Ꚛ' => 'ꚛ', 'Ꜣ' => 'ꜣ', 'Ꜥ' => 'ꜥ', 'Ꜧ' => 'ꜧ', 'Ꜩ' => 'ꜩ', 'Ꜫ' => 'ꜫ', 'Ꜭ' => 'ꜭ', 'Ꜯ' => 'ꜯ', 'Ꜳ' => 'ꜳ', 'Ꜵ' => 'ꜵ', 'Ꜷ' => 'ꜷ', 'Ꜹ' => 'ꜹ', 'Ꜻ' => 'ꜻ', 'Ꜽ' => 'ꜽ', 'Ꜿ' => 'ꜿ', 'Ꝁ' => 'ꝁ', 'Ꝃ' => 'ꝃ', 'Ꝅ' => 'ꝅ', 'Ꝇ' => 'ꝇ', 'Ꝉ' => 'ꝉ', 'Ꝋ' => 'ꝋ', 'Ꝍ' => 'ꝍ', 'Ꝏ' => 'ꝏ', 'Ꝑ' => 'ꝑ', 'Ꝓ' => 'ꝓ', 'Ꝕ' => 'ꝕ', 'Ꝗ' => 'ꝗ', 'Ꝙ' => 'ꝙ', 'Ꝛ' => 'ꝛ', 'Ꝝ' => 'ꝝ', 'Ꝟ' => 'ꝟ', 'Ꝡ' => 'ꝡ', 'Ꝣ' => 'ꝣ', 'Ꝥ' => 'ꝥ', 'Ꝧ' => 'ꝧ', 'Ꝩ' => 'ꝩ', 'Ꝫ' => 'ꝫ', 'Ꝭ' => 'ꝭ', 'Ꝯ' => 'ꝯ', 'Ꝺ' => 'ꝺ', 'Ꝼ' => 'ꝼ', 'Ᵹ' => 'ᵹ', 'Ꝿ' => 'ꝿ', 'Ꞁ' => 'ꞁ', 'Ꞃ' => 'ꞃ', 'Ꞅ' => 'ꞅ', 'Ꞇ' => 'ꞇ', 'Ꞌ' => 'ꞌ', 'Ɥ' => 'ɥ', 'Ꞑ' => 'ꞑ', 'Ꞓ' => 'ꞓ', 'Ꞗ' => 'ꞗ', 'Ꞙ' => 'ꞙ', 'Ꞛ' => 'ꞛ', 'Ꞝ' => 'ꞝ', 'Ꞟ' => 'ꞟ', 'Ꞡ' => 'ꞡ', 'Ꞣ' => 'ꞣ', 'Ꞥ' => 'ꞥ', 'Ꞧ' => 'ꞧ', 'Ꞩ' => 'ꞩ', 'Ɦ' => 'ɦ', 'Ɜ' => 'ɜ', 'Ɡ' => 'ɡ', 'Ɬ' => 'ɬ', 'Ɪ' => 'ɪ', 'Ʞ' => 'ʞ', 'Ʇ' => 'ʇ', 'Ʝ' => 'ʝ', 'Ꭓ' => 'ꭓ', 'Ꞵ' => 'ꞵ', 'Ꞷ' => 'ꞷ', 'Ꞹ' => 'ꞹ', 'Ꞻ' => 'ꞻ', 'Ꞽ' => 'ꞽ', 'Ꞿ' => 'ꞿ', 'Ꟃ' => 'ꟃ', 'Ꞔ' => 'ꞔ', 'Ʂ' => 'ʂ', 'Ᶎ' => 'ᶎ', 'Ꟈ' => 'ꟈ', 'Ꟊ' => 'ꟊ', 'Ꟶ' => 'ꟶ', 'A' => 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e', 'F' => 'f', 'G' => 'g', 'H' => 'h', 'I' => 'i', 'J' => 'j', 'K' => 'k', 'L' => 'l', 'M' => 'm', 'N' => 'n', 'O' => 'o', 'P' => 'p', 'Q' => 'q', 'R' => 'r', 'S' => 's', 'T' => 't', 'U' => 'u', 'V' => 'v', 'W' => 'w', 'X' => 'x', 'Y' => 'y', 'Z' => 'z', '𐐀' => '𐐨', '𐐁' => '𐐩', '𐐂' => '𐐪', '𐐃' => '𐐫', '𐐄' => '𐐬', '𐐅' => '𐐭', '𐐆' => '𐐮', '𐐇' => '𐐯', '𐐈' => '𐐰', '𐐉' => '𐐱', '𐐊' => '𐐲', '𐐋' => '𐐳', '𐐌' => '𐐴', '𐐍' => '𐐵', '𐐎' => '𐐶', '𐐏' => '𐐷', '𐐐' => '𐐸', '𐐑' => '𐐹', '𐐒' => '𐐺', '𐐓' => '𐐻', '𐐔' => '𐐼', '𐐕' => '𐐽', '𐐖' => '𐐾', '𐐗' => '𐐿', '𐐘' => '𐑀', '𐐙' => '𐑁', '𐐚' => '𐑂', '𐐛' => '𐑃', '𐐜' => '𐑄', '𐐝' => '𐑅', '𐐞' => '𐑆', '𐐟' => '𐑇', '𐐠' => '𐑈', '𐐡' => '𐑉', '𐐢' => '𐑊', '𐐣' => '𐑋', '𐐤' => '𐑌', '𐐥' => '𐑍', '𐐦' => '𐑎', '𐐧' => '𐑏', '𐒰' => '𐓘', '𐒱' => '𐓙', '𐒲' => '𐓚', '𐒳' => '𐓛', '𐒴' => '𐓜', '𐒵' => '𐓝', '𐒶' => '𐓞', '𐒷' => '𐓟', '𐒸' => '𐓠', '𐒹' => '𐓡', '𐒺' => '𐓢', '𐒻' => '𐓣', '𐒼' => '𐓤', '𐒽' => '𐓥', '𐒾' => '𐓦', '𐒿' => '𐓧', '𐓀' => '𐓨', '𐓁' => '𐓩', '𐓂' => '𐓪', '𐓃' => '𐓫', '𐓄' => '𐓬', '𐓅' => '𐓭', '𐓆' => '𐓮', '𐓇' => '𐓯', '𐓈' => '𐓰', '𐓉' => '𐓱', '𐓊' => '𐓲', '𐓋' => '𐓳', '𐓌' => '𐓴', '𐓍' => '𐓵', '𐓎' => '𐓶', '𐓏' => '𐓷', '𐓐' => '𐓸', '𐓑' => '𐓹', '𐓒' => '𐓺', '𐓓' => '𐓻', '𐲀' => '𐳀', '𐲁' => '𐳁', '𐲂' => '𐳂', '𐲃' => '𐳃', '𐲄' => '𐳄', '𐲅' => '𐳅', '𐲆' => '𐳆', '𐲇' => '𐳇', '𐲈' => '𐳈', '𐲉' => '𐳉', '𐲊' => '𐳊', '𐲋' => '𐳋', '𐲌' => '𐳌', '𐲍' => '𐳍', '𐲎' => '𐳎', '𐲏' => '𐳏', '𐲐' => '𐳐', '𐲑' => '𐳑', '𐲒' => '𐳒', '𐲓' => '𐳓', '𐲔' => '𐳔', '𐲕' => '𐳕', '𐲖' => '𐳖', '𐲗' => '𐳗', '𐲘' => '𐳘', '𐲙' => '𐳙', '𐲚' => '𐳚', '𐲛' => '𐳛', '𐲜' => '𐳜', '𐲝' => '𐳝', '𐲞' => '𐳞', '𐲟' => '𐳟', '𐲠' => '𐳠', '𐲡' => '𐳡', '𐲢' => '𐳢', '𐲣' => '𐳣', '𐲤' => '𐳤', '𐲥' => '𐳥', '𐲦' => '𐳦', '𐲧' => '𐳧', '𐲨' => '𐳨', '𐲩' => '𐳩', '𐲪' => '𐳪', '𐲫' => '𐳫', '𐲬' => '𐳬', '𐲭' => '𐳭', '𐲮' => '𐳮', '𐲯' => '𐳯', '𐲰' => '𐳰', '𐲱' => '𐳱', '𐲲' => '𐳲', '𑢠' => '𑣀', '𑢡' => '𑣁', '𑢢' => '𑣂', '𑢣' => '𑣃', '𑢤' => '𑣄', '𑢥' => '𑣅', '𑢦' => '𑣆', '𑢧' => '𑣇', '𑢨' => '𑣈', '𑢩' => '𑣉', '𑢪' => '𑣊', '𑢫' => '𑣋', '𑢬' => '𑣌', '𑢭' => '𑣍', '𑢮' => '𑣎', '𑢯' => '𑣏', '𑢰' => '𑣐', '𑢱' => '𑣑', '𑢲' => '𑣒', '𑢳' => '𑣓', '𑢴' => '𑣔', '𑢵' => '𑣕', '𑢶' => '𑣖', '𑢷' => '𑣗', '𑢸' => '𑣘', '𑢹' => '𑣙', '𑢺' => '𑣚', '𑢻' => '𑣛', '𑢼' => '𑣜', '𑢽' => '𑣝', '𑢾' => '𑣞', '𑢿' => '𑣟', '𖹀' => '𖹠', '𖹁' => '𖹡', '𖹂' => '𖹢', '𖹃' => '𖹣', '𖹄' => '𖹤', '𖹅' => '𖹥', '𖹆' => '𖹦', '𖹇' => '𖹧', '𖹈' => '𖹨', '𖹉' => '𖹩', '𖹊' => '𖹪', '𖹋' => '𖹫', '𖹌' => '𖹬', '𖹍' => '𖹭', '𖹎' => '𖹮', '𖹏' => '𖹯', '𖹐' => '𖹰', '𖹑' => '𖹱', '𖹒' => '𖹲', '𖹓' => '𖹳', '𖹔' => '𖹴', '𖹕' => '𖹵', '𖹖' => '𖹶', '𖹗' => '𖹷', '𖹘' => '𖹸', '𖹙' => '𖹹', '𖹚' => '𖹺', '𖹛' => '𖹻', '𖹜' => '𖹼', '𖹝' => '𖹽', '𖹞' => '𖹾', '𖹟' => '𖹿', '𞤀' => '𞤢', '𞤁' => '𞤣', '𞤂' => '𞤤', '𞤃' => '𞤥', '𞤄' => '𞤦', '𞤅' => '𞤧', '𞤆' => '𞤨', '𞤇' => '𞤩', '𞤈' => '𞤪', '𞤉' => '𞤫', '𞤊' => '𞤬', '𞤋' => '𞤭', '𞤌' => '𞤮', '𞤍' => '𞤯', '𞤎' => '𞤰', '𞤏' => '𞤱', '𞤐' => '𞤲', '𞤑' => '𞤳', '𞤒' => '𞤴', '𞤓' => '𞤵', '𞤔' => '𞤶', '𞤕' => '𞤷', '𞤖' => '𞤸', '𞤗' => '𞤹', '𞤘' => '𞤺', '𞤙' => '𞤻', '𞤚' => '𞤼', '𞤛' => '𞤽', '𞤜' => '𞤾', '𞤝' => '𞤿', '𞤞' => '𞥀', '𞤟' => '𞥁', '𞤠' => '𞥂', '𞤡' => '𞥃'); 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D', 'e' => 'E', 'f' => 'F', 'g' => 'G', 'h' => 'H', 'i' => 'I', 'j' => 'J', 'k' => 'K', 'l' => 'L', 'm' => 'M', 'n' => 'N', 'o' => 'O', 'p' => 'P', 'q' => 'Q', 'r' => 'R', 's' => 'S', 't' => 'T', 'u' => 'U', 'v' => 'V', 'w' => 'W', 'x' => 'X', 'y' => 'Y', 'z' => 'Z', 'µ' => 'Μ', 'à' => 'À', 'á' => 'Á', 'â' => 'Â', 'ã' => 'Ã', 'ä' => 'Ä', 'å' => 'Å', 'æ' => 'Æ', 'ç' => 'Ç', 'è' => 'È', 'é' => 'É', 'ê' => 'Ê', 'ë' => 'Ë', 'ì' => 'Ì', 'í' => 'Í', 'î' => 'Î', 'ï' => 'Ï', 'ð' => 'Ð', 'ñ' => 'Ñ', 'ò' => 'Ò', 'ó' => 'Ó', 'ô' => 'Ô', 'õ' => 'Õ', 'ö' => 'Ö', 'ø' => 'Ø', 'ù' => 'Ù', 'ú' => 'Ú', 'û' => 'Û', 'ü' => 'Ü', 'ý' => 'Ý', 'þ' => 'Þ', 'ÿ' => 'Ÿ', 'ā' => 'Ā', 'ă' => 'Ă', 'ą' => 'Ą', 'ć' => 'Ć', 'ĉ' => 'Ĉ', 'ċ' => 'Ċ', 'č' => 'Č', 'ď' => 'Ď', 'đ' => 'Đ', 'ē' => 'Ē', 'ĕ' => 'Ĕ', 'ė' => 'Ė', 'ę' => 'Ę', 'ě' => 'Ě', 'ĝ' => 'Ĝ', 'ğ' => 'Ğ', 'ġ' => 'Ġ', 'ģ' => 'Ģ', 'ĥ' => 'Ĥ', 'ħ' => 'Ħ', 'ĩ' => 'Ĩ', 'ī' => 'Ī', 'ĭ' => 'Ĭ', 'į' => 'Į', 'ı' => 'I', 'ij' => 'IJ', 'ĵ' => 'Ĵ', 'ķ' => 'Ķ', 'ĺ' => 'Ĺ', 'ļ' => 'Ļ', 'ľ' => 'Ľ', 'ŀ' => 'Ŀ', 'ł' => 'Ł', 'ń' => 'Ń', 'ņ' => 'Ņ', 'ň' => 'Ň', 'ŋ' => 'Ŋ', 'ō' => 'Ō', 'ŏ' => 'Ŏ', 'ő' => 'Ő', 'œ' => 'Œ', 'ŕ' => 'Ŕ', 'ŗ' => 'Ŗ', 'ř' => 'Ř', 'ś' => 'Ś', 'ŝ' => 'Ŝ', 'ş' => 'Ş', 'š' => 'Š', 'ţ' => 'Ţ', 'ť' => 'Ť', 'ŧ' => 'Ŧ', 'ũ' => 'Ũ', 'ū' => 'Ū', 'ŭ' => 'Ŭ', 'ů' => 'Ů', 'ű' => 'Ű', 'ų' => 'Ų', 'ŵ' => 'Ŵ', 'ŷ' => 'Ŷ', 'ź' => 'Ź', 'ż' => 'Ż', 'ž' => 'Ž', 'ſ' => 'S', 'ƀ' => 'Ƀ', 'ƃ' => 'Ƃ', 'ƅ' => 'Ƅ', 'ƈ' => 'Ƈ', 'ƌ' => 'Ƌ', 'ƒ' => 'Ƒ', 'ƕ' => 'Ƕ', 'ƙ' => 'Ƙ', 'ƚ' => 'Ƚ', 'ƞ' => 'Ƞ', 'ơ' => 'Ơ', 'ƣ' => 'Ƣ', 'ƥ' => 'Ƥ', 'ƨ' => 'Ƨ', 'ƭ' => 'Ƭ', 'ư' => 'Ư', 'ƴ' => 'Ƴ', 'ƶ' => 'Ƶ', 'ƹ' => 'Ƹ', 'ƽ' => 'Ƽ', 'ƿ' => 'Ƿ', 'Dž' => 'DŽ', 'dž' => 'DŽ', 'Lj' => 'LJ', 'lj' => 'LJ', 'Nj' => 'NJ', 'nj' => 'NJ', 'ǎ' => 'Ǎ', 'ǐ' => 'Ǐ', 'ǒ' => 'Ǒ', 'ǔ' => 'Ǔ', 'ǖ' => 'Ǖ', 'ǘ' => 'Ǘ', 'ǚ' => 'Ǚ', 'ǜ' => 'Ǜ', 'ǝ' => 'Ǝ', 'ǟ' => 'Ǟ', 'ǡ' => 'Ǡ', 'ǣ' => 'Ǣ', 'ǥ' => 'Ǥ', 'ǧ' => 'Ǧ', 'ǩ' => 'Ǩ', 'ǫ' => 'Ǫ', 'ǭ' => 'Ǭ', 'ǯ' => 'Ǯ', 'Dz' => 'DZ', 'dz' => 'DZ', 'ǵ' => 'Ǵ', 'ǹ' => 'Ǹ', 'ǻ' => 'Ǻ', 'ǽ' => 'Ǽ', 'ǿ' => 'Ǿ', 'ȁ' => 'Ȁ', 'ȃ' => 'Ȃ', 'ȅ' => 'Ȅ', 'ȇ' => 'Ȇ', 'ȉ' => 'Ȉ', 'ȋ' => 'Ȋ', 'ȍ' => 'Ȍ', 'ȏ' => 'Ȏ', 'ȑ' => 'Ȑ', 'ȓ' => 'Ȓ', 'ȕ' => 'Ȕ', 'ȗ' => 'Ȗ', 'ș' => 'Ș', 'ț' => 'Ț', 'ȝ' => 'Ȝ', 'ȟ' => 'Ȟ', 'ȣ' => 'Ȣ', 'ȥ' => 'Ȥ', 'ȧ' => 'Ȧ', 'ȩ' => 'Ȩ', 'ȫ' => 'Ȫ', 'ȭ' => 'Ȭ', 'ȯ' => 'Ȯ', 'ȱ' => 'Ȱ', 'ȳ' => 'Ȳ', 'ȼ' => 'Ȼ', 'ȿ' => 'Ȿ', 'ɀ' => 'Ɀ', 'ɂ' => 'Ɂ', 'ɇ' => 'Ɇ', 'ɉ' => 'Ɉ', 'ɋ' => 'Ɋ', 'ɍ' => 'Ɍ', 'ɏ' => 'Ɏ', 'ɐ' => 'Ɐ', 'ɑ' => 'Ɑ', 'ɒ' => 'Ɒ', 'ɓ' => 'Ɓ', 'ɔ' => 'Ɔ', 'ɖ' => 'Ɖ', 'ɗ' => 'Ɗ', 'ə' => 'Ə', 'ɛ' => 'Ɛ', 'ɜ' => 'Ɜ', 'ɠ' => 'Ɠ', 'ɡ' => 'Ɡ', 'ɣ' => 'Ɣ', 'ɥ' => 'Ɥ', 'ɦ' => 'Ɦ', 'ɨ' => 'Ɨ', 'ɩ' => 'Ɩ', 'ɪ' => 'Ɪ', 'ɫ' => 'Ɫ', 'ɬ' => 'Ɬ', 'ɯ' => 'Ɯ', 'ɱ' => 'Ɱ', 'ɲ' => 'Ɲ', 'ɵ' => 'Ɵ', 'ɽ' => 'Ɽ', 'ʀ' => 'Ʀ', 'ʂ' => 'Ʂ', 'ʃ' => 'Ʃ', 'ʇ' => 'Ʇ', 'ʈ' => 'Ʈ', 'ʉ' => 'Ʉ', 'ʊ' => 'Ʊ', 'ʋ' => 'Ʋ', 'ʌ' => 'Ʌ', 'ʒ' => 'Ʒ', 'ʝ' => 'Ʝ', 'ʞ' => 'Ʞ', 'ͅ' => 'Ι', 'ͱ' => 'Ͱ', 'ͳ' => 'Ͳ', 'ͷ' => 'Ͷ', 'ͻ' => 'Ͻ', 'ͼ' => 'Ͼ', 'ͽ' => 'Ͽ', 'ά' => 'Ά', 'έ' => 'Έ', 'ή' => 'Ή', 'ί' => 'Ί', 'α' => 'Α', 'β' => 'Β', 'γ' => 'Γ', 'δ' => 'Δ', 'ε' => 'Ε', 'ζ' => 'Ζ', 'η' => 'Η', 'θ' => 'Θ', 'ι' => 'Ι', 'κ' => 'Κ', 'λ' => 'Λ', 'μ' => 'Μ', 'ν' => 'Ν', 'ξ' => 'Ξ', 'ο' => 'Ο', 'π' => 'Π', 'ρ' => 'Ρ', 'ς' => 'Σ', 'σ' => 'Σ', 'τ' => 'Τ', 'υ' => 'Υ', 'φ' => 'Φ', 'χ' => 'Χ', 'ψ' => 'Ψ', 'ω' => 'Ω', 'ϊ' => 'Ϊ', 'ϋ' => 'Ϋ', 'ό' => 'Ό', 'ύ' => 'Ύ', 'ώ' => 'Ώ', 'ϐ' => 'Β', 'ϑ' => 'Θ', 'ϕ' => 'Φ', 'ϖ' => 'Π', 'ϗ' => 'Ϗ', 'ϙ' => 'Ϙ', 'ϛ' => 'Ϛ', 'ϝ' => 'Ϝ', 'ϟ' => 'Ϟ', 'ϡ' => 'Ϡ', 'ϣ' => 'Ϣ', 'ϥ' => 'Ϥ', 'ϧ' => 'Ϧ', 'ϩ' => 'Ϩ', 'ϫ' => 'Ϫ', 'ϭ' => 'Ϭ', 'ϯ' => 'Ϯ', 'ϰ' => 'Κ', 'ϱ' => 'Ρ', 'ϲ' => 'Ϲ', 'ϳ' => 'Ϳ', 'ϵ' => 'Ε', 'ϸ' => 'Ϸ', 'ϻ' => 'Ϻ', 'а' => 'А', 'б' => 'Б', 'в' => 'В', 'г' => 'Г', 'д' => 'Д', 'е' => 'Е', 'ж' => 'Ж', 'з' => 'З', 'и' => 'И', 'й' => 'Й', 'к' => 'К', 'л' => 'Л', 'м' => 'М', 'н' => 'Н', 'о' => 'О', 'п' => 'П', 'р' => 'Р', 'с' => 'С', 'т' => 'Т', 'у' => 'У', 'ф' => 'Ф', 'х' => 'Х', 'ц' => 'Ц', 'ч' => 'Ч', 'ш' => 'Ш', 'щ' => 'Щ', 'ъ' => 'Ъ', 'ы' => 'Ы', 'ь' => 'Ь', 'э' => 'Э', 'ю' => 'Ю', 'я' => 'Я', 'ѐ' => 'Ѐ', 'ё' => 'Ё', 'ђ' => 'Ђ', 'ѓ' => 'Ѓ', 'є' => 'Є', 'ѕ' => 'Ѕ', 'і' => 'І', 'ї' => 'Ї', 'ј' => 'Ј', 'љ' => 'Љ', 'њ' => 'Њ', 'ћ' => 'Ћ', 'ќ' => 'Ќ', 'ѝ' => 'Ѝ', 'ў' => 'Ў', 'џ' => 'Џ', 'ѡ' => 'Ѡ', 'ѣ' => 'Ѣ', 'ѥ' => 'Ѥ', 'ѧ' => 'Ѧ', 'ѩ' => 'Ѩ', 'ѫ' => 'Ѫ', 'ѭ' => 'Ѭ', 'ѯ' => 'Ѯ', 'ѱ' => 'Ѱ', 'ѳ' => 'Ѳ', 'ѵ' => 'Ѵ', 'ѷ' => 'Ѷ', 'ѹ' => 'Ѹ', 'ѻ' => 'Ѻ', 'ѽ' => 'Ѽ', 'ѿ' => 'Ѿ', 'ҁ' => 'Ҁ', 'ҋ' => 'Ҋ', 'ҍ' => 'Ҍ', 'ҏ' => 'Ҏ', 'ґ' => 'Ґ', 'ғ' => 'Ғ', 'ҕ' => 'Ҕ', 'җ' => 'Җ', 'ҙ' => 'Ҙ', 'қ' => 'Қ', 'ҝ' => 'Ҝ', 'ҟ' => 'Ҟ', 'ҡ' => 'Ҡ', 'ң' => 'Ң', 'ҥ' => 'Ҥ', 'ҧ' => 'Ҧ', 'ҩ' => 'Ҩ', 'ҫ' => 'Ҫ', 'ҭ' => 'Ҭ', 'ү' => 'Ү', 'ұ' => 'Ұ', 'ҳ' => 'Ҳ', 'ҵ' => 'Ҵ', 'ҷ' => 'Ҷ', 'ҹ' => 'Ҹ', 'һ' => 'Һ', 'ҽ' => 'Ҽ', 'ҿ' => 'Ҿ', 'ӂ' => 'Ӂ', 'ӄ' => 'Ӄ', 'ӆ' => 'Ӆ', 'ӈ' => 'Ӈ', 'ӊ' => 'Ӊ', 'ӌ' => 'Ӌ', 'ӎ' => 'Ӎ', 'ӏ' => 'Ӏ', 'ӑ' => 'Ӑ', 'ӓ' => 'Ӓ', 'ӕ' => 'Ӕ', 'ӗ' => 'Ӗ', 'ә' => 'Ә', 'ӛ' => 'Ӛ', 'ӝ' => 'Ӝ', 'ӟ' => 'Ӟ', 'ӡ' => 'Ӡ', 'ӣ' => 'Ӣ', 'ӥ' => 'Ӥ', 'ӧ' => 'Ӧ', 'ө' => 'Ө', 'ӫ' => 'Ӫ', 'ӭ' => 'Ӭ', 'ӯ' => 'Ӯ', 'ӱ' => 'Ӱ', 'ӳ' => 'Ӳ', 'ӵ' => 'Ӵ', 'ӷ' => 'Ӷ', 'ӹ' => 'Ӹ', 'ӻ' => 'Ӻ', 'ӽ' => 'Ӽ', 'ӿ' => 'Ӿ', 'ԁ' => 'Ԁ', 'ԃ' => 'Ԃ', 'ԅ' => 'Ԅ', 'ԇ' => 'Ԇ', 'ԉ' => 'Ԉ', 'ԋ' => 'Ԋ', 'ԍ' => 'Ԍ', 'ԏ' => 'Ԏ', 'ԑ' => 'Ԑ', 'ԓ' => 'Ԓ', 'ԕ' => 'Ԕ', 'ԗ' => 'Ԗ', 'ԙ' => 'Ԙ', 'ԛ' => 'Ԛ', 'ԝ' => 'Ԝ', 'ԟ' => 'Ԟ', 'ԡ' => 'Ԡ', 'ԣ' => 'Ԣ', 'ԥ' => 'Ԥ', 'ԧ' => 'Ԧ', 'ԩ' => 'Ԩ', 'ԫ' => 'Ԫ', 'ԭ' => 'Ԭ', 'ԯ' => 'Ԯ', 'ա' => 'Ա', 'բ' => 'Բ', 'գ' => 'Գ', 'դ' => 'Դ', 'ե' => 'Ե', 'զ' => 'Զ', 'է' => 'Է', 'ը' => 'Ը', 'թ' => 'Թ', 'ժ' => 'Ժ', 'ի' => 'Ի', 'լ' => 'Լ', 'խ' => 'Խ', 'ծ' => 'Ծ', 'կ' => 'Կ', 'հ' => 'Հ', 'ձ' => 'Ձ', 'ղ' => 'Ղ', 'ճ' => 'Ճ', 'մ' => 'Մ', 'յ' => 'Յ', 'ն' => 'Ն', 'շ' => 'Շ', 'ո' => 'Ո', 'չ' => 'Չ', 'պ' => 'Պ', 'ջ' => 'Ջ', 'ռ' => 'Ռ', 'ս' => 'Ս', 'վ' => 'Վ', 'տ' => 'Տ', 'ր' => 'Ր', 'ց' => 'Ց', 'ւ' => 'Ւ', 'փ' => 'Փ', 'ք' => 'Ք', 'օ' => 'Օ', 'ֆ' => 'Ֆ', 'ა' => 'Ა', 'ბ' => 'Ბ', 'გ' => 'Გ', 'დ' => 'Დ', 'ე' => 'Ე', 'ვ' => 'Ვ', 'ზ' => 'Ზ', 'თ' => 'Თ', 'ი' => 'Ი', 'კ' => 'Კ', 'ლ' => 'Ლ', 'მ' => 'Მ', 'ნ' => 'Ნ', 'ო' => 'Ო', 'პ' => 'Პ', 'ჟ' => 'Ჟ', 'რ' => 'Რ', 'ს' => 'Ს', 'ტ' => 'Ტ', 'უ' => 'Უ', 'ფ' => 'Ფ', 'ქ' => 'Ქ', 'ღ' => 'Ღ', 'ყ' => 'Ყ', 'შ' => 'Შ', 'ჩ' => 'Ჩ', 'ც' => 'Ც', 'ძ' => 'Ძ', 'წ' => 'Წ', 'ჭ' => 'Ჭ', 'ხ' => 'Ხ', 'ჯ' => 'Ჯ', 'ჰ' => 'Ჰ', 'ჱ' => 'Ჱ', 'ჲ' => 'Ჲ', 'ჳ' => 'Ჳ', 'ჴ' => 'Ჴ', 'ჵ' => 'Ჵ', 'ჶ' => 'Ჶ', 'ჷ' => 'Ჷ', 'ჸ' => 'Ჸ', 'ჹ' => 'Ჹ', 'ჺ' => 'Ჺ', 'ჽ' => 'Ჽ', 'ჾ' => 'Ჾ', 'ჿ' => 'Ჿ', 'ᏸ' => 'Ᏸ', 'ᏹ' => 'Ᏹ', 'ᏺ' => 'Ᏺ', 'ᏻ' => 'Ᏻ', 'ᏼ' => 'Ᏼ', 'ᏽ' => 'Ᏽ', 'ᲀ' => 'В', 'ᲁ' => 'Д', 'ᲂ' => 'О', 'ᲃ' => 'С', 'ᲄ' => 'Т', 'ᲅ' => 'Т', 'ᲆ' => 'Ъ', 'ᲇ' => 'Ѣ', 'ᲈ' => 'Ꙋ', 'ᵹ' => 'Ᵹ', 'ᵽ' => 'Ᵽ', 'ᶎ' => 'Ᶎ', 'ḁ' => 'Ḁ', 'ḃ' => 'Ḃ', 'ḅ' => 'Ḅ', 'ḇ' => 'Ḇ', 'ḉ' => 'Ḉ', 'ḋ' => 'Ḋ', 'ḍ' => 'Ḍ', 'ḏ' => 'Ḏ', 'ḑ' => 'Ḑ', 'ḓ' => 'Ḓ', 'ḕ' => 'Ḕ', 'ḗ' => 'Ḗ', 'ḙ' => 'Ḙ', 'ḛ' => 'Ḛ', 'ḝ' => 'Ḝ', 'ḟ' => 'Ḟ', 'ḡ' => 'Ḡ', 'ḣ' => 'Ḣ', 'ḥ' => 'Ḥ', 'ḧ' => 'Ḧ', 'ḩ' => 'Ḩ', 'ḫ' => 'Ḫ', 'ḭ' => 'Ḭ', 'ḯ' => 'Ḯ', 'ḱ' => 'Ḱ', 'ḳ' => 'Ḳ', 'ḵ' => 'Ḵ', 'ḷ' => 'Ḷ', 'ḹ' => 'Ḹ', 'ḻ' => 'Ḻ', 'ḽ' => 'Ḽ', 'ḿ' => 'Ḿ', 'ṁ' => 'Ṁ', 'ṃ' => 'Ṃ', 'ṅ' => 'Ṅ', 'ṇ' => 'Ṇ', 'ṉ' => 'Ṉ', 'ṋ' => 'Ṋ', 'ṍ' => 'Ṍ', 'ṏ' => 'Ṏ', 'ṑ' => 'Ṑ', 'ṓ' => 'Ṓ', 'ṕ' => 'Ṕ', 'ṗ' => 'Ṗ', 'ṙ' => 'Ṙ', 'ṛ' => 'Ṛ', 'ṝ' => 'Ṝ', 'ṟ' => 'Ṟ', 'ṡ' => 'Ṡ', 'ṣ' => 'Ṣ', 'ṥ' => 'Ṥ', 'ṧ' => 'Ṧ', 'ṩ' => 'Ṩ', 'ṫ' => 'Ṫ', 'ṭ' => 'Ṭ', 'ṯ' => 'Ṯ', 'ṱ' => 'Ṱ', 'ṳ' => 'Ṳ', 'ṵ' => 'Ṵ', 'ṷ' => 'Ṷ', 'ṹ' => 'Ṹ', 'ṻ' => 'Ṻ', 'ṽ' => 'Ṽ', 'ṿ' => 'Ṿ', 'ẁ' => 'Ẁ', 'ẃ' => 'Ẃ', 'ẅ' => 'Ẅ', 'ẇ' => 'Ẇ', 'ẉ' => 'Ẉ', 'ẋ' => 'Ẋ', 'ẍ' => 'Ẍ', 'ẏ' => 'Ẏ', 'ẑ' => 'Ẑ', 'ẓ' => 'Ẓ', 'ẕ' => 'Ẕ', 'ẛ' => 'Ṡ', 'ạ' => 'Ạ', 'ả' => 'Ả', 'ấ' => 'Ấ', 'ầ' => 'Ầ', 'ẩ' => 'Ẩ', 'ẫ' => 'Ẫ', 'ậ' => 'Ậ', 'ắ' => 'Ắ', 'ằ' => 'Ằ', 'ẳ' => 'Ẳ', 'ẵ' => 'Ẵ', 'ặ' => 'Ặ', 'ẹ' => 'Ẹ', 'ẻ' => 'Ẻ', 'ẽ' => 'Ẽ', 'ế' => 'Ế', 'ề' => 'Ề', 'ể' => 'Ể', 'ễ' => 'Ễ', 'ệ' => 'Ệ', 'ỉ' => 'Ỉ', 'ị' => 'Ị', 'ọ' => 'Ọ', 'ỏ' => 'Ỏ', 'ố' => 'Ố', 'ồ' => 'Ồ', 'ổ' => 'Ổ', 'ỗ' => 'Ỗ', 'ộ' => 'Ộ', 'ớ' => 'Ớ', 'ờ' => 'Ờ', 'ở' => 'Ở', 'ỡ' => 'Ỡ', 'ợ' => 'Ợ', 'ụ' => 'Ụ', 'ủ' => 'Ủ', 'ứ' => 'Ứ', 'ừ' => 'Ừ', 'ử' => 'Ử', 'ữ' => 'Ữ', 'ự' => 'Ự', 'ỳ' => 'Ỳ', 'ỵ' => 'Ỵ', 'ỷ' => 'Ỷ', 'ỹ' => 'Ỹ', 'ỻ' => 'Ỻ', 'ỽ' => 'Ỽ', 'ỿ' => 'Ỿ', 'ἀ' => 'Ἀ', 'ἁ' => 'Ἁ', 'ἂ' => 'Ἂ', 'ἃ' => 'Ἃ', 'ἄ' => 'Ἄ', 'ἅ' => 'Ἅ', 'ἆ' => 'Ἆ', 'ἇ' => 'Ἇ', 'ἐ' => 'Ἐ', 'ἑ' => 'Ἑ', 'ἒ' => 'Ἒ', 'ἓ' => 'Ἓ', 'ἔ' => 'Ἔ', 'ἕ' => 'Ἕ', 'ἠ' => 'Ἠ', 'ἡ' => 'Ἡ', 'ἢ' => 'Ἢ', 'ἣ' => 'Ἣ', 'ἤ' => 'Ἤ', 'ἥ' => 'Ἥ', 'ἦ' => 'Ἦ', 'ἧ' => 'Ἧ', 'ἰ' => 'Ἰ', 'ἱ' => 'Ἱ', 'ἲ' => 'Ἲ', 'ἳ' => 'Ἳ', 'ἴ' => 'Ἴ', 'ἵ' => 'Ἵ', 'ἶ' => 'Ἶ', 'ἷ' => 'Ἷ', 'ὀ' => 'Ὀ', 'ὁ' => 'Ὁ', 'ὂ' => 'Ὂ', 'ὃ' => 'Ὃ', 'ὄ' => 'Ὄ', 'ὅ' => 'Ὅ', 'ὑ' => 'Ὑ', 'ὓ' => 'Ὓ', 'ὕ' => 'Ὕ', 'ὗ' => 'Ὗ', 'ὠ' => 'Ὠ', 'ὡ' => 'Ὡ', 'ὢ' => 'Ὢ', 'ὣ' => 'Ὣ', 'ὤ' => 'Ὤ', 'ὥ' => 'Ὥ', 'ὦ' => 'Ὦ', 'ὧ' => 'Ὧ', 'ὰ' => 'Ὰ', 'ά' => 'Ά', 'ὲ' => 'Ὲ', 'έ' => 'Έ', 'ὴ' => 'Ὴ', 'ή' => 'Ή', 'ὶ' => 'Ὶ', 'ί' => 'Ί', 'ὸ' => 'Ὸ', 'ό' => 'Ό', 'ὺ' => 'Ὺ', 'ύ' => 'Ύ', 'ὼ' => 'Ὼ', 'ώ' => 'Ώ', 'ᾀ' => 'ᾈ', 'ᾁ' => 'ᾉ', 'ᾂ' => 'ᾊ', 'ᾃ' => 'ᾋ', 'ᾄ' => 'ᾌ', 'ᾅ' => 'ᾍ', 'ᾆ' => 'ᾎ', 'ᾇ' => 'ᾏ', 'ᾐ' => 'ᾘ', 'ᾑ' => 'ᾙ', 'ᾒ' => 'ᾚ', 'ᾓ' => 'ᾛ', 'ᾔ' => 'ᾜ', 'ᾕ' => 'ᾝ', 'ᾖ' => 'ᾞ', 'ᾗ' => 'ᾟ', 'ᾠ' => 'ᾨ', 'ᾡ' => 'ᾩ', 'ᾢ' => 'ᾪ', 'ᾣ' => 'ᾫ', 'ᾤ' => 'ᾬ', 'ᾥ' => 'ᾭ', 'ᾦ' => 'ᾮ', 'ᾧ' => 'ᾯ', 'ᾰ' => 'Ᾰ', 'ᾱ' => 'Ᾱ', 'ᾳ' => 'ᾼ', 'ι' => 'Ι', 'ῃ' => 'ῌ', 'ῐ' => 'Ῐ', 'ῑ' => 'Ῑ', 'ῠ' => 'Ῠ', 'ῡ' => 'Ῡ', 'ῥ' => 'Ῥ', 'ῳ' => 'ῼ', 'ⅎ' => 'Ⅎ', 'ⅰ' => 'Ⅰ', 'ⅱ' => 'Ⅱ', 'ⅲ' => 'Ⅲ', 'ⅳ' => 'Ⅳ', 'ⅴ' => 'Ⅴ', 'ⅵ' => 'Ⅵ', 'ⅶ' => 'Ⅶ', 'ⅷ' => 'Ⅷ', 'ⅸ' => 'Ⅸ', 'ⅹ' => 'Ⅹ', 'ⅺ' => 'Ⅺ', 'ⅻ' => 'Ⅻ', 'ⅼ' => 'Ⅼ', 'ⅽ' => 'Ⅽ', 'ⅾ' => 'Ⅾ', 'ⅿ' => 'Ⅿ', 'ↄ' => 'Ↄ', 'ⓐ' => 'Ⓐ', 'ⓑ' => 'Ⓑ', 'ⓒ' => 'Ⓒ', 'ⓓ' => 'Ⓓ', 'ⓔ' => 'Ⓔ', 'ⓕ' => 'Ⓕ', 'ⓖ' => 'Ⓖ', 'ⓗ' => 'Ⓗ', 'ⓘ' => 'Ⓘ', 'ⓙ' => 'Ⓙ', 'ⓚ' => 'Ⓚ', 'ⓛ' => 'Ⓛ', 'ⓜ' => 'Ⓜ', 'ⓝ' => 'Ⓝ', 'ⓞ' => 'Ⓞ', 'ⓟ' => 'Ⓟ', 'ⓠ' => 'Ⓠ', 'ⓡ' => 'Ⓡ', 'ⓢ' => 'Ⓢ', 'ⓣ' => 'Ⓣ', 'ⓤ' => 'Ⓤ', 'ⓥ' => 'Ⓥ', 'ⓦ' => 'Ⓦ', 'ⓧ' => 'Ⓧ', 'ⓨ' => 'Ⓨ', 'ⓩ' => 'Ⓩ', 'ⰰ' => 'Ⰰ', 'ⰱ' => 'Ⰱ', 'ⰲ' => 'Ⰲ', 'ⰳ' => 'Ⰳ', 'ⰴ' => 'Ⰴ', 'ⰵ' => 'Ⰵ', 'ⰶ' => 'Ⰶ', 'ⰷ' => 'Ⰷ', 'ⰸ' => 'Ⰸ', 'ⰹ' => 'Ⰹ', 'ⰺ' => 'Ⰺ', 'ⰻ' => 'Ⰻ', 'ⰼ' => 'Ⰼ', 'ⰽ' => 'Ⰽ', 'ⰾ' => 'Ⰾ', 'ⰿ' => 'Ⰿ', 'ⱀ' => 'Ⱀ', 'ⱁ' => 'Ⱁ', 'ⱂ' => 'Ⱂ', 'ⱃ' => 'Ⱃ', 'ⱄ' => 'Ⱄ', 'ⱅ' => 'Ⱅ', 'ⱆ' => 'Ⱆ', 'ⱇ' => 'Ⱇ', 'ⱈ' => 'Ⱈ', 'ⱉ' => 'Ⱉ', 'ⱊ' => 'Ⱊ', 'ⱋ' => 'Ⱋ', 'ⱌ' => 'Ⱌ', 'ⱍ' => 'Ⱍ', 'ⱎ' => 'Ⱎ', 'ⱏ' => 'Ⱏ', 'ⱐ' => 'Ⱐ', 'ⱑ' => 'Ⱑ', 'ⱒ' => 'Ⱒ', 'ⱓ' => 'Ⱓ', 'ⱔ' => 'Ⱔ', 'ⱕ' => 'Ⱕ', 'ⱖ' => 'Ⱖ', 'ⱗ' => 'Ⱗ', 'ⱘ' => 'Ⱘ', 'ⱙ' => 'Ⱙ', 'ⱚ' => 'Ⱚ', 'ⱛ' => 'Ⱛ', 'ⱜ' => 'Ⱜ', 'ⱝ' => 'Ⱝ', 'ⱞ' => 'Ⱞ', 'ⱡ' => 'Ⱡ', 'ⱥ' => 'Ⱥ', 'ⱦ' => 'Ⱦ', 'ⱨ' => 'Ⱨ', 'ⱪ' => 'Ⱪ', 'ⱬ' => 'Ⱬ', 'ⱳ' => 'Ⱳ', 'ⱶ' => 'Ⱶ', 'ⲁ' => 'Ⲁ', 'ⲃ' => 'Ⲃ', 'ⲅ' => 'Ⲅ', 'ⲇ' => 'Ⲇ', 'ⲉ' => 'Ⲉ', 'ⲋ' => 'Ⲋ', 'ⲍ' => 'Ⲍ', 'ⲏ' => 'Ⲏ', 'ⲑ' => 'Ⲑ', 'ⲓ' => 'Ⲓ', 'ⲕ' => 'Ⲕ', 'ⲗ' => 'Ⲗ', 'ⲙ' => 'Ⲙ', 'ⲛ' => 'Ⲛ', 'ⲝ' => 'Ⲝ', 'ⲟ' => 'Ⲟ', 'ⲡ' => 'Ⲡ', 'ⲣ' => 'Ⲣ', 'ⲥ' => 'Ⲥ', 'ⲧ' => 'Ⲧ', 'ⲩ' => 'Ⲩ', 'ⲫ' => 'Ⲫ', 'ⲭ' => 'Ⲭ', 'ⲯ' => 'Ⲯ', 'ⲱ' => 'Ⲱ', 'ⲳ' => 'Ⲳ', 'ⲵ' => 'Ⲵ', 'ⲷ' => 'Ⲷ', 'ⲹ' => 'Ⲹ', 'ⲻ' => 'Ⲻ', 'ⲽ' => 'Ⲽ', 'ⲿ' => 'Ⲿ', 'ⳁ' => 'Ⳁ', 'ⳃ' => 'Ⳃ', 'ⳅ' => 'Ⳅ', 'ⳇ' => 'Ⳇ', 'ⳉ' => 'Ⳉ', 'ⳋ' => 'Ⳋ', 'ⳍ' => 'Ⳍ', 'ⳏ' => 'Ⳏ', 'ⳑ' => 'Ⳑ', 'ⳓ' => 'Ⳓ', 'ⳕ' => 'Ⳕ', 'ⳗ' => 'Ⳗ', 'ⳙ' => 'Ⳙ', 'ⳛ' => 'Ⳛ', 'ⳝ' => 'Ⳝ', 'ⳟ' => 'Ⳟ', 'ⳡ' => 'Ⳡ', 'ⳣ' => 'Ⳣ', 'ⳬ' => 'Ⳬ', 'ⳮ' => 'Ⳮ', 'ⳳ' => 'Ⳳ', 'ⴀ' => 'Ⴀ', 'ⴁ' => 'Ⴁ', 'ⴂ' => 'Ⴂ', 'ⴃ' => 'Ⴃ', 'ⴄ' => 'Ⴄ', 'ⴅ' => 'Ⴅ', 'ⴆ' => 'Ⴆ', 'ⴇ' => 'Ⴇ', 'ⴈ' => 'Ⴈ', 'ⴉ' => 'Ⴉ', 'ⴊ' => 'Ⴊ', 'ⴋ' => 'Ⴋ', 'ⴌ' => 'Ⴌ', 'ⴍ' => 'Ⴍ', 'ⴎ' => 'Ⴎ', 'ⴏ' => 'Ⴏ', 'ⴐ' => 'Ⴐ', 'ⴑ' => 'Ⴑ', 'ⴒ' => 'Ⴒ', 'ⴓ' => 'Ⴓ', 'ⴔ' => 'Ⴔ', 'ⴕ' => 'Ⴕ', 'ⴖ' => 'Ⴖ', 'ⴗ' => 'Ⴗ', 'ⴘ' => 'Ⴘ', 'ⴙ' => 'Ⴙ', 'ⴚ' => 'Ⴚ', 'ⴛ' => 'Ⴛ', 'ⴜ' => 'Ⴜ', 'ⴝ' => 'Ⴝ', 'ⴞ' => 'Ⴞ', 'ⴟ' => 'Ⴟ', 'ⴠ' => 'Ⴠ', 'ⴡ' => 'Ⴡ', 'ⴢ' => 'Ⴢ', 'ⴣ' => 'Ⴣ', 'ⴤ' => 'Ⴤ', 'ⴥ' => 'Ⴥ', 'ⴧ' => 'Ⴧ', 'ⴭ' => 'Ⴭ', 'ꙁ' => 'Ꙁ', 'ꙃ' => 'Ꙃ', 'ꙅ' => 'Ꙅ', 'ꙇ' => 'Ꙇ', 'ꙉ' => 'Ꙉ', 'ꙋ' => 'Ꙋ', 'ꙍ' => 'Ꙍ', 'ꙏ' => 'Ꙏ', 'ꙑ' => 'Ꙑ', 'ꙓ' => 'Ꙓ', 'ꙕ' => 'Ꙕ', 'ꙗ' => 'Ꙗ', 'ꙙ' => 'Ꙙ', 'ꙛ' => 'Ꙛ', 'ꙝ' => 'Ꙝ', 'ꙟ' => 'Ꙟ', 'ꙡ' => 'Ꙡ', 'ꙣ' => 'Ꙣ', 'ꙥ' => 'Ꙥ', 'ꙧ' => 'Ꙧ', 'ꙩ' => 'Ꙩ', 'ꙫ' => 'Ꙫ', 'ꙭ' => 'Ꙭ', 'ꚁ' => 'Ꚁ', 'ꚃ' => 'Ꚃ', 'ꚅ' => 'Ꚅ', 'ꚇ' => 'Ꚇ', 'ꚉ' => 'Ꚉ', 'ꚋ' => 'Ꚋ', 'ꚍ' => 'Ꚍ', 'ꚏ' => 'Ꚏ', 'ꚑ' => 'Ꚑ', 'ꚓ' => 'Ꚓ', 'ꚕ' => 'Ꚕ', 'ꚗ' => 'Ꚗ', 'ꚙ' => 'Ꚙ', 'ꚛ' => 'Ꚛ', 'ꜣ' => 'Ꜣ', 'ꜥ' => 'Ꜥ', 'ꜧ' => 'Ꜧ', 'ꜩ' => 'Ꜩ', 'ꜫ' => 'Ꜫ', 'ꜭ' => 'Ꜭ', 'ꜯ' => 'Ꜯ', 'ꜳ' => 'Ꜳ', 'ꜵ' => 'Ꜵ', 'ꜷ' => 'Ꜷ', 'ꜹ' => 'Ꜹ', 'ꜻ' => 'Ꜻ', 'ꜽ' => 'Ꜽ', 'ꜿ' => 'Ꜿ', 'ꝁ' => 'Ꝁ', 'ꝃ' => 'Ꝃ', 'ꝅ' => 'Ꝅ', 'ꝇ' => 'Ꝇ', 'ꝉ' => 'Ꝉ', 'ꝋ' => 'Ꝋ', 'ꝍ' => 'Ꝍ', 'ꝏ' => 'Ꝏ', 'ꝑ' => 'Ꝑ', 'ꝓ' => 'Ꝓ', 'ꝕ' => 'Ꝕ', 'ꝗ' => 'Ꝗ', 'ꝙ' => 'Ꝙ', 'ꝛ' => 'Ꝛ', 'ꝝ' => 'Ꝝ', 'ꝟ' => 'Ꝟ', 'ꝡ' => 'Ꝡ', 'ꝣ' => 'Ꝣ', 'ꝥ' => 'Ꝥ', 'ꝧ' => 'Ꝧ', 'ꝩ' => 'Ꝩ', 'ꝫ' => 'Ꝫ', 'ꝭ' => 'Ꝭ', 'ꝯ' => 'Ꝯ', 'ꝺ' => 'Ꝺ', 'ꝼ' => 'Ꝼ', 'ꝿ' => 'Ꝿ', 'ꞁ' => 'Ꞁ', 'ꞃ' => 'Ꞃ', 'ꞅ' => 'Ꞅ', 'ꞇ' => 'Ꞇ', 'ꞌ' => 'Ꞌ', 'ꞑ' => 'Ꞑ', 'ꞓ' => 'Ꞓ', 'ꞔ' => 'Ꞔ', 'ꞗ' => 'Ꞗ', 'ꞙ' => 'Ꞙ', 'ꞛ' => 'Ꞛ', 'ꞝ' => 'Ꞝ', 'ꞟ' => 'Ꞟ', 'ꞡ' => 'Ꞡ', 'ꞣ' => 'Ꞣ', 'ꞥ' => 'Ꞥ', 'ꞧ' => 'Ꞧ', 'ꞩ' => 'Ꞩ', 'ꞵ' => 'Ꞵ', 'ꞷ' => 'Ꞷ', 'ꞹ' => 'Ꞹ', 'ꞻ' => 'Ꞻ', 'ꞽ' => 'Ꞽ', 'ꞿ' => 'Ꞿ', 'ꟃ' => 'Ꟃ', 'ꟈ' => 'Ꟈ', 'ꟊ' => 'Ꟊ', 'ꟶ' => 'Ꟶ', 'ꭓ' => 'Ꭓ', 'ꭰ' => 'Ꭰ', 'ꭱ' => 'Ꭱ', 'ꭲ' => 'Ꭲ', 'ꭳ' => 'Ꭳ', 'ꭴ' => 'Ꭴ', 'ꭵ' => 'Ꭵ', 'ꭶ' => 'Ꭶ', 'ꭷ' => 'Ꭷ', 'ꭸ' => 'Ꭸ', 'ꭹ' => 'Ꭹ', 'ꭺ' => 'Ꭺ', 'ꭻ' => 'Ꭻ', 'ꭼ' => 'Ꭼ', 'ꭽ' => 'Ꭽ', 'ꭾ' => 'Ꭾ', 'ꭿ' => 'Ꭿ', 'ꮀ' => 'Ꮀ', 'ꮁ' => 'Ꮁ', 'ꮂ' => 'Ꮂ', 'ꮃ' => 'Ꮃ', 'ꮄ' => 'Ꮄ', 'ꮅ' => 'Ꮅ', 'ꮆ' => 'Ꮆ', 'ꮇ' => 'Ꮇ', 'ꮈ' => 'Ꮈ', 'ꮉ' => 'Ꮉ', 'ꮊ' => 'Ꮊ', 'ꮋ' => 'Ꮋ', 'ꮌ' => 'Ꮌ', 'ꮍ' => 'Ꮍ', 'ꮎ' => 'Ꮎ', 'ꮏ' => 'Ꮏ', 'ꮐ' => 'Ꮐ', 'ꮑ' => 'Ꮑ', 'ꮒ' => 'Ꮒ', 'ꮓ' => 'Ꮓ', 'ꮔ' => 'Ꮔ', 'ꮕ' => 'Ꮕ', 'ꮖ' => 'Ꮖ', 'ꮗ' => 'Ꮗ', 'ꮘ' => 'Ꮘ', 'ꮙ' => 'Ꮙ', 'ꮚ' => 'Ꮚ', 'ꮛ' => 'Ꮛ', 'ꮜ' => 'Ꮜ', 'ꮝ' => 'Ꮝ', 'ꮞ' => 'Ꮞ', 'ꮟ' => 'Ꮟ', 'ꮠ' => 'Ꮠ', 'ꮡ' => 'Ꮡ', 'ꮢ' => 'Ꮢ', 'ꮣ' => 'Ꮣ', 'ꮤ' => 'Ꮤ', 'ꮥ' => 'Ꮥ', 'ꮦ' => 'Ꮦ', 'ꮧ' => 'Ꮧ', 'ꮨ' => 'Ꮨ', 'ꮩ' => 'Ꮩ', 'ꮪ' => 'Ꮪ', 'ꮫ' => 'Ꮫ', 'ꮬ' => 'Ꮬ', 'ꮭ' => 'Ꮭ', 'ꮮ' => 'Ꮮ', 'ꮯ' => 'Ꮯ', 'ꮰ' => 'Ꮰ', 'ꮱ' => 'Ꮱ', 'ꮲ' => 'Ꮲ', 'ꮳ' => 'Ꮳ', 'ꮴ' => 'Ꮴ', 'ꮵ' => 'Ꮵ', 'ꮶ' => 'Ꮶ', 'ꮷ' => 'Ꮷ', 'ꮸ' => 'Ꮸ', 'ꮹ' => 'Ꮹ', 'ꮺ' => 'Ꮺ', 'ꮻ' => 'Ꮻ', 'ꮼ' => 'Ꮼ', 'ꮽ' => 'Ꮽ', 'ꮾ' => 'Ꮾ', 'ꮿ' => 'Ꮿ', 'a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D', 'e' => 'E', 'f' => 'F', 'g' => 'G', 'h' => 'H', 'i' => 'I', 'j' => 'J', 'k' => 'K', 'l' => 'L', 'm' => 'M', 'n' => 'N', 'o' => 'O', 'p' => 'P', 'q' => 'Q', 'r' => 'R', 's' => 'S', 't' => 'T', 'u' => 'U', 'v' => 'V', 'w' => 'W', 'x' => 'X', 'y' => 'Y', 'z' => 'Z', '𐐨' => '𐐀', '𐐩' => '𐐁', '𐐪' => '𐐂', '𐐫' => '𐐃', '𐐬' => '𐐄', '𐐭' => '𐐅', '𐐮' => '𐐆', '𐐯' => '𐐇', '𐐰' => '𐐈', '𐐱' => '𐐉', '𐐲' => '𐐊', '𐐳' => '𐐋', '𐐴' => '𐐌', '𐐵' => '𐐍', '𐐶' => '𐐎', '𐐷' => '𐐏', '𐐸' => '𐐐', '𐐹' => '𐐑', '𐐺' => '𐐒', '𐐻' => '𐐓', '𐐼' => '𐐔', '𐐽' => '𐐕', '𐐾' => '𐐖', '𐐿' => '𐐗', '𐑀' => '𐐘', '𐑁' => '𐐙', '𐑂' => '𐐚', '𐑃' => '𐐛', '𐑄' => '𐐜', '𐑅' => '𐐝', '𐑆' => '𐐞', '𐑇' => '𐐟', '𐑈' => '𐐠', '𐑉' => '𐐡', '𐑊' => '𐐢', '𐑋' => '𐐣', '𐑌' => '𐐤', '𐑍' => '𐐥', '𐑎' => '𐐦', '𐑏' => '𐐧', '𐓘' => '𐒰', '𐓙' => '𐒱', '𐓚' => '𐒲', '𐓛' => '𐒳', '𐓜' => '𐒴', '𐓝' => '𐒵', '𐓞' => '𐒶', '𐓟' => '𐒷', '𐓠' => '𐒸', '𐓡' => '𐒹', '𐓢' => '𐒺', '𐓣' => '𐒻', '𐓤' => '𐒼', '𐓥' => '𐒽', '𐓦' => '𐒾', '𐓧' => '𐒿', '𐓨' => '𐓀', '𐓩' => '𐓁', '𐓪' => '𐓂', '𐓫' => '𐓃', '𐓬' => '𐓄', '𐓭' => '𐓅', '𐓮' => '𐓆', '𐓯' => '𐓇', '𐓰' => '𐓈', '𐓱' => '𐓉', '𐓲' => '𐓊', '𐓳' => '𐓋', '𐓴' => '𐓌', '𐓵' => '𐓍', '𐓶' => '𐓎', '𐓷' => '𐓏', '𐓸' => '𐓐', '𐓹' => '𐓑', '𐓺' => '𐓒', '𐓻' => '𐓓', '𐳀' => '𐲀', '𐳁' => '𐲁', '𐳂' => '𐲂', '𐳃' => '𐲃', '𐳄' => '𐲄', '𐳅' => '𐲅', '𐳆' => '𐲆', '𐳇' => '𐲇', '𐳈' => '𐲈', '𐳉' => '𐲉', '𐳊' => '𐲊', '𐳋' => '𐲋', '𐳌' => '𐲌', '𐳍' => '𐲍', '𐳎' => '𐲎', '𐳏' => '𐲏', '𐳐' => '𐲐', '𐳑' => '𐲑', '𐳒' => '𐲒', '𐳓' => '𐲓', '𐳔' => '𐲔', '𐳕' => '𐲕', '𐳖' => '𐲖', '𐳗' => '𐲗', '𐳘' => '𐲘', '𐳙' => '𐲙', '𐳚' => '𐲚', '𐳛' => '𐲛', '𐳜' => '𐲜', '𐳝' => '𐲝', '𐳞' => '𐲞', '𐳟' => '𐲟', '𐳠' => '𐲠', '𐳡' => '𐲡', '𐳢' => '𐲢', '𐳣' => '𐲣', '𐳤' => '𐲤', '𐳥' => '𐲥', '𐳦' => '𐲦', '𐳧' => '𐲧', '𐳨' => '𐲨', '𐳩' => '𐲩', '𐳪' => '𐲪', '𐳫' => '𐲫', '𐳬' => '𐲬', '𐳭' => '𐲭', '𐳮' => '𐲮', '𐳯' => '𐲯', '𐳰' => '𐲰', '𐳱' => '𐲱', '𐳲' => '𐲲', '𑣀' => '𑢠', '𑣁' => '𑢡', '𑣂' => '𑢢', '𑣃' => '𑢣', '𑣄' => '𑢤', '𑣅' => '𑢥', '𑣆' => '𑢦', '𑣇' => '𑢧', '𑣈' => '𑢨', '𑣉' => '𑢩', '𑣊' => '𑢪', '𑣋' => '𑢫', '𑣌' => '𑢬', '𑣍' => '𑢭', '𑣎' => '𑢮', '𑣏' => '𑢯', '𑣐' => '𑢰', '𑣑' => '𑢱', '𑣒' => '𑢲', '𑣓' => '𑢳', '𑣔' => '𑢴', '𑣕' => '𑢵', '𑣖' => '𑢶', '𑣗' => '𑢷', '𑣘' => '𑢸', '𑣙' => '𑢹', '𑣚' => '𑢺', '𑣛' => '𑢻', '𑣜' => '𑢼', '𑣝' => '𑢽', '𑣞' => '𑢾', '𑣟' => '𑢿', '𖹠' => '𖹀', '𖹡' => '𖹁', '𖹢' => '𖹂', '𖹣' => '𖹃', '𖹤' => '𖹄', '𖹥' => '𖹅', '𖹦' => '𖹆', '𖹧' => '𖹇', '𖹨' => '𖹈', '𖹩' => '𖹉', '𖹪' => '𖹊', '𖹫' => '𖹋', '𖹬' => '𖹌', '𖹭' => '𖹍', '𖹮' => '𖹎', '𖹯' => '𖹏', '𖹰' => '𖹐', '𖹱' => '𖹑', '𖹲' => '𖹒', '𖹳' => '𖹓', '𖹴' => '𖹔', '𖹵' => '𖹕', '𖹶' => '𖹖', '𖹷' => '𖹗', '𖹸' => '𖹘', '𖹹' => '𖹙', '𖹺' => '𖹚', '𖹻' => '𖹛', '𖹼' => '𖹜', '𖹽' => '𖹝', '𖹾' => '𖹞', '𖹿' => '𖹟', '𞤢' => '𞤀', '𞤣' => '𞤁', '𞤤' => '𞤂', '𞤥' => '𞤃', '𞤦' => '𞤄', '𞤧' => '𞤅', '𞤨' => '𞤆', '𞤩' => '𞤇', '𞤪' => '𞤈', '𞤫' => '𞤉', '𞤬' => '𞤊', '𞤭' => '𞤋', '𞤮' => '𞤌', '𞤯' => '𞤍', '𞤰' => '𞤎', '𞤱' => '𞤏', '𞤲' => '𞤐', '𞤳' => '𞤑', '𞤴' => '𞤒', '𞤵' => '𞤓', '𞤶' => '𞤔', '𞤷' => '𞤕', '𞤸' => '𞤖', '𞤹' => '𞤗', '𞤺' => '𞤘', '𞤻' => '𞤙', '𞤼' => '𞤚', '𞤽' => '𞤛', '𞤾' => '𞤜', '𞤿' => '𞤝', '𞥀' => '𞤞', '𞥁' => '𞤟', '𞥂' => '𞤠', '𞥃' => '𞤡'); * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Contracts\Service; /** * Provides a way to reset an object to its initial state. * * When calling the "reset()" method on an object, it should be put back to its * initial state. This usually means clearing any internal buffers and forwarding * the call to internal dependencies. All properties of the object should be put * back to the same state it had when it was first ready to use. * * This method could be called, for example, to recycle objects that are used as * services, so that they can be used to handle several requests in the same * process loop (note that we advise making your services stateless instead of * implementing this interface when possible.) */ interface ResetInterface { public function reset(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Contracts\Service; /** * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. * * The getSubscribedServices method returns an array of service types required by such instances, * optionally keyed by the service names used internally. Service types that start with an interrogation * mark "?" are optional, while the other ones are mandatory service dependencies. * * The injected service locators SHOULD NOT allow access to any other services not specified by the method. * * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. * This interface does not dictate any injection method for these service locators, although constructor * injection is recommended. * * @author Nicolas Grekas */ interface ServiceSubscriberInterface { /** * Returns an array of service types required by such instances, optionally keyed by the service names used internally. * * For mandatory dependencies: * * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name * internally to fetch a service which must implement Psr\Log\LoggerInterface. * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name * internally to fetch an iterable of Psr\Log\LoggerInterface instances. * * ['Psr\Log\LoggerInterface'] is a shortcut for * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface'] * * otherwise: * * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency * * ['?Psr\Log\LoggerInterface'] is a shortcut for * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] * * @return array The required service types, optionally keyed by service names */ public static function getSubscribedServices(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Contracts\Service\Attribute; use Attribute; /** * A required dependency. * * This attribute indicates that a property holds a required dependency. The annotated property or method should be * considered during the instantiation process of the containing class. * * @author Alexander M. Turek */ #[Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] final class Required { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Contracts\Service; use _HumbugBoxd02f763d3c56\Psr\Container\ContainerExceptionInterface; use _HumbugBoxd02f763d3c56\Psr\Container\NotFoundExceptionInterface; // Help opcache.preload discover always-needed symbols \class_exists(\_HumbugBoxd02f763d3c56\Psr\Container\ContainerExceptionInterface::class); \class_exists(\_HumbugBoxd02f763d3c56\Psr\Container\NotFoundExceptionInterface::class); /** * A trait to help implement ServiceProviderInterface. * * @author Robin Chalas * @author Nicolas Grekas */ trait ServiceLocatorTrait { private $factories; private $loading = []; private $providedTypes; /** * @param callable[] $factories */ public function __construct(array $factories) { $this->factories = $factories; } /** * {@inheritdoc} * * @return bool */ public function has($id) { return isset($this->factories[$id]); } /** * {@inheritdoc} */ public function get($id) { if (!isset($this->factories[$id])) { throw $this->createNotFoundException($id); } if (isset($this->loading[$id])) { $ids = \array_values($this->loading); $ids = \array_slice($this->loading, \array_search($id, $ids)); $ids[] = $id; throw $this->createCircularReferenceException($id, $ids); } $this->loading[$id] = $id; try { return $this->factories[$id]($this); } finally { unset($this->loading[$id]); } } /** * {@inheritdoc} */ public function getProvidedServices() : array { if (null === $this->providedTypes) { $this->providedTypes = []; foreach ($this->factories as $name => $factory) { if (!\is_callable($factory)) { $this->providedTypes[$name] = '?'; } else { $type = (new \ReflectionFunction($factory))->getReturnType(); $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '') . ($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?'; } } } return $this->providedTypes; } private function createNotFoundException(string $id) : \_HumbugBoxd02f763d3c56\Psr\Container\NotFoundExceptionInterface { if (!($alternatives = \array_keys($this->factories))) { $message = 'is empty...'; } else { $last = \array_pop($alternatives); if ($alternatives) { $message = \sprintf('only knows about the "%s" and "%s" services.', \implode('", "', $alternatives), $last); } else { $message = \sprintf('only knows about the "%s" service.', $last); } } if ($this->loading) { $message = \sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', \end($this->loading), $id, $message); } else { $message = \sprintf('Service "%s" not found: the current service locator %s', $id, $message); } return new class($message) extends \InvalidArgumentException implements \_HumbugBoxd02f763d3c56\Psr\Container\NotFoundExceptionInterface { }; } private function createCircularReferenceException(string $id, array $path) : \_HumbugBoxd02f763d3c56\Psr\Container\ContainerExceptionInterface { return new class(\sprintf('Circular reference detected for service "%s", path: "%s".', $id, \implode(' -> ', $path))) extends \RuntimeException implements \_HumbugBoxd02f763d3c56\Psr\Container\ContainerExceptionInterface { }; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Contracts\Service; use _HumbugBoxd02f763d3c56\Psr\Container\ContainerInterface; /** * Implementation of ServiceSubscriberInterface that determines subscribed services from * private method return types. Service ids are available as "ClassName::methodName". * * @author Kevin Bond */ trait ServiceSubscriberTrait { /** @var ContainerInterface */ protected $container; public static function getSubscribedServices() : array { static $services; if (null !== $services) { return $services; } $services = \is_callable(['parent', __FUNCTION__]) ? parent::getSubscribedServices() : []; foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { continue; } if (self::class === $method->getDeclaringClass()->name && ($returnType = $method->getReturnType()) && !$returnType->isBuiltin()) { $services[self::class . '::' . $method->name] = '?' . ($returnType instanceof \ReflectionNamedType ? $returnType->getName() : $type); } } return $services; } /** * @required */ public function setContainer(\_HumbugBoxd02f763d3c56\Psr\Container\ContainerInterface $container) { $this->container = $container; if (\is_callable(['parent', __FUNCTION__])) { return parent::setContainer($container); } return null; } } Copyright (c) 2018-2020 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Symfony\Contracts\Service; use _HumbugBoxd02f763d3c56\Psr\Container\ContainerInterface; /** * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container. * * @author Nicolas Grekas * @author Mateusz Sip */ interface ServiceProviderInterface extends \_HumbugBoxd02f763d3c56\Psr\Container\ContainerInterface { /** * Returns an associative array of service types keyed by the identifiers provided by the current container. * * Examples: * * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface * * ['foo' => '?'] means the container provides service name "foo" of unspecified type * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null * * @return string[] The provided service types, keyed by service names */ public function getProvidedServices() : array; } diagnostics = $diagnostics; } } symbol = $symbol; $this->location = $location; } } range = $range; $this->newText = $newText; } } capabilities = $capabilities ?? new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\ServerCapabilities(); } } triggerCharacters = $triggerCharacters; } } message = $message; $this->range = $range; $this->code = $code; $this->severity = $severity; $this->source = $source; } } attributes = $attributes ?? new \stdClass(); $this->hints = $hints; } } includeDeclaration = $includeDeclaration; } } changes = $changes; } } contents = $contents; $this->range = $range; } } uri = $uri; } } range = $range; $this->command = $command; $this->data = $data; } } start = $start; $this->end = $end; } /** * Checks if a position is within the range * * @param Position $position * @return bool */ public function includes(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position $position) : bool { return $this->start->compare($position) <= 0 && $this->end->compare($position) >= 0; } } signatures = $signatures; $this->activeSignature = $activeSignature; $this->activeParameter = $activeParameter; } } range = $range; $this->kind = $kind; } } triggerKind = $triggerKind; $this->triggerCharacter = $triggerCharacter; } } line = $line; $this->character = $character; } /** * Compares this position to another position * Returns * - 0 if the positions match * - a negative number if $this is before $position * - a positive number otherwise * * @param Position $position * @return int */ public function compare(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position $position) : int { if ($this->line === $position->line && $this->character === $position->character) { return 0; } if ($this->line !== $position->line) { return $this->line - $position->line; } return $this->character - $position->character; } /** * Returns the offset of the position in a string * * @param string $content * @return int */ public function toOffset(string $content) : int { $lines = \explode("\n", $content); $slice = \array_slice($lines, 0, $this->line); return (int) \array_sum(\array_map('strlen', $slice)) + \count($slice) + $this->character; } } firstTriggerCharacter = $firstTriggerCharacter; $this->moreTriggerCharacter = $moreTriggerCharacter; } } tabSize = $tabSize; $this->insertSpaces = $insertSpaces; } } language = $language; $this->value = $value; } } name = $name; $this->kind = $kind; $this->location = $location; $this->containerName = $containerName; } } resolveProvider = $resolveProvider; } } title = $title; $this->command = $command; $this->arguments = $arguments; } } range = $range; $this->rangeLength = $rangeLength; $this->text = $text; } } xfilesProvider = $xfilesProvider; $this->xcontentProvider = $xcontentProvider; $this->xcacheProvider = $xcacheProvider; } } resolveProvider = $resolveProvider; $this->triggerCharacters = $triggerCharacters; } } reference = $reference; $this->symbol = $symbol; } } label = $label; $this->parameters = $parameters; $this->documentation = $documentation; } } fqsen = $fqsen; $this->package = $package; } } label = $label; $this->kind = $kind; $this->detail = $detail; $this->documentation = $documentation; $this->sortText = $sortText; $this->filterText = $filterText; $this->insertText = $insertText; $this->textEdit = $textEdit; $this->additionalTextEdits = $additionalTextEdits; $this->command = $command; $this->data = $data; $this->insertTextFormat = $insertTextFormat; } } uri = $uri; $this->range = $range; } } range = $range; $this->rangeLength = $rangeLength; $this->text = $text; } } name = $name; } } label = $label; $this->documentation = $documentation; } } uri = $uri; $this->type = $type; } } version = $version; } } items = $items; $this->isIncomplete = $isIncomplete; } } uri = $uri; $this->languageId = $languageId; $this->version = $version; $this->text = $text; } } title = $title; } } kind = $kind; $this->value = $value; } } { "name": "php-language-server-protocol", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", "dev": true, "requires": { "call-me-maybe": "^1.0.1", "glob-to-regexp": "^0.3.0" } }, "@nodelib/fs.stat": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.2.tgz", "integrity": "sha512-yprFYuno9FtNsSHVlSWd+nRlmGoAbqbeCwOryP6sC/zoCjhpArcRMYp19EvpSUSizJAlsXEwJv+wcWS9XaXdMw==", "dev": true }, "@octokit/rest": { "version": "15.12.0", "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-15.12.0.tgz", "integrity": "sha512-5wRag4kHRkp0JDo++L9x9FkDlHEALbLnbSede16D8u+a2/t+gX32uhDs8cukVLyyrZR79nmh1lNpxZmffwoNoQ==", "dev": true, "requires": { "before-after-hook": "^1.1.0", "btoa-lite": "^1.0.0", "debug": "^3.1.0", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.0", "lodash": "^4.17.4", "node-fetch": "^2.1.1", "universal-user-agent": "^2.0.0", "url-template": "^2.0.8" }, "dependencies": { "debug": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { "ms": "^2.1.1" } } } }, "@semantic-release/commit-analyzer": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-6.0.1.tgz", "integrity": "sha512-ENCRn1tm1D08CCBnIPsID8GjboWT6E97s0Lk3XrpAh+IMx615uAU1X2FoXyOGGc6zmqp9Ff4s8KECd/GjMcodQ==", "dev": true, "requires": { "conventional-changelog-angular": "^5.0.0", "conventional-commits-filter": "^2.0.0", "conventional-commits-parser": "^3.0.0", "debug": "^4.0.0", "import-from": "^2.1.0", "lodash": "^4.17.4" } }, "@semantic-release/error": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-2.2.0.tgz", "integrity": "sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg==", "dev": true }, "@semantic-release/github": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-5.0.5.tgz", "integrity": "sha512-Hdt6b8ST2pg6pl151PlcsnTcdsC2UJhA5FdbmunbZG/TVmlnKCZ4WUzpji7YqJtDLjbQTuFm/vhM6atW3XjMWg==", "dev": true, "requires": { "@octokit/rest": "^15.2.0", "@semantic-release/error": "^2.2.0", "aggregate-error": "^1.0.0", "bottleneck": "^2.0.1", "debug": "^4.0.0", "dir-glob": "^2.0.0", "fs-extra": "^7.0.0", "globby": "^8.0.0", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.1", "issue-parser": "^3.0.0", "lodash": "^4.17.4", "mime": "^2.0.3", "p-filter": "^1.0.0", "p-retry": "^2.0.0", "parse-github-url": "^1.0.1", "url-join": "^4.0.0" } }, "@semantic-release/npm": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-5.0.4.tgz", "integrity": "sha512-ExGXP9GnM2hqUIgTnp6sXKB1G0Yh+fuLftmIopq5KHBWj34Wd2YbM/3iLkXXnAP1YZ9YCp7hsAdsR014ctbwHg==", "dev": true, "requires": { "@semantic-release/error": "^2.2.0", "aggregate-error": "^1.0.0", "detect-indent": "^5.0.0", "detect-newline": "^2.1.0", "execa": "^1.0.0", "fs-extra": "^7.0.0", "lodash": "^4.17.4", "nerf-dart": "^1.0.0", "normalize-url": "^3.0.0", "npm": "^6.3.0", "parse-json": "^4.0.0", "rc": "^1.2.8", "read-pkg": "^4.0.0", "registry-auth-token": "^3.3.1" }, "dependencies": { "read-pkg": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", "dev": true, "requires": { "normalize-package-data": "^2.3.2", "parse-json": "^4.0.0", "pify": "^3.0.0" } } } }, "@semantic-release/release-notes-generator": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-7.0.2.tgz", "integrity": "sha512-fomHrGq/gfZIAQYZk0MLRwfQ8d+DbTcI3kuO1hU2L0fDJYKHZHuPmKnsfVa5KoNdVVPHx878D/ojgyStRqhc9g==", "dev": true, "requires": { "conventional-changelog-angular": "^5.0.0", "conventional-changelog-writer": "^4.0.0", "conventional-commits-filter": "^2.0.0", "conventional-commits-parser": "^3.0.0", "debug": "^4.0.0", "get-stream": "^4.0.0", "git-url-parse": "^10.0.1", "import-from": "^2.1.0", "into-stream": "^3.1.0", "lodash": "^4.17.4" } }, "JSONStream": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.4.tgz", "integrity": "sha512-Y7vfi3I5oMOYIr+WxV8NZxDSwcbNgzdKYsTNInmycOq9bUYwGg9ryu57Wg5NLmCjqdFPNUmpMBo3kSJN9tCbXg==", "dev": true, "requires": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" } }, "agent-base": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", "dev": true, "requires": { "es6-promisify": "^5.0.0" } }, "aggregate-error": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-1.0.0.tgz", "integrity": "sha1-iINE2tAiCnLjr1CQYRf0h3GSX6w=", "dev": true, "requires": { "clean-stack": "^1.0.0", "indent-string": "^3.0.0" } }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" } }, "ansicolors": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", "dev": true }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "~1.0.2" } }, "argv-formatter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", "integrity": "sha1-oMoMvCmltz6Dbuvhy/bF4OTrgvk=", "dev": true }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, "array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", "dev": true }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { "array-uniq": "^1.0.1" } }, "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { "lodash": "^4.17.10" } }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", "component-emitter": "^1.2.1", "define-property": "^1.0.0", "isobject": "^3.0.1", "mixin-deep": "^1.2.0", "pascalcase": "^0.1.1" }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } } } }, "before-after-hook": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-1.1.0.tgz", "integrity": "sha512-VOMDtYPwLbIncTxNoSzRyvaMxtXmLWLUqr8k5AfC1BzLk34HvBXaQX8snOwQZ4c0aX8aSERqtJSiI9/m2u5kuA==", "dev": true }, "bottleneck": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.11.0.tgz", "integrity": "sha512-DvKiYR1kG1qRVoLBUtPlmJffktoBZIz3qtdUbINlwzQXDhlhZdF8gWesPjwp05xqr5QZ7wXA2k1w78/COCweTg==", "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", "fill-range": "^4.0.0", "isobject": "^3.0.1", "repeat-element": "^1.1.2", "snapdragon": "^0.8.1", "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" } } } }, "btoa-lite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", "dev": true }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", "get-value": "^2.0.6", "has-value": "^1.0.0", "isobject": "^3.0.1", "set-value": "^2.0.0", "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" } }, "call-me-maybe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", "dev": true }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "camelcase-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", "dev": true, "requires": { "camelcase": "^4.1.0", "map-obj": "^2.0.0", "quick-lru": "^1.0.0" } }, "cardinal": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", "dev": true, "requires": { "ansicolors": "~0.3.2", "redeyed": "~2.1.0" } }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", "isobject": "^3.0.0", "static-extend": "^0.1.1" }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" } } } }, "clean-stack": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz", "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=", "dev": true }, "cli-table": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", "dev": true, "requires": { "colors": "1.0.3" } }, "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" } }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" } }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" } }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", "dev": true }, "commander": { "version": "2.17.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", "dev": true, "optional": true }, "compare-func": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", "integrity": "sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg=", "dev": true, "requires": { "array-ify": "^1.0.0", "dot-prop": "^3.0.0" } }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "conventional-changelog-angular": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.1.tgz", "integrity": "sha512-q4ylJ68fWZDdrFC9z4zKcf97HW6hp7Mo2YlqD4owfXhecFKy/PJCU/1oVFF4TqochchChqmZ0Vb0e0g8/MKNlA==", "dev": true, "requires": { "compare-func": "^1.3.1", "q": "^1.5.1" } }, "conventional-changelog-writer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.0.tgz", "integrity": "sha512-hMZPe0AQ6Bi05epeK/7hz80xxk59nPA5z/b63TOHq2wigM0/akreOc8N4Jam5b9nFgKWX1e9PdPv2ewgW6bcfg==", "dev": true, "requires": { "compare-func": "^1.3.1", "conventional-commits-filter": "^2.0.0", "dateformat": "^3.0.0", "handlebars": "^4.0.2", "json-stringify-safe": "^5.0.1", "lodash": "^4.2.1", "meow": "^4.0.0", "semver": "^5.5.0", "split": "^1.0.0", "through2": "^2.0.0" } }, "conventional-commits-filter": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.0.tgz", "integrity": "sha512-Cfl0j1/NquB/TMVx7Wrmyq7uRM+/rPQbtVVGwzfkhZ6/yH6fcMmP0Q/9044TBZPTNdGzm46vXFXL14wbET0/Mg==", "dev": true, "requires": { "is-subset": "^0.1.1", "modify-values": "^1.0.0" } }, "conventional-commits-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.0.0.tgz", "integrity": "sha512-GWh71U26BLWgMykCp+VghZ4s64wVbtseECcKQ/PvcPZR2cUnz+FUc2J9KjxNl7/ZbCxST8R03c9fc+Vi0umS9Q==", "dev": true, "requires": { "JSONStream": "^1.0.4", "is-text-path": "^1.0.0", "lodash": "^4.2.1", "meow": "^4.0.0", "split2": "^2.0.0", "through2": "^2.0.0", "trim-off-newlines": "^1.0.0" } }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "cosmiconfig": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.6.tgz", "integrity": "sha512-6DWfizHriCrFWURP1/qyhsiFvYdlJzbCzmtFWh744+KyWsJo5+kPzUZZaMRSSItoYc0pxFX7gEO7ZC1/gN/7AQ==", "dev": true, "requires": { "is-directory": "^0.3.1", "js-yaml": "^3.9.0", "parse-json": "^4.0.0" } }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { "array-find-index": "^1.0.1" } }, "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true }, "debug": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.0.1.tgz", "integrity": "sha512-K23FHJ/Mt404FSlp6gSZCevIbTMLX0j3fmHhUEhQ3Wq0FMODW3+cUSoLdy1Gx4polAf4t/lphhmHH35BB8cLYw==", "dev": true, "requires": { "ms": "^2.1.1" } }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "decamelize-keys": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", "dev": true, "requires": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" }, "dependencies": { "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true } } }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" }, "dependencies": { "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } } } }, "detect-indent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", "dev": true }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", "dev": true }, "dir-glob": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", "dev": true, "requires": { "arrify": "^1.0.1", "path-type": "^3.0.0" } }, "dot-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", "dev": true, "requires": { "is-obj": "^1.0.0" } }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "requires": { "readable-stream": "^2.0.2" } }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { "once": "^1.4.0" } }, "env-ci": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-3.0.0.tgz", "integrity": "sha512-3Xt4Cfjdy9MTTrg/eWTnJNQIrtU1DDV0KyuWOGlrR2oa9dOdzoOMbQBFbfrTiv+GypdiWWIw5HdmtakZO+rzWA==", "dev": true, "requires": { "execa": "^1.0.0", "java-properties": "^0.2.9" } }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { "is-arrayish": "^0.2.1" } }, "es6-promise": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", "dev": true }, "es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { "es6-promise": "^4.0.3" } }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { "debug": "^2.3.3", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "posix-character-classes": "^0.1.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" } }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } } }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" } } } }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { "array-unique": "^0.3.2", "define-property": "^1.0.0", "expand-brackets": "^2.1.4", "extend-shallow": "^2.0.1", "fragment-cache": "^0.2.1", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { "is-descriptor": "^1.0.0" } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" } }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } } } }, "fast-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", "dev": true, "requires": { "@mrmlnc/readdir-enhanced": "^2.2.1", "@nodelib/fs.stat": "^1.0.1", "glob-parent": "^3.1.0", "is-glob": "^4.0.0", "merge2": "^1.2.1", "micromatch": "^3.1.10" } }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" } }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" } } } }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { "locate-path": "^2.0.0" } }, "find-versions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-2.0.0.tgz", "integrity": "sha1-KtkNSQ9oKMGqQCks9wmsMxghDDw=", "dev": true, "requires": { "array-uniq": "^1.0.0", "semver-regex": "^1.0.0" } }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { "map-cache": "^0.2.2" } }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "dev": true, "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" } }, "fs-extra": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.0.tgz", "integrity": "sha512-EglNDLRpmaTWiD/qraZn6HREAEAHJcJOmxNEYwq6xeMKnVMAy3GUcFB+wXt2C6k4CNvB/mP1y/U3dzvKKj5OtQ==", "dev": true, "requires": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, "get-stream": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.0.0.tgz", "integrity": "sha512-FneLKMENeOR7wOK0/ZXCh+lwqtnPwkeunJjRN28LPqzGvNAhYvrTAhXv6xDm4vsJ0M7lcRbIYHQudKsSy2RtSQ==", "dev": true, "requires": { "pump": "^3.0.0" } }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, "git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", "integrity": "sha1-LmpMGxP8AAKCB7p5WnrDFme5/Uo=", "dev": true, "requires": { "argv-formatter": "~1.0.0", "spawn-error-forwarder": "~1.0.0", "split2": "~1.0.0", "stream-combiner2": "~1.1.1", "through2": "~2.0.0", "traverse": "~0.6.6" }, "dependencies": { "split2": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", "integrity": "sha1-UuLiIdiMdfmnP5BVbiY/+WdysxQ=", "dev": true, "requires": { "through2": "~2.0.0" } } } }, "git-up": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/git-up/-/git-up-2.0.10.tgz", "integrity": "sha512-2v4UN3qV2RGypD9QpmUjpk+4+RlYpW8GFuiZqQnKmvei08HsFPd0RfbDvEhnE4wBvnYs8ORVtYpOFuuCEmBVBw==", "dev": true, "requires": { "is-ssh": "^1.3.0", "parse-url": "^1.3.0" } }, "git-url-parse": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-10.0.1.tgz", "integrity": "sha512-Tq2u8UPXc/FawC/dO8bvh8jcck0Lkor5OhuZvmVSeyJGRucDBfw9y2zy/GNCx28lMYh1N12IzPwDexjUNFyAeg==", "dev": true, "requires": { "git-up": "^2.0.0" } }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" }, "dependencies": { "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { "is-extglob": "^2.1.0" } } } }, "glob-to-regexp": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", "dev": true }, "globby": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", "dev": true, "requires": { "array-union": "^1.0.1", "dir-glob": "^2.0.0", "fast-glob": "^2.0.2", "glob": "^7.1.2", "ignore": "^3.3.5", "pify": "^3.0.0", "slash": "^1.0.0" } }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, "handlebars": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", "dev": true, "requires": { "async": "^2.5.0", "optimist": "^0.6.1", "source-map": "^0.6.1", "uglify-js": "^3.1.4" }, "dependencies": { "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" } }, "has-values": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" }, "dependencies": { "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { "is-buffer": "^1.1.5" } } } }, "hook-std": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-1.1.0.tgz", "integrity": "sha512-aIyBZbZl3NS8XoSwIDQ+ZaiBuPOhhPWoBFA3QX0Q8hOMO8Tx4xGRTDnn/nl/LAtZWdieXzFC9ohAtTSnWrlHCQ==", "dev": true }, "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, "http-proxy-agent": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", "dev": true, "requires": { "agent-base": "4", "debug": "3.1.0" }, "dependencies": { "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } } }, "https-proxy-agent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "dev": true, "requires": { "agent-base": "^4.1.0", "debug": "^3.1.0" }, "dependencies": { "debug": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.5.tgz", "integrity": "sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==", "dev": true, "requires": { "ms": "^2.1.1" } } } }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, "import-from": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", "dev": true, "requires": { "resolve-from": "^3.0.0" }, "dependencies": { "resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true } } }, "indent-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, "into-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", "dev": true, "requires": { "from2": "^2.1.1", "p-is-promise": "^1.1.0" } }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" } } } }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-builtin-module": { "version": "1.0.0", "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { "builtin-modules": "^1.0.0" } }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" } } } }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" }, "dependencies": { "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, "is-directory": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", "dev": true }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "is-glob": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { "is-extglob": "^2.1.1" } }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" } } } }, "is-obj": { "version": "1.0.1", "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { "isobject": "^3.0.1" } }, "is-ssh": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.0.tgz", "integrity": "sha1-6+oRaaJhTaOSpjdANmw84EnY3/Y=", "dev": true, "requires": { "protocols": "^1.1.0" } }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "is-subset": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", "dev": true }, "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", "dev": true, "requires": { "text-extensions": "^1.0.0" } }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "issue-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-3.0.0.tgz", "integrity": "sha512-VWIhBdy0eOhlvpxOOMecBCHMpjx7lWVZcYpSzjD4dSdxptzI9TBR/cQEh057HL8+7jQKTLs+uCtezY/9VoveCA==", "dev": true, "requires": { "lodash.capitalize": "^4.2.1", "lodash.escaperegexp": "^4.1.2", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.uniqby": "^4.7.0" } }, "java-properties": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-0.2.10.tgz", "integrity": "sha512-CpKJh9VRNhS+XqZtg1UMejETGEiqwCGDC/uwPEEQwc2nfdbSm73SIE29TplG2gLYuBOOTNDqxzG6A9NtEPLt0w==", "dev": true }, "js-yaml": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { "graceful-fs": "^4.1.6" } }, "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { "invert-kv": "^2.0.0" } }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", "pify": "^3.0.0", "strip-bom": "^3.0.0" } }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" }, "dependencies": { "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { "p-limit": "^1.1.0" } } } }, "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", "dev": true }, "lodash.capitalize": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", "integrity": "sha1-+CbJtOKoUR2E46yinbBeGk87cqk=", "dev": true }, "lodash.escaperegexp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=", "dev": true }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", "dev": true }, "lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", "dev": true }, "lodash.toarray": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", "dev": true }, "lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", "integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=", "dev": true }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { "currently-unhandled": "^0.4.1", "signal-exit": "^3.0.0" } }, "macos-release": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-1.1.0.tgz", "integrity": "sha512-mmLbumEYMi5nXReB9js3WGsB8UE6cDBWyIO62Z4DNx6GbRhDxHNjA1MlzSpJ2S2KM1wyiPRA0d19uHWYYvMHjA==", "dev": true }, "map-age-cleaner": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz", "integrity": "sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==", "dev": true, "requires": { "p-defer": "^1.0.0" } }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", "dev": true }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { "object-visit": "^1.0.0" } }, "marked": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/marked/-/marked-0.5.0.tgz", "integrity": "sha512-UhjmkCWKu1SS/BIePL2a59BMJ7V42EYtTfksodPRXzPEGEph3Inp5dylseqt+KbU9Jglsx8xcMKmlumfJMBXAA==", "dev": true }, "marked-terminal": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-3.1.1.tgz", "integrity": "sha512-7UBFww1rdx0w9HehLMCVYa8/AxXaiDigDfMsJcj82/wgLQG9cj+oiMAVlJpeWD57VFJY2OYY+bKeEVIjIlxi+w==", "dev": true, "requires": { "cardinal": "^2.1.1", "chalk": "^2.4.1", "cli-table": "^0.3.1", "lodash.assign": "^4.2.0", "node-emoji": "^1.4.1" } }, "mem": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", "dev": true, "requires": { "map-age-cleaner": "^0.1.1", "mimic-fn": "^1.0.0", "p-is-promise": "^1.1.0" } }, "meow": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", "dev": true, "requires": { "camelcase-keys": "^4.0.0", "decamelize-keys": "^1.0.0", "loud-rejection": "^1.0.0", "minimist": "^1.1.3", "minimist-options": "^3.0.1", "normalize-package-data": "^2.3.4", "read-pkg-up": "^3.0.0", "redent": "^2.0.0", "trim-newlines": "^2.0.0" }, "dependencies": { "read-pkg-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { "find-up": "^2.0.0", "read-pkg": "^3.0.0" } } } }, "merge2": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==", "dev": true }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "extglob": "^2.0.4", "fragment-cache": "^0.2.1", "kind-of": "^6.0.2", "nanomatch": "^1.2.9", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } }, "mime": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", "dev": true }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "minimist-options": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", "dev": true, "requires": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0" } }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" } } } }, "modify-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "fragment-cache": "^0.2.1", "is-windows": "^1.0.2", "kind-of": "^6.0.2", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "nerf-dart": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", "integrity": "sha1-5tq3/r9a2Bbqgc9cYpxaDr3nLBo=", "dev": true }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "node-emoji": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==", "dev": true, "requires": { "lodash.toarray": "^4.4.0" } }, "node-fetch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.2.0.tgz", "integrity": "sha512-OayFWziIxiHY8bCUyLX6sTpDH8Jsbp4FfYd1j1f7vZyfgkcOnAyM4oQR16f8a0s7Gl/viMGRey8eScYk4V4EZA==", "dev": true }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", "is-builtin-module": "^1.0.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "normalize-url": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", "dev": true }, "npm": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/npm/-/npm-6.4.1.tgz", "integrity": "sha512-mXJL1NTVU136PtuopXCUQaNWuHlXCTp4McwlSW8S9/Aj8OEPAlSBgo8og7kJ01MjCDrkmqFQTvN5tTEhBMhXQg==", "dev": true, "requires": { "JSONStream": "^1.3.4", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", "ansistyles": "~0.1.3", "aproba": "~1.2.0", "archy": "~1.0.0", "bin-links": "^1.1.2", "bluebird": "~3.5.1", "byte-size": "^4.0.3", "cacache": "^11.2.0", "call-limit": "~1.1.0", "chownr": "~1.0.1", "ci-info": "^1.4.0", "cli-columns": "^3.1.2", "cli-table3": "^0.5.0", "cmd-shim": "~2.0.2", "columnify": "~1.5.4", "config-chain": "~1.1.11", "debuglog": "*", "detect-indent": "~5.0.0", "detect-newline": "^2.1.0", "dezalgo": "~1.0.3", "editor": "~1.0.0", "figgy-pudding": "^3.4.1", "find-npm-prefix": "^1.0.2", "fs-vacuum": "~1.2.10", "fs-write-stream-atomic": "~1.0.10", "gentle-fs": "^2.0.1", "glob": "~7.1.2", "graceful-fs": "~4.1.11", "has-unicode": "~2.0.1", "hosted-git-info": "^2.7.1", "iferr": "^1.0.2", "imurmurhash": "*", "inflight": "~1.0.6", "inherits": "~2.0.3", "ini": "^1.3.5", "init-package-json": "^1.10.3", "is-cidr": "^2.0.6", "json-parse-better-errors": "^1.0.2", "lazy-property": "~1.0.0", "libcipm": "^2.0.2", "libnpmhook": "^4.0.1", "libnpx": "^10.2.0", "lock-verify": "^2.0.2", "lockfile": "^1.0.4", "lodash._baseindexof": "*", "lodash._baseuniq": "~4.6.0", "lodash._bindcallback": "*", "lodash._cacheindexof": "*", "lodash._createcache": "*", "lodash._getnative": "*", "lodash.clonedeep": "~4.5.0", "lodash.restparam": "*", "lodash.union": "~4.6.0", "lodash.uniq": "~4.5.0", "lodash.without": "~4.4.0", "lru-cache": "^4.1.3", "meant": "~1.0.1", "mississippi": "^3.0.0", "mkdirp": "~0.5.1", "move-concurrently": "^1.0.1", "node-gyp": "^3.8.0", "nopt": "~4.0.1", "normalize-package-data": "~2.4.0", "npm-audit-report": "^1.3.1", "npm-cache-filename": "~1.0.2", "npm-install-checks": "~3.0.0", "npm-lifecycle": "^2.1.0", "npm-package-arg": "^6.1.0", "npm-packlist": "^1.1.11", "npm-pick-manifest": "^2.1.0", "npm-profile": "^3.0.2", "npm-registry-client": "^8.6.0", "npm-registry-fetch": "^1.1.0", "npm-user-validate": "~1.0.0", "npmlog": "~4.1.2", "once": "~1.4.0", "opener": "^1.5.0", "osenv": "^0.1.5", "pacote": "^8.1.6", "path-is-inside": "~1.0.2", "promise-inflight": "~1.0.1", "qrcode-terminal": "^0.12.0", "query-string": "^6.1.0", "qw": "~1.0.1", "read": "~1.0.7", "read-cmd-shim": "~1.0.1", "read-installed": "~4.0.3", "read-package-json": "^2.0.13", "read-package-tree": "^5.2.1", "readable-stream": "^2.3.6", "readdir-scoped-modules": "*", "request": "^2.88.0", "retry": "^0.12.0", "rimraf": "~2.6.2", "safe-buffer": "^5.1.2", "semver": "^5.5.0", "sha": "~2.0.1", "slide": "~1.1.6", "sorted-object": "~2.0.1", "sorted-union-stream": "~2.1.3", "ssri": "^6.0.0", "stringify-package": "^1.0.0", "tar": "^4.4.6", "text-table": "~0.2.0", "tiny-relative-date": "^1.3.0", "uid-number": "0.0.6", "umask": "~1.1.0", "unique-filename": "~1.1.0", "unpipe": "~1.0.0", "update-notifier": "^2.5.0", "uuid": "^3.3.2", "validate-npm-package-license": "^3.0.4", "validate-npm-package-name": "~3.0.0", "which": "^1.3.1", "worker-farm": "^1.6.0", "write-file-atomic": "^2.3.0" }, "dependencies": { "JSONStream": { "version": "1.3.4", "bundled": true, "dev": true, "requires": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" } }, "abbrev": { "version": "1.1.1", "bundled": true, "dev": true }, "agent-base": { "version": "4.2.0", "bundled": true, "dev": true, "requires": { "es6-promisify": "^5.0.0" } }, "agentkeepalive": { "version": "3.4.1", "bundled": true, "dev": true, "requires": { "humanize-ms": "^1.2.1" } }, "ajv": { "version": "5.5.2", "bundled": true, "dev": true, "requires": { "co": "^4.6.0", "fast-deep-equal": "^1.0.0", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.3.0" } }, "ansi-align": { "version": "2.0.0", "bundled": true, "dev": true, "requires": { "string-width": "^2.0.0" } }, "ansi-regex": { "version": "2.1.1", "bundled": true, "dev": true }, "ansi-styles": { "version": "3.2.1", "bundled": true, "dev": true, "requires": { "color-convert": "^1.9.0" } }, "ansicolors": { "version": "0.3.2", "bundled": true, "dev": true }, "ansistyles": { "version": "0.1.3", "bundled": true, "dev": true }, "aproba": { "version": "1.2.0", "bundled": true, "dev": true }, "archy": { "version": "1.0.0", "bundled": true, "dev": true }, "are-we-there-yet": { "version": "1.1.4", "bundled": true, "dev": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" } }, "asap": { "version": "2.0.6", "bundled": true, "dev": true }, "asn1": { "version": "0.2.4", "bundled": true, "dev": true, "requires": { "safer-buffer": "~2.1.0" } }, "assert-plus": { "version": "1.0.0", "bundled": true, "dev": true }, "asynckit": { "version": "0.4.0", "bundled": true, "dev": true }, "aws-sign2": { "version": "0.7.0", "bundled": true, "dev": true }, "aws4": { "version": "1.8.0", "bundled": true, "dev": true }, "balanced-match": { "version": "1.0.0", "bundled": true, "dev": true }, "bcrypt-pbkdf": { "version": "1.0.2", "bundled": true, "dev": true, "optional": true, "requires": { "tweetnacl": "^0.14.3" } }, "bin-links": { "version": "1.1.2", "bundled": true, "dev": true, "requires": { "bluebird": "^3.5.0", "cmd-shim": "^2.0.2", "gentle-fs": "^2.0.0", "graceful-fs": "^4.1.11", "write-file-atomic": "^2.3.0" } }, "block-stream": { "version": "0.0.9", "bundled": true, "dev": true, "requires": { "inherits": "~2.0.0" } }, "bluebird": { "version": "3.5.1", "bundled": true, "dev": true }, "boxen": { "version": "1.3.0", "bundled": true, "dev": true, "requires": { "ansi-align": "^2.0.0", "camelcase": "^4.0.0", "chalk": "^2.0.1", "cli-boxes": "^1.0.0", "string-width": "^2.0.0", "term-size": "^1.2.0", "widest-line": "^2.0.0" } }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "buffer-from": { "version": "1.0.0", "bundled": true, "dev": true }, "builtin-modules": { "version": "1.1.1", "bundled": true, "dev": true }, "builtins": { "version": "1.0.3", "bundled": true, "dev": true }, "byline": { "version": "5.0.0", "bundled": true, "dev": true }, "byte-size": { "version": "4.0.3", "bundled": true, "dev": true }, "cacache": { "version": "11.2.0", "bundled": true, "dev": true, "requires": { "bluebird": "^3.5.1", "chownr": "^1.0.1", "figgy-pudding": "^3.1.0", "glob": "^7.1.2", "graceful-fs": "^4.1.11", "lru-cache": "^4.1.3", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", "ssri": "^6.0.0", "unique-filename": "^1.1.0", "y18n": "^4.0.0" } }, "call-limit": { "version": "1.1.0", "bundled": true, "dev": true }, "camelcase": { "version": "4.1.0", "bundled": true, "dev": true }, "capture-stack-trace": { "version": "1.0.0", "bundled": true, "dev": true }, "caseless": { "version": "0.12.0", "bundled": true, "dev": true }, "chalk": { "version": "2.4.1", "bundled": true, "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "chownr": { "version": "1.0.1", "bundled": true, "dev": true }, "ci-info": { "version": "1.4.0", "bundled": true, "dev": true }, "cidr-regex": { "version": "2.0.9", "bundled": true, "dev": true, "requires": { "ip-regex": "^2.1.0" } }, "cli-boxes": { "version": "1.0.0", "bundled": true, "dev": true }, "cli-columns": { "version": "3.1.2", "bundled": true, "dev": true, "requires": { "string-width": "^2.0.0", "strip-ansi": "^3.0.1" } }, "cli-table3": { "version": "0.5.0", "bundled": true, "dev": true, "requires": { "colors": "^1.1.2", "object-assign": "^4.1.0", "string-width": "^2.1.1" } }, "cliui": { "version": "4.1.0", "bundled": true, "dev": true, "requires": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" }, "dependencies": { "ansi-regex": { "version": "3.0.0", "bundled": true, "dev": true }, "strip-ansi": { "version": "4.0.0", "bundled": true, "dev": true, "requires": { "ansi-regex": "^3.0.0" } } } }, "clone": { "version": "1.0.4", "bundled": true, "dev": true }, "cmd-shim": { "version": "2.0.2", "bundled": true, "dev": true, "requires": { "graceful-fs": "^4.1.2", "mkdirp": "~0.5.0" } }, "co": { "version": "4.6.0", "bundled": true, "dev": true }, "code-point-at": { "version": "1.1.0", "bundled": true, "dev": true }, "color-convert": { "version": "1.9.1", "bundled": true, "dev": true, "requires": { "color-name": "^1.1.1" } }, "color-name": { "version": "1.1.3", "bundled": true, "dev": true }, "colors": { "version": "1.1.2", "bundled": true, "dev": true, "optional": true }, "columnify": { "version": "1.5.4", "bundled": true, "dev": true, "requires": { "strip-ansi": "^3.0.0", "wcwidth": "^1.0.0" } }, "combined-stream": { "version": "1.0.6", "bundled": true, "dev": true, "requires": { "delayed-stream": "~1.0.0" } }, "concat-map": { "version": "0.0.1", "bundled": true, "dev": true }, "concat-stream": { "version": "1.6.2", "bundled": true, "dev": true, "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, "config-chain": { "version": "1.1.11", "bundled": true, "dev": true, "requires": { "ini": "^1.3.4", "proto-list": "~1.2.1" } }, "configstore": { "version": "3.1.2", "bundled": true, "dev": true, "requires": { "dot-prop": "^4.1.0", "graceful-fs": "^4.1.2", "make-dir": "^1.0.0", "unique-string": "^1.0.0", "write-file-atomic": "^2.0.0", "xdg-basedir": "^3.0.0" } }, "console-control-strings": { "version": "1.1.0", "bundled": true, "dev": true }, "copy-concurrently": { "version": "1.0.5", "bundled": true, "dev": true, "requires": { "aproba": "^1.1.1", "fs-write-stream-atomic": "^1.0.8", "iferr": "^0.1.5", "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" }, "dependencies": { "iferr": { "version": "0.1.5", "bundled": true, "dev": true } } }, "core-util-is": { "version": "1.0.2", "bundled": true, "dev": true }, "create-error-class": { "version": "3.0.2", "bundled": true, "dev": true, "requires": { "capture-stack-trace": "^1.0.0" } }, "cross-spawn": { "version": "5.1.0", "bundled": true, "dev": true, "requires": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "crypto-random-string": { "version": "1.0.0", "bundled": true, "dev": true }, "cyclist": { "version": "0.2.2", "bundled": true, "dev": true }, "dashdash": { "version": "1.14.1", "bundled": true, "dev": true, "requires": { "assert-plus": "^1.0.0" } }, "debug": { "version": "3.1.0", "bundled": true, "dev": true, "requires": { "ms": "2.0.0" }, "dependencies": { "ms": { "version": "2.0.0", "bundled": true, "dev": true } } }, "debuglog": { "version": "1.0.1", "bundled": true, "dev": true }, "decamelize": { "version": "1.2.0", "bundled": true, "dev": true }, "decode-uri-component": { "version": "0.2.0", "bundled": true, "dev": true }, "deep-extend": { "version": "0.5.1", "bundled": true, "dev": true }, "defaults": { "version": "1.0.3", "bundled": true, "dev": true, "requires": { "clone": "^1.0.2" } }, "delayed-stream": { "version": "1.0.0", "bundled": true, "dev": true }, "delegates": { "version": "1.0.0", "bundled": true, "dev": true }, "detect-indent": { "version": "5.0.0", "bundled": true, "dev": true }, "detect-newline": { "version": "2.1.0", "bundled": true, "dev": true }, "dezalgo": { "version": "1.0.3", "bundled": true, "dev": true, "requires": { "asap": "^2.0.0", "wrappy": "1" } }, "dot-prop": { "version": "4.2.0", "bundled": true, "dev": true, "requires": { "is-obj": "^1.0.0" } }, "dotenv": { "version": "5.0.1", "bundled": true, "dev": true }, "duplexer3": { "version": "0.1.4", "bundled": true, "dev": true }, "duplexify": { "version": "3.6.0", "bundled": true, "dev": true, "requires": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "ecc-jsbn": { "version": "0.1.2", "bundled": true, "dev": true, "optional": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, "editor": { "version": "1.0.0", "bundled": true, "dev": true }, "encoding": { "version": "0.1.12", "bundled": true, "dev": true, "requires": { "iconv-lite": "~0.4.13" } }, "end-of-stream": { "version": "1.4.1", "bundled": true, "dev": true, "requires": { "once": "^1.4.0" } }, "err-code": { "version": "1.1.2", "bundled": true, "dev": true }, "errno": { "version": "0.1.7", "bundled": true, "dev": true, "requires": { "prr": "~1.0.1" } }, "es6-promise": { "version": "4.2.4", "bundled": true, "dev": true }, "es6-promisify": { "version": "5.0.0", "bundled": true, "dev": true, "requires": { "es6-promise": "^4.0.3" } }, "escape-string-regexp": { "version": "1.0.5", "bundled": true, "dev": true }, "execa": { "version": "0.7.0", "bundled": true, "dev": true, "requires": { "cross-spawn": "^5.0.1", "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "extend": { "version": "3.0.2", "bundled": true, "dev": true }, "extsprintf": { "version": "1.3.0", "bundled": true, "dev": true }, "fast-deep-equal": { "version": "1.1.0", "bundled": true, "dev": true }, "fast-json-stable-stringify": { "version": "2.0.0", "bundled": true, "dev": true }, "figgy-pudding": { "version": "3.4.1", "bundled": true, "dev": true }, "find-npm-prefix": { "version": "1.0.2", "bundled": true, "dev": true }, "find-up": { "version": "2.1.0", "bundled": true, "dev": true, "requires": { "locate-path": "^2.0.0" } }, "flush-write-stream": { "version": "1.0.3", "bundled": true, "dev": true, "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.4" } }, "forever-agent": { "version": "0.6.1", "bundled": true, "dev": true }, "form-data": { "version": "2.3.2", "bundled": true, "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "1.0.6", "mime-types": "^2.1.12" } }, "from2": { "version": "2.3.0", "bundled": true, "dev": true, "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" } }, "fs-minipass": { "version": "1.2.5", "bundled": true, "dev": true, "requires": { "minipass": "^2.2.1" } }, "fs-vacuum": { "version": "1.2.10", "bundled": true, "dev": true, "requires": { "graceful-fs": "^4.1.2", "path-is-inside": "^1.0.1", "rimraf": "^2.5.2" } }, "fs-write-stream-atomic": { "version": "1.0.10", "bundled": true, "dev": true, "requires": { "graceful-fs": "^4.1.2", "iferr": "^0.1.5", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" }, "dependencies": { "iferr": { "version": "0.1.5", "bundled": true, "dev": true } } }, "fs.realpath": { "version": "1.0.0", "bundled": true, "dev": true }, "fstream": { "version": "1.0.11", "bundled": true, "dev": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", "mkdirp": ">=0.5 0", "rimraf": "2" } }, "gauge": { "version": "2.7.4", "bundled": true, "dev": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.0", "object-assign": "^4.1.0", "signal-exit": "^3.0.0", "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" }, "dependencies": { "string-width": { "version": "1.0.2", "bundled": true, "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } } } }, "genfun": { "version": "4.0.1", "bundled": true, "dev": true }, "gentle-fs": { "version": "2.0.1", "bundled": true, "dev": true, "requires": { "aproba": "^1.1.2", "fs-vacuum": "^1.2.10", "graceful-fs": "^4.1.11", "iferr": "^0.1.5", "mkdirp": "^0.5.1", "path-is-inside": "^1.0.2", "read-cmd-shim": "^1.0.1", "slide": "^1.1.6" }, "dependencies": { "iferr": { "version": "0.1.5", "bundled": true, "dev": true } } }, "get-caller-file": { "version": "1.0.2", "bundled": true, "dev": true }, "get-stream": { "version": "3.0.0", "bundled": true, "dev": true }, "getpass": { "version": "0.1.7", "bundled": true, "dev": true, "requires": { "assert-plus": "^1.0.0" } }, "glob": { "version": "7.1.2", "bundled": true, "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "global-dirs": { "version": "0.1.1", "bundled": true, "dev": true, "requires": { "ini": "^1.3.4" } }, "got": { "version": "6.7.1", "bundled": true, "dev": true, "requires": { "create-error-class": "^3.0.0", "duplexer3": "^0.1.4", "get-stream": "^3.0.0", "is-redirect": "^1.0.0", "is-retry-allowed": "^1.0.0", "is-stream": "^1.0.0", "lowercase-keys": "^1.0.0", "safe-buffer": "^5.0.1", "timed-out": "^4.0.0", "unzip-response": "^2.0.1", "url-parse-lax": "^1.0.0" } }, "graceful-fs": { "version": "4.1.11", "bundled": true, "dev": true }, "har-schema": { "version": "2.0.0", "bundled": true, "dev": true }, "har-validator": { "version": "5.1.0", "bundled": true, "dev": true, "requires": { "ajv": "^5.3.0", "har-schema": "^2.0.0" } }, "has-flag": { "version": "3.0.0", "bundled": true, "dev": true }, "has-unicode": { "version": "2.0.1", "bundled": true, "dev": true }, "hosted-git-info": { "version": "2.7.1", "bundled": true, "dev": true }, "http-cache-semantics": { "version": "3.8.1", "bundled": true, "dev": true }, "http-proxy-agent": { "version": "2.1.0", "bundled": true, "dev": true, "requires": { "agent-base": "4", "debug": "3.1.0" } }, "http-signature": { "version": "1.2.0", "bundled": true, "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" } }, "https-proxy-agent": { "version": "2.2.1", "bundled": true, "dev": true, "requires": { "agent-base": "^4.1.0", "debug": "^3.1.0" } }, "humanize-ms": { "version": "1.2.1", "bundled": true, "dev": true, "requires": { "ms": "^2.0.0" } }, "iconv-lite": { "version": "0.4.23", "bundled": true, "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } }, "iferr": { "version": "1.0.2", "bundled": true, "dev": true }, "ignore-walk": { "version": "3.0.1", "bundled": true, "dev": true, "requires": { "minimatch": "^3.0.4" } }, "import-lazy": { "version": "2.1.0", "bundled": true, "dev": true }, "imurmurhash": { "version": "0.1.4", "bundled": true, "dev": true }, "inflight": { "version": "1.0.6", "bundled": true, "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { "version": "2.0.3", "bundled": true, "dev": true }, "ini": { "version": "1.3.5", "bundled": true, "dev": true }, "init-package-json": { "version": "1.10.3", "bundled": true, "dev": true, "requires": { "glob": "^7.1.1", "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", "promzard": "^0.3.0", "read": "~1.0.1", "read-package-json": "1 || 2", "semver": "2.x || 3.x || 4 || 5", "validate-npm-package-license": "^3.0.1", "validate-npm-package-name": "^3.0.0" } }, "invert-kv": { "version": "1.0.0", "bundled": true, "dev": true }, "ip": { "version": "1.1.5", "bundled": true, "dev": true }, "ip-regex": { "version": "2.1.0", "bundled": true, "dev": true }, "is-builtin-module": { "version": "1.0.0", "bundled": true, "dev": true, "requires": { "builtin-modules": "^1.0.0" } }, "is-ci": { "version": "1.1.0", "bundled": true, "dev": true, "requires": { "ci-info": "^1.0.0" } }, "is-cidr": { "version": "2.0.6", "bundled": true, "dev": true, "requires": { "cidr-regex": "^2.0.8" } }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, "dev": true, "requires": { "number-is-nan": "^1.0.0" } }, "is-installed-globally": { "version": "0.1.0", "bundled": true, "dev": true, "requires": { "global-dirs": "^0.1.0", "is-path-inside": "^1.0.0" } }, "is-npm": { "version": "1.0.0", "bundled": true, "dev": true }, "is-obj": { "version": "1.0.1", "bundled": true, "dev": true }, "is-path-inside": { "version": "1.0.1", "bundled": true, "dev": true, "requires": { "path-is-inside": "^1.0.1" } }, "is-redirect": { "version": "1.0.0", "bundled": true, "dev": true }, "is-retry-allowed": { "version": "1.1.0", "bundled": true, "dev": true }, "is-stream": { "version": "1.1.0", "bundled": true, "dev": true }, "is-typedarray": { "version": "1.0.0", "bundled": true, "dev": true }, "isarray": { "version": "1.0.0", "bundled": true, "dev": true }, "isexe": { "version": "2.0.0", "bundled": true, "dev": true }, "isstream": { "version": "0.1.2", "bundled": true, "dev": true }, "jsbn": { "version": "0.1.1", "bundled": true, "dev": true, "optional": true }, "json-parse-better-errors": { "version": "1.0.2", "bundled": true, "dev": true }, "json-schema": { "version": "0.2.3", "bundled": true, "dev": true }, "json-schema-traverse": { "version": "0.3.1", "bundled": true, "dev": true }, "json-stringify-safe": { "version": "5.0.1", "bundled": true, "dev": true }, "jsonparse": { "version": "1.3.1", "bundled": true, "dev": true }, "jsprim": { "version": "1.4.1", "bundled": true, "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" } }, "latest-version": { "version": "3.1.0", "bundled": true, "dev": true, "requires": { "package-json": "^4.0.0" } }, "lazy-property": { "version": "1.0.0", "bundled": true, "dev": true }, "lcid": { "version": "1.0.0", "bundled": true, "dev": true, "requires": { "invert-kv": "^1.0.0" } }, "libcipm": { "version": "2.0.2", "bundled": true, "dev": true, "requires": { "bin-links": "^1.1.2", "bluebird": "^3.5.1", "find-npm-prefix": "^1.0.2", "graceful-fs": "^4.1.11", "lock-verify": "^2.0.2", "mkdirp": "^0.5.1", "npm-lifecycle": "^2.0.3", "npm-logical-tree": "^1.2.1", "npm-package-arg": "^6.1.0", "pacote": "^8.1.6", "protoduck": "^5.0.0", "read-package-json": "^2.0.13", "rimraf": "^2.6.2", "worker-farm": "^1.6.0" } }, "libnpmhook": { "version": "4.0.1", "bundled": true, "dev": true, "requires": { "figgy-pudding": "^3.1.0", "npm-registry-fetch": "^3.0.0" }, "dependencies": { "npm-registry-fetch": { "version": "3.1.1", "bundled": true, "dev": true, "requires": { "bluebird": "^3.5.1", "figgy-pudding": "^3.1.0", "lru-cache": "^4.1.2", "make-fetch-happen": "^4.0.0", "npm-package-arg": "^6.0.0" } } } }, "libnpx": { "version": "10.2.0", "bundled": true, "dev": true, "requires": { "dotenv": "^5.0.1", "npm-package-arg": "^6.0.0", "rimraf": "^2.6.2", "safe-buffer": "^5.1.0", "update-notifier": "^2.3.0", "which": "^1.3.0", "y18n": "^4.0.0", "yargs": "^11.0.0" } }, "locate-path": { "version": "2.0.0", "bundled": true, "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, "lock-verify": { "version": "2.0.2", "bundled": true, "dev": true, "requires": { "npm-package-arg": "^5.1.2 || 6", "semver": "^5.4.1" } }, "lockfile": { "version": "1.0.4", "bundled": true, "dev": true, "requires": { "signal-exit": "^3.0.2" } }, "lodash._baseindexof": { "version": "3.1.0", "bundled": true, "dev": true }, "lodash._baseuniq": { "version": "4.6.0", "bundled": true, "dev": true, "requires": { "lodash._createset": "~4.0.0", "lodash._root": "~3.0.0" } }, "lodash._bindcallback": { "version": "3.0.1", "bundled": true, "dev": true }, "lodash._cacheindexof": { "version": "3.0.2", "bundled": true, "dev": true }, "lodash._createcache": { "version": "3.1.2", "bundled": true, "dev": true, "requires": { "lodash._getnative": "^3.0.0" } }, "lodash._createset": { "version": "4.0.3", "bundled": true, "dev": true }, "lodash._getnative": { "version": "3.9.1", "bundled": true, "dev": true }, "lodash._root": { "version": "3.0.1", "bundled": true, "dev": true }, "lodash.clonedeep": { "version": "4.5.0", "bundled": true, "dev": true }, "lodash.restparam": { "version": "3.6.1", "bundled": true, "dev": true }, "lodash.union": { "version": "4.6.0", "bundled": true, "dev": true }, "lodash.uniq": { "version": "4.5.0", "bundled": true, "dev": true }, "lodash.without": { "version": "4.4.0", "bundled": true, "dev": true }, "lowercase-keys": { "version": "1.0.1", "bundled": true, "dev": true }, "lru-cache": { "version": "4.1.3", "bundled": true, "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, "make-dir": { "version": "1.3.0", "bundled": true, "dev": true, "requires": { "pify": "^3.0.0" } }, "make-fetch-happen": { "version": "4.0.1", "bundled": true, "dev": true, "requires": { "agentkeepalive": "^3.4.1", "cacache": "^11.0.1", "http-cache-semantics": "^3.8.1", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.1", "lru-cache": "^4.1.2", "mississippi": "^3.0.0", "node-fetch-npm": "^2.0.2", "promise-retry": "^1.1.1", "socks-proxy-agent": "^4.0.0", "ssri": "^6.0.0" } }, "meant": { "version": "1.0.1", "bundled": true, "dev": true }, "mem": { "version": "1.1.0", "bundled": true, "dev": true, "requires": { "mimic-fn": "^1.0.0" } }, "mime-db": { "version": "1.35.0", "bundled": true, "dev": true }, "mime-types": { "version": "2.1.19", "bundled": true, "dev": true, "requires": { "mime-db": "~1.35.0" } }, "mimic-fn": { "version": "1.2.0", "bundled": true, "dev": true }, "minimatch": { "version": "3.0.4", "bundled": true, "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", "bundled": true, "dev": true }, "minipass": { "version": "2.3.3", "bundled": true, "dev": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" }, "dependencies": { "yallist": { "version": "3.0.2", "bundled": true, "dev": true } } }, "minizlib": { "version": "1.1.0", "bundled": true, "dev": true, "requires": { "minipass": "^2.2.1" } }, "mississippi": { "version": "3.0.0", "bundled": true, "dev": true, "requires": { "concat-stream": "^1.5.0", "duplexify": "^3.4.2", "end-of-stream": "^1.1.0", "flush-write-stream": "^1.0.0", "from2": "^2.1.0", "parallel-transform": "^1.1.0", "pump": "^3.0.0", "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" } }, "mkdirp": { "version": "0.5.1", "bundled": true, "dev": true, "requires": { "minimist": "0.0.8" } }, "move-concurrently": { "version": "1.0.1", "bundled": true, "dev": true, "requires": { "aproba": "^1.1.1", "copy-concurrently": "^1.0.0", "fs-write-stream-atomic": "^1.0.8", "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" } }, "ms": { "version": "2.1.1", "bundled": true, "dev": true }, "mute-stream": { "version": "0.0.7", "bundled": true, "dev": true }, "node-fetch-npm": { "version": "2.0.2", "bundled": true, "dev": true, "requires": { "encoding": "^0.1.11", "json-parse-better-errors": "^1.0.0", "safe-buffer": "^5.1.1" } }, "node-gyp": { "version": "3.8.0", "bundled": true, "dev": true, "requires": { "fstream": "^1.0.0", "glob": "^7.0.3", "graceful-fs": "^4.1.2", "mkdirp": "^0.5.0", "nopt": "2 || 3", "npmlog": "0 || 1 || 2 || 3 || 4", "osenv": "0", "request": "^2.87.0", "rimraf": "2", "semver": "~5.3.0", "tar": "^2.0.0", "which": "1" }, "dependencies": { "nopt": { "version": "3.0.6", "bundled": true, "dev": true, "requires": { "abbrev": "1" } }, "semver": { "version": "5.3.0", "bundled": true, "dev": true }, "tar": { "version": "2.2.1", "bundled": true, "dev": true, "requires": { "block-stream": "*", "fstream": "^1.0.2", "inherits": "2" } } } }, "nopt": { "version": "4.0.1", "bundled": true, "dev": true, "requires": { "abbrev": "1", "osenv": "^0.1.4" } }, "normalize-package-data": { "version": "2.4.0", "bundled": true, "dev": true, "requires": { "hosted-git-info": "^2.1.4", "is-builtin-module": "^1.0.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "npm-audit-report": { "version": "1.3.1", "bundled": true, "dev": true, "requires": { "cli-table3": "^0.5.0", "console-control-strings": "^1.1.0" } }, "npm-bundled": { "version": "1.0.5", "bundled": true, "dev": true }, "npm-cache-filename": { "version": "1.0.2", "bundled": true, "dev": true }, "npm-install-checks": { "version": "3.0.0", "bundled": true, "dev": true, "requires": { "semver": "^2.3.0 || 3.x || 4 || 5" } }, "npm-lifecycle": { "version": "2.1.0", "bundled": true, "dev": true, "requires": { "byline": "^5.0.0", "graceful-fs": "^4.1.11", "node-gyp": "^3.8.0", "resolve-from": "^4.0.0", "slide": "^1.1.6", "uid-number": "0.0.6", "umask": "^1.1.0", "which": "^1.3.1" } }, "npm-logical-tree": { "version": "1.2.1", "bundled": true, "dev": true }, "npm-package-arg": { "version": "6.1.0", "bundled": true, "dev": true, "requires": { "hosted-git-info": "^2.6.0", "osenv": "^0.1.5", "semver": "^5.5.0", "validate-npm-package-name": "^3.0.0" } }, "npm-packlist": { "version": "1.1.11", "bundled": true, "dev": true, "requires": { "ignore-walk": "^3.0.1", "npm-bundled": "^1.0.1" } }, "npm-pick-manifest": { "version": "2.1.0", "bundled": true, "dev": true, "requires": { "npm-package-arg": "^6.0.0", "semver": "^5.4.1" } }, "npm-profile": { "version": "3.0.2", "bundled": true, "dev": true, "requires": { "aproba": "^1.1.2 || 2", "make-fetch-happen": "^2.5.0 || 3 || 4" } }, "npm-registry-client": { "version": "8.6.0", "bundled": true, "dev": true, "requires": { "concat-stream": "^1.5.2", "graceful-fs": "^4.1.6", "normalize-package-data": "~1.0.1 || ^2.0.0", "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", "npmlog": "2 || ^3.1.0 || ^4.0.0", "once": "^1.3.3", "request": "^2.74.0", "retry": "^0.10.0", "safe-buffer": "^5.1.1", "semver": "2 >=2.2.1 || 3.x || 4 || 5", "slide": "^1.1.3", "ssri": "^5.2.4" }, "dependencies": { "retry": { "version": "0.10.1", "bundled": true, "dev": true }, "ssri": { "version": "5.3.0", "bundled": true, "dev": true, "requires": { "safe-buffer": "^5.1.1" } } } }, "npm-registry-fetch": { "version": "1.1.0", "bundled": true, "dev": true, "requires": { "bluebird": "^3.5.1", "figgy-pudding": "^2.0.1", "lru-cache": "^4.1.2", "make-fetch-happen": "^3.0.0", "npm-package-arg": "^6.0.0", "safe-buffer": "^5.1.1" }, "dependencies": { "cacache": { "version": "10.0.4", "bundled": true, "dev": true, "requires": { "bluebird": "^3.5.1", "chownr": "^1.0.1", "glob": "^7.1.2", "graceful-fs": "^4.1.11", "lru-cache": "^4.1.1", "mississippi": "^2.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", "ssri": "^5.2.4", "unique-filename": "^1.1.0", "y18n": "^4.0.0" }, "dependencies": { "mississippi": { "version": "2.0.0", "bundled": true, "dev": true, "requires": { "concat-stream": "^1.5.0", "duplexify": "^3.4.2", "end-of-stream": "^1.1.0", "flush-write-stream": "^1.0.0", "from2": "^2.1.0", "parallel-transform": "^1.1.0", "pump": "^2.0.1", "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" } } } }, "figgy-pudding": { "version": "2.0.1", "bundled": true, "dev": true }, "make-fetch-happen": { "version": "3.0.0", "bundled": true, "dev": true, "requires": { "agentkeepalive": "^3.4.1", "cacache": "^10.0.4", "http-cache-semantics": "^3.8.1", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.0", "lru-cache": "^4.1.2", "mississippi": "^3.0.0", "node-fetch-npm": "^2.0.2", "promise-retry": "^1.1.1", "socks-proxy-agent": "^3.0.1", "ssri": "^5.2.4" } }, "pump": { "version": "2.0.1", "bundled": true, "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "smart-buffer": { "version": "1.1.15", "bundled": true, "dev": true }, "socks": { "version": "1.1.10", "bundled": true, "dev": true, "requires": { "ip": "^1.1.4", "smart-buffer": "^1.0.13" } }, "socks-proxy-agent": { "version": "3.0.1", "bundled": true, "dev": true, "requires": { "agent-base": "^4.1.0", "socks": "^1.1.10" } }, "ssri": { "version": "5.3.0", "bundled": true, "dev": true, "requires": { "safe-buffer": "^5.1.1" } } } }, "npm-run-path": { "version": "2.0.2", "bundled": true, "dev": true, "requires": { "path-key": "^2.0.0" } }, "npm-user-validate": { "version": "1.0.0", "bundled": true, "dev": true }, "npmlog": { "version": "4.1.2", "bundled": true, "dev": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", "gauge": "~2.7.3", "set-blocking": "~2.0.0" } }, "number-is-nan": { "version": "1.0.1", "bundled": true, "dev": true }, "oauth-sign": { "version": "0.9.0", "bundled": true, "dev": true }, "object-assign": { "version": "4.1.1", "bundled": true, "dev": true }, "once": { "version": "1.4.0", "bundled": true, "dev": true, "requires": { "wrappy": "1" } }, "opener": { "version": "1.5.0", "bundled": true, "dev": true }, "os-homedir": { "version": "1.0.2", "bundled": true, "dev": true }, "os-locale": { "version": "2.1.0", "bundled": true, "dev": true, "requires": { "execa": "^0.7.0", "lcid": "^1.0.0", "mem": "^1.1.0" } }, "os-tmpdir": { "version": "1.0.2", "bundled": true, "dev": true }, "osenv": { "version": "0.1.5", "bundled": true, "dev": true, "requires": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" } }, "p-finally": { "version": "1.0.0", "bundled": true, "dev": true }, "p-limit": { "version": "1.2.0", "bundled": true, "dev": true, "requires": { "p-try": "^1.0.0" } }, "p-locate": { "version": "2.0.0", "bundled": true, "dev": true, "requires": { "p-limit": "^1.1.0" } }, "p-try": { "version": "1.0.0", "bundled": true, "dev": true }, "package-json": { "version": "4.0.1", "bundled": true, "dev": true, "requires": { "got": "^6.7.1", "registry-auth-token": "^3.0.1", "registry-url": "^3.0.3", "semver": "^5.1.0" } }, "pacote": { "version": "8.1.6", "bundled": true, "dev": true, "requires": { "bluebird": "^3.5.1", "cacache": "^11.0.2", "get-stream": "^3.0.0", "glob": "^7.1.2", "lru-cache": "^4.1.3", "make-fetch-happen": "^4.0.1", "minimatch": "^3.0.4", "minipass": "^2.3.3", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "normalize-package-data": "^2.4.0", "npm-package-arg": "^6.1.0", "npm-packlist": "^1.1.10", "npm-pick-manifest": "^2.1.0", "osenv": "^0.1.5", "promise-inflight": "^1.0.1", "promise-retry": "^1.1.1", "protoduck": "^5.0.0", "rimraf": "^2.6.2", "safe-buffer": "^5.1.2", "semver": "^5.5.0", "ssri": "^6.0.0", "tar": "^4.4.3", "unique-filename": "^1.1.0", "which": "^1.3.0" } }, "parallel-transform": { "version": "1.1.0", "bundled": true, "dev": true, "requires": { "cyclist": "~0.2.2", "inherits": "^2.0.3", "readable-stream": "^2.1.5" } }, "path-exists": { "version": "3.0.0", "bundled": true, "dev": true }, "path-is-absolute": { "version": "1.0.1", "bundled": true, "dev": true }, "path-is-inside": { "version": "1.0.2", "bundled": true, "dev": true }, "path-key": { "version": "2.0.1", "bundled": true, "dev": true }, "performance-now": { "version": "2.1.0", "bundled": true, "dev": true }, "pify": { "version": "3.0.0", "bundled": true, "dev": true }, "prepend-http": { "version": "1.0.4", "bundled": true, "dev": true }, "process-nextick-args": { "version": "2.0.0", "bundled": true, "dev": true }, "promise-inflight": { "version": "1.0.1", "bundled": true, "dev": true }, "promise-retry": { "version": "1.1.1", "bundled": true, "dev": true, "requires": { "err-code": "^1.0.0", "retry": "^0.10.0" }, "dependencies": { "retry": { "version": "0.10.1", "bundled": true, "dev": true } } }, "promzard": { "version": "0.3.0", "bundled": true, "dev": true, "requires": { "read": "1" } }, "proto-list": { "version": "1.2.4", "bundled": true, "dev": true }, "protoduck": { "version": "5.0.0", "bundled": true, "dev": true, "requires": { "genfun": "^4.0.1" } }, "prr": { "version": "1.0.1", "bundled": true, "dev": true }, "pseudomap": { "version": "1.0.2", "bundled": true, "dev": true }, "psl": { "version": "1.1.29", "bundled": true, "dev": true }, "pump": { "version": "3.0.0", "bundled": true, "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "pumpify": { "version": "1.5.1", "bundled": true, "dev": true, "requires": { "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" }, "dependencies": { "pump": { "version": "2.0.1", "bundled": true, "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } } } }, "punycode": { "version": "1.4.1", "bundled": true, "dev": true }, "qrcode-terminal": { "version": "0.12.0", "bundled": true, "dev": true }, "qs": { "version": "6.5.2", "bundled": true, "dev": true }, "query-string": { "version": "6.1.0", "bundled": true, "dev": true, "requires": { "decode-uri-component": "^0.2.0", "strict-uri-encode": "^2.0.0" } }, "qw": { "version": "1.0.1", "bundled": true, "dev": true }, "rc": { "version": "1.2.7", "bundled": true, "dev": true, "requires": { "deep-extend": "^0.5.1", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { "version": "1.2.0", "bundled": true, "dev": true } } }, "read": { "version": "1.0.7", "bundled": true, "dev": true, "requires": { "mute-stream": "~0.0.4" } }, "read-cmd-shim": { "version": "1.0.1", "bundled": true, "dev": true, "requires": { "graceful-fs": "^4.1.2" } }, "read-installed": { "version": "4.0.3", "bundled": true, "dev": true, "requires": { "debuglog": "^1.0.1", "graceful-fs": "^4.1.2", "read-package-json": "^2.0.0", "readdir-scoped-modules": "^1.0.0", "semver": "2 || 3 || 4 || 5", "slide": "~1.1.3", "util-extend": "^1.0.1" } }, "read-package-json": { "version": "2.0.13", "bundled": true, "dev": true, "requires": { "glob": "^7.1.1", "graceful-fs": "^4.1.2", "json-parse-better-errors": "^1.0.1", "normalize-package-data": "^2.0.0", "slash": "^1.0.0" } }, "read-package-tree": { "version": "5.2.1", "bundled": true, "dev": true, "requires": { "debuglog": "^1.0.1", "dezalgo": "^1.0.0", "once": "^1.3.0", "read-package-json": "^2.0.0", "readdir-scoped-modules": "^1.0.0" } }, "readable-stream": { "version": "2.3.6", "bundled": true, "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "readdir-scoped-modules": { "version": "1.0.2", "bundled": true, "dev": true, "requires": { "debuglog": "^1.0.1", "dezalgo": "^1.0.0", "graceful-fs": "^4.1.2", "once": "^1.3.0" } }, "registry-auth-token": { "version": "3.3.2", "bundled": true, "dev": true, "requires": { "rc": "^1.1.6", "safe-buffer": "^5.0.1" } }, "registry-url": { "version": "3.1.0", "bundled": true, "dev": true, "requires": { "rc": "^1.0.1" } }, "request": { "version": "2.88.0", "bundled": true, "dev": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", "har-validator": "~5.1.0", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" } }, "require-directory": { "version": "2.1.1", "bundled": true, "dev": true }, "require-main-filename": { "version": "1.0.1", "bundled": true, "dev": true }, "resolve-from": { "version": "4.0.0", "bundled": true, "dev": true }, "retry": { "version": "0.12.0", "bundled": true, "dev": true }, "rimraf": { "version": "2.6.2", "bundled": true, "dev": true, "requires": { "glob": "^7.0.5" } }, "run-queue": { "version": "1.0.3", "bundled": true, "dev": true, "requires": { "aproba": "^1.1.1" } }, "safe-buffer": { "version": "5.1.2", "bundled": true, "dev": true }, "safer-buffer": { "version": "2.1.2", "bundled": true, "dev": true }, "semver": { "version": "5.5.0", "bundled": true, "dev": true }, "semver-diff": { "version": "2.1.0", "bundled": true, "dev": true, "requires": { "semver": "^5.0.3" } }, "set-blocking": { "version": "2.0.0", "bundled": true, "dev": true }, "sha": { "version": "2.0.1", "bundled": true, "dev": true, "requires": { "graceful-fs": "^4.1.2", "readable-stream": "^2.0.2" } }, "shebang-command": { "version": "1.2.0", "bundled": true, "dev": true, "requires": { "shebang-regex": "^1.0.0" } }, "shebang-regex": { "version": "1.0.0", "bundled": true, "dev": true }, "signal-exit": { "version": "3.0.2", "bundled": true, "dev": true }, "slash": { "version": "1.0.0", "bundled": true, "dev": true }, "slide": { "version": "1.1.6", "bundled": true, "dev": true }, "smart-buffer": { "version": "4.0.1", "bundled": true, "dev": true }, "socks": { "version": "2.2.0", "bundled": true, "dev": true, "requires": { "ip": "^1.1.5", "smart-buffer": "^4.0.1" } }, "socks-proxy-agent": { "version": "4.0.1", "bundled": true, "dev": true, "requires": { "agent-base": "~4.2.0", "socks": "~2.2.0" } }, "sorted-object": { "version": "2.0.1", "bundled": true, "dev": true }, "sorted-union-stream": { "version": "2.1.3", "bundled": true, "dev": true, "requires": { "from2": "^1.3.0", "stream-iterate": "^1.1.0" }, "dependencies": { "from2": { "version": "1.3.0", "bundled": true, "dev": true, "requires": { "inherits": "~2.0.1", "readable-stream": "~1.1.10" } }, "isarray": { "version": "0.0.1", "bundled": true, "dev": true }, "readable-stream": { "version": "1.1.14", "bundled": true, "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "string_decoder": { "version": "0.10.31", "bundled": true, "dev": true } } }, "spdx-correct": { "version": "3.0.0", "bundled": true, "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { "version": "2.1.0", "bundled": true, "dev": true }, "spdx-expression-parse": { "version": "3.0.0", "bundled": true, "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { "version": "3.0.0", "bundled": true, "dev": true }, "sshpk": { "version": "1.14.2", "bundled": true, "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", "dashdash": "^1.12.0", "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" } }, "ssri": { "version": "6.0.0", "bundled": true, "dev": true }, "stream-each": { "version": "1.2.2", "bundled": true, "dev": true, "requires": { "end-of-stream": "^1.1.0", "stream-shift": "^1.0.0" } }, "stream-iterate": { "version": "1.2.0", "bundled": true, "dev": true, "requires": { "readable-stream": "^2.1.5", "stream-shift": "^1.0.0" } }, "stream-shift": { "version": "1.0.0", "bundled": true, "dev": true }, "strict-uri-encode": { "version": "2.0.0", "bundled": true, "dev": true }, "string-width": { "version": "2.1.1", "bundled": true, "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" }, "dependencies": { "ansi-regex": { "version": "3.0.0", "bundled": true, "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", "bundled": true, "dev": true }, "strip-ansi": { "version": "4.0.0", "bundled": true, "dev": true, "requires": { "ansi-regex": "^3.0.0" } } } }, "string_decoder": { "version": "1.1.1", "bundled": true, "dev": true, "requires": { "safe-buffer": "~5.1.0" } }, "stringify-package": { "version": "1.0.0", "bundled": true, "dev": true }, "strip-ansi": { "version": "3.0.1", "bundled": true, "dev": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-eof": { "version": "1.0.0", "bundled": true, "dev": true }, "strip-json-comments": { "version": "2.0.1", "bundled": true, "dev": true }, "supports-color": { "version": "5.4.0", "bundled": true, "dev": true, "requires": { "has-flag": "^3.0.0" } }, "tar": { "version": "4.4.6", "bundled": true, "dev": true, "requires": { "chownr": "^1.0.1", "fs-minipass": "^1.2.5", "minipass": "^2.3.3", "minizlib": "^1.1.0", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", "yallist": "^3.0.2" }, "dependencies": { "yallist": { "version": "3.0.2", "bundled": true, "dev": true } } }, "term-size": { "version": "1.2.0", "bundled": true, "dev": true, "requires": { "execa": "^0.7.0" } }, "text-table": { "version": "0.2.0", "bundled": true, "dev": true }, "through": { "version": "2.3.8", "bundled": true, "dev": true }, "through2": { "version": "2.0.3", "bundled": true, "dev": true, "requires": { "readable-stream": "^2.1.5", "xtend": "~4.0.1" } }, "timed-out": { "version": "4.0.1", "bundled": true, "dev": true }, "tiny-relative-date": { "version": "1.3.0", "bundled": true, "dev": true }, "tough-cookie": { "version": "2.4.3", "bundled": true, "dev": true, "requires": { "psl": "^1.1.24", "punycode": "^1.4.1" } }, "tunnel-agent": { "version": "0.6.0", "bundled": true, "dev": true, "requires": { "safe-buffer": "^5.0.1" } }, "tweetnacl": { "version": "0.14.5", "bundled": true, "dev": true, "optional": true }, "typedarray": { "version": "0.0.6", "bundled": true, "dev": true }, "uid-number": { "version": "0.0.6", "bundled": true, "dev": true }, "umask": { "version": "1.1.0", "bundled": true, "dev": true }, "unique-filename": { "version": "1.1.0", "bundled": true, "dev": true, "requires": { "unique-slug": "^2.0.0" } }, "unique-slug": { "version": "2.0.0", "bundled": true, "dev": true, "requires": { "imurmurhash": "^0.1.4" } }, "unique-string": { "version": "1.0.0", "bundled": true, "dev": true, "requires": { "crypto-random-string": "^1.0.0" } }, "unpipe": { "version": "1.0.0", "bundled": true, "dev": true }, "unzip-response": { "version": "2.0.1", "bundled": true, "dev": true }, "update-notifier": { "version": "2.5.0", "bundled": true, "dev": true, "requires": { "boxen": "^1.2.1", "chalk": "^2.0.1", "configstore": "^3.0.0", "import-lazy": "^2.1.0", "is-ci": "^1.0.10", "is-installed-globally": "^0.1.0", "is-npm": "^1.0.0", "latest-version": "^3.0.0", "semver-diff": "^2.0.0", "xdg-basedir": "^3.0.0" } }, "url-parse-lax": { "version": "1.0.0", "bundled": true, "dev": true, "requires": { "prepend-http": "^1.0.1" } }, "util-deprecate": { "version": "1.0.2", "bundled": true, "dev": true }, "util-extend": { "version": "1.0.3", "bundled": true, "dev": true }, "uuid": { "version": "3.3.2", "bundled": true, "dev": true }, "validate-npm-package-license": { "version": "3.0.4", "bundled": true, "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "validate-npm-package-name": { "version": "3.0.0", "bundled": true, "dev": true, "requires": { "builtins": "^1.0.3" } }, "verror": { "version": "1.10.0", "bundled": true, "dev": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "wcwidth": { "version": "1.0.1", "bundled": true, "dev": true, "requires": { "defaults": "^1.0.3" } }, "which": { "version": "1.3.1", "bundled": true, "dev": true, "requires": { "isexe": "^2.0.0" } }, "which-module": { "version": "2.0.0", "bundled": true, "dev": true }, "wide-align": { "version": "1.1.2", "bundled": true, "dev": true, "requires": { "string-width": "^1.0.2" }, "dependencies": { "string-width": { "version": "1.0.2", "bundled": true, "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } } } }, "widest-line": { "version": "2.0.0", "bundled": true, "dev": true, "requires": { "string-width": "^2.1.1" } }, "worker-farm": { "version": "1.6.0", "bundled": true, "dev": true, "requires": { "errno": "~0.1.7" } }, "wrap-ansi": { "version": "2.1.0", "bundled": true, "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" }, "dependencies": { "string-width": { "version": "1.0.2", "bundled": true, "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } } } }, "wrappy": { "version": "1.0.2", "bundled": true, "dev": true }, "write-file-atomic": { "version": "2.3.0", "bundled": true, "dev": true, "requires": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", "signal-exit": "^3.0.2" } }, "xdg-basedir": { "version": "3.0.0", "bundled": true, "dev": true }, "xtend": { "version": "4.0.1", "bundled": true, "dev": true }, "y18n": { "version": "4.0.0", "bundled": true, "dev": true }, "yallist": { "version": "2.1.2", "bundled": true, "dev": true }, "yargs": { "version": "11.0.0", "bundled": true, "dev": true, "requires": { "cliui": "^4.0.0", "decamelize": "^1.1.1", "find-up": "^2.1.0", "get-caller-file": "^1.0.1", "os-locale": "^2.0.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^2.0.0", "which-module": "^2.0.0", "y18n": "^3.2.1", "yargs-parser": "^9.0.2" }, "dependencies": { "y18n": { "version": "3.2.1", "bundled": true, "dev": true } } }, "yargs-parser": { "version": "9.0.2", "bundled": true, "dev": true, "requires": { "camelcase": "^4.1.0" } } } }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { "path-key": "^2.0.0" } }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", "kind-of": "^3.0.3" }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" } } } }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { "isobject": "^3.0.0" } }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { "isobject": "^3.0.1" } }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { "wrappy": "1" } }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { "minimist": "~0.0.1", "wordwrap": "~0.0.2" }, "dependencies": { "minimist": { "version": "0.0.10", "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true } } }, "os-locale": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", "dev": true, "requires": { "execa": "^0.10.0", "lcid": "^2.0.0", "mem": "^4.0.0" }, "dependencies": { "execa": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", "dev": true, "requires": { "cross-spawn": "^6.0.0", "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true } } }, "os-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/os-name/-/os-name-2.0.1.tgz", "integrity": "sha1-uaOGNhwXrjohc27wWZQFyajF3F4=", "dev": true, "requires": { "macos-release": "^1.0.0", "win-release": "^1.0.0" } }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, "p-filter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-1.0.0.tgz", "integrity": "sha1-Yp0xcVAgnI/VCLoTdxPvS7kg6ds=", "dev": true, "requires": { "p-map": "^1.0.0" } }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-is-promise": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", "dev": true }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { "p-try": "^1.0.0" } }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { "p-limit": "^2.0.0" }, "dependencies": { "p-limit": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", "dev": true, "requires": { "p-try": "^2.0.0" } }, "p-try": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true } } }, "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", "dev": true }, "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", "dev": true }, "p-retry": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-2.0.0.tgz", "integrity": "sha512-ZbCuzAmiwJ45q4evp/IG9D+5MUllGSUeCWwPt3j/tdYSi1KPkSD+46uqmAA1LhccDhOXv8kYZKNb8x78VflzfA==", "dev": true, "requires": { "retry": "^0.12.0" } }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, "parse-github-url": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", "dev": true }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "parse-url": { "version": "1.3.11", "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-1.3.11.tgz", "integrity": "sha1-V8FUKKuKiSsfQ4aWRccR0OFEtVQ=", "dev": true, "requires": { "is-ssh": "^1.3.0", "protocols": "^1.4.0" } }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { "pify": "^3.0.0" } }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "pkg-conf": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=", "dev": true, "requires": { "find-up": "^2.0.0", "load-json-file": "^4.0.0" } }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, "protocols": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.6.tgz", "integrity": "sha1-+LsmPqG1/Xp2BNJri+Ob13Z4v4o=", "dev": true }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, "quick-lru": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", "dev": true }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" } }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" } }, "read-pkg-up": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", "dev": true, "requires": { "find-up": "^3.0.0", "read-pkg": "^3.0.0" }, "dependencies": { "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { "locate-path": "^3.0.0" } }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } } } }, "readable-stream": { "version": "2.3.6", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "redent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", "dev": true, "requires": { "indent-string": "^3.0.0", "strip-indent": "^2.0.0" } }, "redeyed": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", "dev": true, "requires": { "esprima": "~4.0.0" } }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" } }, "registry-auth-token": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", "dev": true, "requires": { "rc": "^1.1.6", "safe-buffer": "^5.0.1" } }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", "dev": true }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, "retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "dev": true }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { "ret": "~0.1.10" } }, "semantic-release": { "version": "15.9.16", "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-15.9.16.tgz", "integrity": "sha512-5RWqMFwDBXzIaNGUdnJxI4aCd4DtKtdc+5ZNjNWXABEmkimZVuuzZhMaTVNhHYfSuVUqWG9GuATEKhjlVoTzfQ==", "dev": true, "requires": { "@semantic-release/commit-analyzer": "^6.0.0", "@semantic-release/error": "^2.2.0", "@semantic-release/github": "^5.0.0", "@semantic-release/npm": "^5.0.1", "@semantic-release/release-notes-generator": "^7.0.0", "aggregate-error": "^1.0.0", "cosmiconfig": "^5.0.1", "debug": "^4.0.0", "env-ci": "^3.0.0", "execa": "^1.0.0", "figures": "^2.0.0", "find-versions": "^2.0.0", "get-stream": "^4.0.0", "git-log-parser": "^1.2.0", "git-url-parse": "^10.0.1", "hook-std": "^1.1.0", "hosted-git-info": "^2.7.1", "lodash": "^4.17.4", "marked": "^0.5.0", "marked-terminal": "^3.0.0", "p-locate": "^3.0.0", "p-reduce": "^1.0.0", "read-pkg-up": "^4.0.0", "resolve-from": "^4.0.0", "semver": "^5.4.1", "signale": "^1.2.1", "yargs": "^12.0.0" } }, "semver": { "version": "5.5.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", "dev": true }, "semver-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", "dev": true }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" } } } }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { "shebang-regex": "^1.0.0" } }, "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "signale": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/signale/-/signale-1.3.0.tgz", "integrity": "sha512-TyFhsQ9wZDYDfsPqWMyjCxsDoMwfpsT0130Mce7wDiVCSDdtWSg83dOqoj8aGpGCs3n1YPcam6sT1OFPuGT/OQ==", "dev": true, "requires": { "chalk": "^2.3.2", "figures": "^2.0.0", "pkg-conf": "^2.1.0" } }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { "base": "^0.11.1", "debug": "^2.2.0", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "map-cache": "^0.2.2", "source-map": "^0.5.6", "source-map-resolve": "^0.5.0", "use": "^3.1.0" }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" } }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" } }, "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } } }, "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", "snapdragon-util": "^3.0.1" }, "dependencies": { "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { "is-descriptor": "^1.0.0" } }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" } }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" } }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } } } }, "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { "kind-of": "^3.2.0" }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" } } } }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", "urix": "^0.1.0" } }, "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, "spawn-error-forwarder": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", "integrity": "sha1-Gv2Uc46ZmwNG17n8NzvlXgdXcCk=", "dev": true }, "spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", "dev": true }, "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "requires": { "through": "2" } }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { "extend-shallow": "^3.0.0" } }, "split2": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", "dev": true, "requires": { "through2": "^2.0.2" } }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" }, "dependencies": { "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" } } } }, "stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", "dev": true, "requires": { "duplexer2": "~0.1.0", "readable-stream": "^2.0.2" } }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" } }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { "ansi-regex": "^3.0.0" } }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-indent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", "dev": true }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" } }, "text-extensions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.8.0.tgz", "integrity": "sha512-mVzjRxuWnDKs/qH1rbOJEVHLlSX9kty9lpi7lMvLgU9S74mQ8/Ozg9UPcKxShh0qG2NZ+NyPOPpcZU4C1Eld9A==", "dev": true }, "through": { "version": "2.3.8", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "through2": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { "readable-stream": "^2.1.5", "xtend": "~4.0.1" } }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" } } } }, "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "regex-not": "^1.0.2", "safe-regex": "^1.1.0" } }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" } }, "traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", "dev": true }, "trim-newlines": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", "dev": true }, "trim-off-newlines": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", "dev": true }, "uglify-js": { "version": "3.4.9", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "dev": true, "optional": true, "requires": { "commander": "~2.17.1", "source-map": "~0.6.1" }, "dependencies": { "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true } } }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", "set-value": "^0.4.3" }, "dependencies": { "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" } }, "set-value": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", "is-plain-object": "^2.0.1", "to-object-path": "^0.3.0" } } } }, "universal-user-agent": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-2.0.1.tgz", "integrity": "sha512-vz+heWVydO0iyYAa65VHD7WZkYzhl7BeNVy4i54p4TF8OMiLSXdbuQe4hm+fmWAsL+rVibaQHXfhvkw3c1Ws2w==", "dev": true, "requires": { "os-name": "^2.0.1" } }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" }, "dependencies": { "has-value": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", "isobject": "^2.0.0" }, "dependencies": { "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { "isarray": "1.0.0" } } } }, "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true } } }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, "url-join": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=", "dev": true }, "url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=", "dev": true }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" } }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "win-release": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", "dev": true, "requires": { "semver": "^5.0.1" } }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true }, "wrap-ansi": { "version": "2.1.0", "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" }, "dependencies": { "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { "number-is-nan": "^1.0.0" } }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" } } } }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "xregexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", "dev": true }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yargs": { "version": "12.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", "dev": true, "requires": { "cliui": "^4.0.0", "decamelize": "^2.0.0", "find-up": "^3.0.0", "get-caller-file": "^1.0.1", "os-locale": "^3.0.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^2.0.0", "which-module": "^2.0.0", "y18n": "^3.2.1 || ^4.0.0", "yargs-parser": "^10.1.0" }, "dependencies": { "decamelize": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", "dev": true, "requires": { "xregexp": "4.0.0" } }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { "locate-path": "^3.0.0" } }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } } } }, "yargs-parser": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", "dev": true, "requires": { "camelcase": "^4.1.0" } } } } ISC License Copyright (c) 2016, Felix Frederick Becker Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. { "private": true, "repository": { "type": "git", "url": "https://github.com/felixfbecker/php-language-server-protocol" }, "release": { "verifyConditions": "@semantic-release/github", "prepare": [], "publish": "@semantic-release/github" }, "devDependencies": { "semantic-release": "^15.9.16" } } ReflectionMethod[] * * @var ReflectionMethod */ private $methods; /** * @var \phpDocumentor\Reflection\DocBlockFactory */ private $docBlockFactory; /** * @var \phpDocumentor\Reflection\Types\ContextFactory */ private $contextFactory; /** * @param object $target The target object that should receive the method calls * @param string $delimiter A delimiter for method calls on properties, for example someProperty->someMethod */ public function __construct($target, $delimiter = '->') { $this->target = $target; $this->delimiter = $delimiter; $this->docBlockFactory = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlockFactory::createInstance(); $this->contextFactory = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\ContextFactory(); $this->mapper = new \_HumbugBoxd02f763d3c56\JsonMapper(); } /** * Calls the appropriate method handler for an incoming Message * * @param string|object $msg The incoming message * @return mixed */ public function dispatch($msg) { if (\is_string($msg)) { $msg = \json_decode($msg); if (\json_last_error() !== \JSON_ERROR_NONE) { throw new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error(\json_last_error_msg(), \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorCode::PARSE_ERROR); } } // Find out the object and function that should be called $obj = $this->target; $parts = \explode($this->delimiter, $msg->method); // The function to call is always the last part of the method $fn = \array_pop($parts); // For namespaced methods like textDocument/didOpen, call the didOpen method on the $textDocument property // For simple methods like initialize, shutdown, exit, this loop will simply not be entered and $obj will be // the target foreach ($parts as $part) { if (!isset($obj->{$part})) { throw new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error("Method {$msg->method} is not implemented", \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorCode::METHOD_NOT_FOUND); } $obj = $obj->{$part}; } if (!isset($this->methods[$msg->method])) { try { $method = new \ReflectionMethod($obj, $fn); $this->methods[$msg->method] = $method; } catch (\ReflectionException $e) { throw new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error($e->getMessage(), \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorCode::METHOD_NOT_FOUND, null, $e); } } $method = $this->methods[$msg->method]; $parameters = $method->getParameters(); if ($method->getDocComment()) { $docBlock = $this->docBlockFactory->create($method->getDocComment(), $this->contextFactory->createFromReflector($method->getDeclaringClass())); $paramTags = $docBlock->getTagsByName('param'); } $args = []; if (isset($msg->params)) { // Find out the position if (\is_array($msg->params)) { $args = $msg->params; } else { if (\is_object($msg->params)) { foreach ($parameters as $pos => $parameter) { $value = null; foreach (\get_object_vars($msg->params) as $key => $val) { if ($parameter->name === $key) { $value = $val; break; } } $args[$pos] = $value; } } else { throw new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error('Params must be structured or omitted', \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorCode::INVALID_REQUEST); } } foreach ($args as $position => $value) { try { // If the type is structured (array or object), map it with JsonMapper if (\is_object($value)) { // Does the parameter have a type hint? $param = $parameters[$position]; if ($param->hasType()) { $paramType = $param->getType(); if ($paramType instanceof \ReflectionNamedType) { // We have object data to map and want the class name. // This should not include the `?` if the type was nullable. $class = $paramType->getName(); } else { // Fallback for php 7.0, which is still supported (and doesn't have nullable). $class = (string) $paramType; } $value = $this->mapper->map($value, new $class()); } } else { if (\is_array($value) && isset($docBlock)) { // Get the array type from the DocBlock $type = $paramTags[$position]->getType(); // For union types, use the first one that is a class array (often it is SomeClass[]|null) if ($type instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Compound) { for ($i = 0; $t = $type->get($i); $i++) { if ($t instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Array_ && $t->getValueType() instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Object_ && (string) $t->getValueType() !== 'object') { $class = (string) $t->getValueType()->getFqsen(); $value = $this->mapper->mapArray($value, [], $class); break; } } } else { if ($type instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Array_) { $class = (string) $type->getValueType()->getFqsen(); $value = $this->mapper->mapArray($value, [], $class); } else { throw new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error('Type is not matching @param tag', \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorCode::INVALID_PARAMS); } } } } } catch (\_HumbugBoxd02f763d3c56\JsonMapper_Exception $e) { throw new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error($e->getMessage(), \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorCode::INVALID_PARAMS, null, $e); } $args[$position] = $value; } } \ksort($args); $result = $obj->{$fn}(...$args); return $result; } } id) && isset($msg->error); } /** * @param int|string $id * @param \AdvancedJsonRpc\Error $error */ public function __construct($id, \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error $error) { parent::__construct($id); $this->error = $error; } } error)); } /** * @param int|string $id * @param mixed $result * @param ResponseError $error */ public function __construct($id) { $this->id = $id; } } method); } /** * @param string|int $id * @param string $method * @param object|array $params */ public function __construct($id, string $method, $params = null) { $this->id = $id; $this->method = $method; $this->params = $params; } } method); } /** * @param string $method * @param mixed $params */ public function __construct(string $method, $params = null) { $this->method = $method; $this->params = $params; } } result = $result; } } data = $data; } } method, $decoded->params ?? null); } else { if (\_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Request::isRequest($decoded)) { $obj = new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Request($decoded->id, $decoded->method, $decoded->params ?? null); } else { if (\_HumbugBoxd02f763d3c56\AdvancedJsonRpc\SuccessResponse::isSuccessResponse($decoded)) { $obj = new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\SuccessResponse($decoded->id, $decoded->result); } else { if (\_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorResponse::isErrorResponse($decoded)) { $obj = new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorResponse($decoded->id, new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error($decoded->error->message, $decoded->error->code, $decoded->error->data ?? null)); } else { throw new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error('Invalid message', \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorCode::INVALID_REQUEST); } } } } return $obj; } public function __toString() : string { $encoded = \json_encode($this); if ($encoded === \false) { throw new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error(\json_last_error_msg(), \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorCode::INTERNAL_ERROR); } return $encoded; } } ISC License Copyright (c) 2016, Felix Frederick Becker Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. [0, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BitwiseNot::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc::class => [10, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec::class => [10, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Int_::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\String_::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Array_::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Object_::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Bool_::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Unset_::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ErrorSuppress::class => [10, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_::class => [20, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot::class => [30, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul::class => [40, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div::class => [40, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod::class => [40, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus::class => [50, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus::class => [50, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat::class => [50, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftLeft::class => [60, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftRight::class => [60, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller::class => [70, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual::class => [70, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater::class => [70, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual::class => [70, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal::class => [80, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual::class => [80, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical::class => [80, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical::class => [80, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Spaceship::class => [80, 0], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd::class => [90, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor::class => [100, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr::class => [110, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd::class => [120, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr::class => [130, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce::class => [140, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary::class => [150, -1], // parser uses %left for assignments, but they really behave as %right \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Plus::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Minus::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mul::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Div::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Concat::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mod::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseAnd::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseOr::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseXor::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftLeft::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftRight::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Pow::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Coalesce::class => [160, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom::class => [165, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Print_::class => [168, 1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd::class => [170, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor::class => [180, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr::class => [190, -1], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::class => [200, -1], ]; /** @var int Current indentation level. */ protected $indentLevel; /** @var string Newline including current indentation. */ protected $nl; /** @var string Token placed at end of doc string to ensure it is followed by a newline. */ protected $docStringEndToken; /** @var bool Whether semicolon namespaces can be used (i.e. no global namespace is used) */ protected $canUseSemicolonNamespaces; /** @var array Pretty printer options */ protected $options; /** @var TokenStream Original tokens for use in format-preserving pretty print */ protected $origTokens; /** @var Internal\Differ Differ for node lists */ protected $nodeListDiffer; /** @var bool[] Map determining whether a certain character is a label character */ protected $labelCharMap; /** * @var int[][] Map from token classes and subnode names to FIXUP_* constants. This is used * during format-preserving prints to place additional parens/braces if necessary. */ protected $fixupMap; /** * @var int[][] Map from "{$node->getType()}->{$subNode}" to ['left' => $l, 'right' => $r], * where $l and $r specify the token type that needs to be stripped when removing * this node. */ protected $removalMap; /** * @var mixed[] Map from "{$node->getType()}->{$subNode}" to [$find, $beforeToken, $extraLeft, $extraRight]. * $find is an optional token after which the insertion occurs. $extraLeft/Right * are optionally added before/after the main insertions. */ protected $insertionMap; /** * @var string[] Map From "{$node->getType()}->{$subNode}" to string that should be inserted * between elements of this list subnode. */ protected $listInsertionMap; protected $emptyListInsertionMap; /** @var int[] Map from "{$node->getType()}->{$subNode}" to token before which the modifiers * should be reprinted. */ protected $modifierChangeMap; /** * Creates a pretty printer instance using the given options. * * Supported options: * * bool $shortArraySyntax = false: Whether to use [] instead of array() as the default array * syntax, if the node does not specify a format. * * @param array $options Dictionary of formatting options */ public function __construct(array $options = []) { $this->docStringEndToken = '_DOC_STRING_END_' . \mt_rand(); $defaultOptions = ['shortArraySyntax' => \false]; $this->options = $options + $defaultOptions; } /** * Reset pretty printing state. */ protected function resetState() { $this->indentLevel = 0; $this->nl = "\n"; $this->origTokens = null; } /** * Set indentation level * * @param int $level Level in number of spaces */ protected function setIndentLevel(int $level) { $this->indentLevel = $level; $this->nl = "\n" . \str_repeat(' ', $level); } /** * Increase indentation level. */ protected function indent() { $this->indentLevel += 4; $this->nl .= ' '; } /** * Decrease indentation level. */ protected function outdent() { \assert($this->indentLevel >= 4); $this->indentLevel -= 4; $this->nl = "\n" . \str_repeat(' ', $this->indentLevel); } /** * Pretty prints an array of statements. * * @param Node[] $stmts Array of statements * * @return string Pretty printed statements */ public function prettyPrint(array $stmts) : string { $this->resetState(); $this->preprocessNodes($stmts); return \ltrim($this->handleMagicTokens($this->pStmts($stmts, \false))); } /** * Pretty prints an expression. * * @param Expr $node Expression node * * @return string Pretty printed node */ public function prettyPrintExpr(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node) : string { $this->resetState(); return $this->handleMagicTokens($this->p($node)); } /** * Pretty prints a file of statements (includes the opening prettyPrint($stmts); if ($stmts[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\InlineHTML) { $p = \preg_replace('/^<\\?php\\s+\\?>\\n?/', '', $p); } if ($stmts[\count($stmts) - 1] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\InlineHTML) { $p = \preg_replace('/<\\?php$/', '', \rtrim($p)); } return $p; } /** * Preprocesses the top-level nodes to initialize pretty printer state. * * @param Node[] $nodes Array of nodes */ protected function preprocessNodes(array $nodes) { /* We can use semicolon-namespaces unless there is a global namespace declaration */ $this->canUseSemicolonNamespaces = \true; foreach ($nodes as $node) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_ && null === $node->name) { $this->canUseSemicolonNamespaces = \false; break; } } } /** * Handles (and removes) no-indent and doc-string-end tokens. * * @param string $str * @return string */ protected function handleMagicTokens(string $str) : string { // Replace doc-string-end tokens with nothing or a newline $str = \str_replace($this->docStringEndToken . ";\n", ";\n", $str); $str = \str_replace($this->docStringEndToken, "\n", $str); return $str; } /** * Pretty prints an array of nodes (statements) and indents them optionally. * * @param Node[] $nodes Array of nodes * @param bool $indent Whether to indent the printed nodes * * @return string Pretty printed statements */ protected function pStmts(array $nodes, bool $indent = \true) : string { if ($indent) { $this->indent(); } $result = ''; foreach ($nodes as $node) { $comments = $node->getComments(); if ($comments) { $result .= $this->nl . $this->pComments($comments); if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop) { continue; } } $result .= $this->nl . $this->p($node); } if ($indent) { $this->outdent(); } return $result; } /** * Pretty-print an infix operation while taking precedence into account. * * @param string $class Node class of operator * @param Node $leftNode Left-hand side node * @param string $operatorString String representation of the operator * @param Node $rightNode Right-hand side node * * @return string Pretty printed infix operation */ protected function pInfixOp(string $class, \_HumbugBoxd02f763d3c56\PhpParser\Node $leftNode, string $operatorString, \_HumbugBoxd02f763d3c56\PhpParser\Node $rightNode) : string { list($precedence, $associativity) = $this->precedenceMap[$class]; return $this->pPrec($leftNode, $precedence, $associativity, -1) . $operatorString . $this->pPrec($rightNode, $precedence, $associativity, 1); } /** * Pretty-print a prefix operation while taking precedence into account. * * @param string $class Node class of operator * @param string $operatorString String representation of the operator * @param Node $node Node * * @return string Pretty printed prefix operation */ protected function pPrefixOp(string $class, string $operatorString, \_HumbugBoxd02f763d3c56\PhpParser\Node $node) : string { list($precedence, $associativity) = $this->precedenceMap[$class]; return $operatorString . $this->pPrec($node, $precedence, $associativity, 1); } /** * Pretty-print a postfix operation while taking precedence into account. * * @param string $class Node class of operator * @param string $operatorString String representation of the operator * @param Node $node Node * * @return string Pretty printed postfix operation */ protected function pPostfixOp(string $class, \_HumbugBoxd02f763d3c56\PhpParser\Node $node, string $operatorString) : string { list($precedence, $associativity) = $this->precedenceMap[$class]; return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString; } /** * Prints an expression node with the least amount of parentheses necessary to preserve the meaning. * * @param Node $node Node to pretty print * @param int $parentPrecedence Precedence of the parent operator * @param int $parentAssociativity Associativity of parent operator * (-1 is left, 0 is nonassoc, 1 is right) * @param int $childPosition Position of the node relative to the operator * (-1 is left, 1 is right) * * @return string The pretty printed node */ protected function pPrec(\_HumbugBoxd02f763d3c56\PhpParser\Node $node, int $parentPrecedence, int $parentAssociativity, int $childPosition) : string { $class = \get_class($node); if (isset($this->precedenceMap[$class])) { $childPrecedence = $this->precedenceMap[$class][0]; if ($childPrecedence > $parentPrecedence || $parentPrecedence === $childPrecedence && $parentAssociativity !== $childPosition) { return '(' . $this->p($node) . ')'; } } return $this->p($node); } /** * Pretty prints an array of nodes and implodes the printed values. * * @param Node[] $nodes Array of Nodes to be printed * @param string $glue Character to implode with * * @return string Imploded pretty printed nodes */ protected function pImplode(array $nodes, string $glue = '') : string { $pNodes = []; foreach ($nodes as $node) { if (null === $node) { $pNodes[] = ''; } else { $pNodes[] = $this->p($node); } } return \implode($glue, $pNodes); } /** * Pretty prints an array of nodes and implodes the printed values with commas. * * @param Node[] $nodes Array of Nodes to be printed * * @return string Comma separated pretty printed nodes */ protected function pCommaSeparated(array $nodes) : string { return $this->pImplode($nodes, ', '); } /** * Pretty prints a comma-separated list of nodes in multiline style, including comments. * * The result includes a leading newline and one level of indentation (same as pStmts). * * @param Node[] $nodes Array of Nodes to be printed * @param bool $trailingComma Whether to use a trailing comma * * @return string Comma separated pretty printed nodes in multiline style */ protected function pCommaSeparatedMultiline(array $nodes, bool $trailingComma) : string { $this->indent(); $result = ''; $lastIdx = \count($nodes) - 1; foreach ($nodes as $idx => $node) { if ($node !== null) { $comments = $node->getComments(); if ($comments) { $result .= $this->nl . $this->pComments($comments); } $result .= $this->nl . $this->p($node); } else { $result .= $this->nl; } if ($trailingComma || $idx !== $lastIdx) { $result .= ','; } } $this->outdent(); return $result; } /** * Prints reformatted text of the passed comments. * * @param Comment[] $comments List of comments * * @return string Reformatted text of comments */ protected function pComments(array $comments) : string { $formattedComments = []; foreach ($comments as $comment) { $formattedComments[] = \str_replace("\n", $this->nl, $comment->getReformattedText()); } return \implode($this->nl, $formattedComments); } /** * Perform a format-preserving pretty print of an AST. * * The format preservation is best effort. For some changes to the AST the formatting will not * be preserved (at least not locally). * * In order to use this method a number of prerequisites must be satisfied: * * The startTokenPos and endTokenPos attributes in the lexer must be enabled. * * The CloningVisitor must be run on the AST prior to modification. * * The original tokens must be provided, using the getTokens() method on the lexer. * * @param Node[] $stmts Modified AST with links to original AST * @param Node[] $origStmts Original AST with token offset information * @param array $origTokens Tokens of the original code * * @return string */ public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string { $this->initializeNodeListDiffer(); $this->initializeLabelCharMap(); $this->initializeFixupMap(); $this->initializeRemovalMap(); $this->initializeInsertionMap(); $this->initializeListInsertionMap(); $this->initializeEmptyListInsertionMap(); $this->initializeModifierChangeMap(); $this->resetState(); $this->origTokens = new \_HumbugBoxd02f763d3c56\PhpParser\Internal\TokenStream($origTokens); $this->preprocessNodes($stmts); $pos = 0; $result = $this->pArray($stmts, $origStmts, $pos, 0, 'File', 'stmts', null); if (null !== $result) { $result .= $this->origTokens->getTokenCode($pos, \count($origTokens), 0); } else { // Fallback // TODO Add pStmts($stmts, \false); } return \ltrim($this->handleMagicTokens($result)); } protected function pFallback(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { return $this->{'p' . $node->getType()}($node); } /** * Pretty prints a node. * * This method also handles formatting preservation for nodes. * * @param Node $node Node to be pretty printed * @param bool $parentFormatPreserved Whether parent node has preserved formatting * * @return string Pretty printed node */ protected function p(\_HumbugBoxd02f763d3c56\PhpParser\Node $node, $parentFormatPreserved = \false) : string { // No orig tokens means this is a normal pretty print without preservation of formatting if (!$this->origTokens) { return $this->{'p' . $node->getType()}($node); } /** @var Node $origNode */ $origNode = $node->getAttribute('origNode'); if (null === $origNode) { return $this->pFallback($node); } $class = \get_class($node); \assert($class === \get_class($origNode)); $startPos = $origNode->getStartTokenPos(); $endPos = $origNode->getEndTokenPos(); \assert($startPos >= 0 && $endPos >= 0); $fallbackNode = $node; if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ && $node->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { // Normalize node structure of anonymous classes $node = \_HumbugBoxd02f763d3c56\PhpParser\Internal\PrintableNewAnonClassNode::fromNewNode($node); $origNode = \_HumbugBoxd02f763d3c56\PhpParser\Internal\PrintableNewAnonClassNode::fromNewNode($origNode); } // InlineHTML node does not contain closing and opening PHP tags. If the parent formatting // is not preserved, then we need to use the fallback code to make sure the tags are // printed. if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\InlineHTML && !$parentFormatPreserved) { return $this->pFallback($fallbackNode); } $indentAdjustment = $this->indentLevel - $this->origTokens->getIndentationBefore($startPos); $type = $node->getType(); $fixupInfo = $this->fixupMap[$class] ?? null; $result = ''; $pos = $startPos; foreach ($node->getSubNodeNames() as $subNodeName) { $subNode = $node->{$subNodeName}; $origSubNode = $origNode->{$subNodeName}; if (!$subNode instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node && $subNode !== null || !$origSubNode instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node && $origSubNode !== null) { if ($subNode === $origSubNode) { // Unchanged, can reuse old code continue; } if (\is_array($subNode) && \is_array($origSubNode)) { // Array subnode changed, we might be able to reconstruct it $listResult = $this->pArray($subNode, $origSubNode, $pos, $indentAdjustment, $type, $subNodeName, $fixupInfo[$subNodeName] ?? null); if (null === $listResult) { return $this->pFallback($fallbackNode); } $result .= $listResult; continue; } if (\is_int($subNode) && \is_int($origSubNode)) { // Check if this is a modifier change $key = $type . '->' . $subNodeName; if (!isset($this->modifierChangeMap[$key])) { return $this->pFallback($fallbackNode); } $findToken = $this->modifierChangeMap[$key]; $result .= $this->pModifiers($subNode); $pos = $this->origTokens->findRight($pos, $findToken); continue; } // If a non-node, non-array subnode changed, we don't be able to do a partial // reconstructions, as we don't have enough offset information. Pretty print the // whole node instead. return $this->pFallback($fallbackNode); } $extraLeft = ''; $extraRight = ''; if ($origSubNode !== null) { $subStartPos = $origSubNode->getStartTokenPos(); $subEndPos = $origSubNode->getEndTokenPos(); \assert($subStartPos >= 0 && $subEndPos >= 0); } else { if ($subNode === null) { // Both null, nothing to do continue; } // A node has been inserted, check if we have insertion information for it $key = $type . '->' . $subNodeName; if (!isset($this->insertionMap[$key])) { return $this->pFallback($fallbackNode); } list($findToken, $beforeToken, $extraLeft, $extraRight) = $this->insertionMap[$key]; if (null !== $findToken) { $subStartPos = $this->origTokens->findRight($pos, $findToken) + (int) (!$beforeToken); } else { $subStartPos = $pos; } if (null === $extraLeft && null !== $extraRight) { // If inserting on the right only, skipping whitespace looks better $subStartPos = $this->origTokens->skipRightWhitespace($subStartPos); } $subEndPos = $subStartPos - 1; } if (null === $subNode) { // A node has been removed, check if we have removal information for it $key = $type . '->' . $subNodeName; if (!isset($this->removalMap[$key])) { return $this->pFallback($fallbackNode); } // Adjust positions to account for additional tokens that must be skipped $removalInfo = $this->removalMap[$key]; if (isset($removalInfo['left'])) { $subStartPos = $this->origTokens->skipLeft($subStartPos - 1, $removalInfo['left']) + 1; } if (isset($removalInfo['right'])) { $subEndPos = $this->origTokens->skipRight($subEndPos + 1, $removalInfo['right']) - 1; } } $result .= $this->origTokens->getTokenCode($pos, $subStartPos, $indentAdjustment); if (null !== $subNode) { $result .= $extraLeft; $origIndentLevel = $this->indentLevel; $this->setIndentLevel($this->origTokens->getIndentationBefore($subStartPos) + $indentAdjustment); // If it's the same node that was previously in this position, it certainly doesn't // need fixup. It's important to check this here, because our fixup checks are more // conservative than strictly necessary. if (isset($fixupInfo[$subNodeName]) && $subNode->getAttribute('origNode') !== $origSubNode) { $fixup = $fixupInfo[$subNodeName]; $res = $this->pFixup($fixup, $subNode, $class, $subStartPos, $subEndPos); } else { $res = $this->p($subNode, \true); } $this->safeAppend($result, $res); $this->setIndentLevel($origIndentLevel); $result .= $extraRight; } $pos = $subEndPos + 1; } $result .= $this->origTokens->getTokenCode($pos, $endPos + 1, $indentAdjustment); return $result; } /** * Perform a format-preserving pretty print of an array. * * @param array $nodes New nodes * @param array $origNodes Original nodes * @param int $pos Current token position (updated by reference) * @param int $indentAdjustment Adjustment for indentation * @param string $parentNodeType Type of the containing node. * @param string $subNodeName Name of array subnode. * @param null|int $fixup Fixup information for array item nodes * * @return null|string Result of pretty print or null if cannot preserve formatting */ protected function pArray(array $nodes, array $origNodes, int &$pos, int $indentAdjustment, string $parentNodeType, string $subNodeName, $fixup) { $diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes); $mapKey = $parentNodeType . '->' . $subNodeName; $insertStr = $this->listInsertionMap[$mapKey] ?? null; $isStmtList = $subNodeName === 'stmts'; $beforeFirstKeepOrReplace = \true; $skipRemovedNode = \false; $delayedAdd = []; $lastElemIndentLevel = $this->indentLevel; $insertNewline = \false; if ($insertStr === "\n") { $insertStr = ''; $insertNewline = \true; } if ($isStmtList && \count($origNodes) === 1 && \count($nodes) !== 1) { $startPos = $origNodes[0]->getStartTokenPos(); $endPos = $origNodes[0]->getEndTokenPos(); \assert($startPos >= 0 && $endPos >= 0); if (!$this->origTokens->haveBraces($startPos, $endPos)) { // This was a single statement without braces, but either additional statements // have been added, or the single statement has been removed. This requires the // addition of braces. For now fall back. // TODO: Try to preserve formatting return null; } } $result = ''; foreach ($diff as $i => $diffElem) { $diffType = $diffElem->type; /** @var Node|null $arrItem */ $arrItem = $diffElem->new; /** @var Node|null $origArrItem */ $origArrItem = $diffElem->old; if ($diffType === \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_KEEP || $diffType === \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_REPLACE) { $beforeFirstKeepOrReplace = \false; if ($origArrItem === null || $arrItem === null) { // We can only handle the case where both are null if ($origArrItem === $arrItem) { continue; } return null; } if (!$arrItem instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node || !$origArrItem instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { // We can only deal with nodes. This can occur for Names, which use string arrays. return null; } $itemStartPos = $origArrItem->getStartTokenPos(); $itemEndPos = $origArrItem->getEndTokenPos(); \assert($itemStartPos >= 0 && $itemEndPos >= 0 && $itemStartPos >= $pos); $origIndentLevel = $this->indentLevel; $lastElemIndentLevel = $this->origTokens->getIndentationBefore($itemStartPos) + $indentAdjustment; $this->setIndentLevel($lastElemIndentLevel); $comments = $arrItem->getComments(); $origComments = $origArrItem->getComments(); $commentStartPos = $origComments ? $origComments[0]->getStartTokenPos() : $itemStartPos; \assert($commentStartPos >= 0); if ($commentStartPos < $pos) { // Comments may be assigned to multiple nodes if they start at the same position. // Make sure we don't try to print them multiple times. $commentStartPos = $itemStartPos; } if ($skipRemovedNode) { if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) { // We'd remove the brace of a code block. // TODO: Preserve formatting. $this->setIndentLevel($origIndentLevel); return null; } } else { $result .= $this->origTokens->getTokenCode($pos, $commentStartPos, $indentAdjustment); } if (!empty($delayedAdd)) { /** @var Node $delayedAddNode */ foreach ($delayedAdd as $delayedAddNode) { if ($insertNewline) { $delayedAddComments = $delayedAddNode->getComments(); if ($delayedAddComments) { $result .= $this->pComments($delayedAddComments) . $this->nl; } } $this->safeAppend($result, $this->p($delayedAddNode, \true)); if ($insertNewline) { $result .= $insertStr . $this->nl; } else { $result .= $insertStr; } } $delayedAdd = []; } if ($comments !== $origComments) { if ($comments) { $result .= $this->pComments($comments) . $this->nl; } } else { $result .= $this->origTokens->getTokenCode($commentStartPos, $itemStartPos, $indentAdjustment); } // If we had to remove anything, we have done so now. $skipRemovedNode = \false; } elseif ($diffType === \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_ADD) { if (null === $insertStr) { // We don't have insertion information for this list type return null; } if ($insertStr === ', ' && $this->isMultiline($origNodes)) { $insertStr = ','; $insertNewline = \true; } if ($beforeFirstKeepOrReplace) { // Will be inserted at the next "replace" or "keep" element $delayedAdd[] = $arrItem; continue; } $itemStartPos = $pos; $itemEndPos = $pos - 1; $origIndentLevel = $this->indentLevel; $this->setIndentLevel($lastElemIndentLevel); if ($insertNewline) { $comments = $arrItem->getComments(); if ($comments) { $result .= $this->nl . $this->pComments($comments); } $result .= $insertStr . $this->nl; } else { $result .= $insertStr; } } elseif ($diffType === \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_REMOVE) { if (!$origArrItem instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { // We only support removal for nodes return null; } $itemStartPos = $origArrItem->getStartTokenPos(); $itemEndPos = $origArrItem->getEndTokenPos(); \assert($itemStartPos >= 0 && $itemEndPos >= 0); // Consider comments part of the node. $origComments = $origArrItem->getComments(); if ($origComments) { $itemStartPos = $origComments[0]->getStartTokenPos(); } if ($i === 0) { // If we're removing from the start, keep the tokens before the node and drop those after it, // instead of the other way around. $result .= $this->origTokens->getTokenCode($pos, $itemStartPos, $indentAdjustment); $skipRemovedNode = \true; } else { if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) { // We'd remove the brace of a code block. // TODO: Preserve formatting. return null; } } $pos = $itemEndPos + 1; continue; } else { throw new \Exception("Shouldn't happen"); } if (null !== $fixup && $arrItem->getAttribute('origNode') !== $origArrItem) { $res = $this->pFixup($fixup, $arrItem, null, $itemStartPos, $itemEndPos); } else { $res = $this->p($arrItem, \true); } $this->safeAppend($result, $res); $this->setIndentLevel($origIndentLevel); $pos = $itemEndPos + 1; } if ($skipRemovedNode) { // TODO: Support removing single node. return null; } if (!empty($delayedAdd)) { if (!isset($this->emptyListInsertionMap[$mapKey])) { return null; } list($findToken, $extraLeft, $extraRight) = $this->emptyListInsertionMap[$mapKey]; if (null !== $findToken) { $insertPos = $this->origTokens->findRight($pos, $findToken) + 1; $result .= $this->origTokens->getTokenCode($pos, $insertPos, $indentAdjustment); $pos = $insertPos; } $first = \true; $result .= $extraLeft; foreach ($delayedAdd as $delayedAddNode) { if (!$first) { $result .= $insertStr; } $result .= $this->p($delayedAddNode, \true); $first = \false; } $result .= $extraRight; } return $result; } /** * Print node with fixups. * * Fixups here refer to the addition of extra parentheses, braces or other characters, that * are required to preserve program semantics in a certain context (e.g. to maintain precedence * or because only certain expressions are allowed in certain places). * * @param int $fixup Fixup type * @param Node $subNode Subnode to print * @param string|null $parentClass Class of parent node * @param int $subStartPos Original start pos of subnode * @param int $subEndPos Original end pos of subnode * * @return string Result of fixed-up print of subnode */ protected function pFixup(int $fixup, \_HumbugBoxd02f763d3c56\PhpParser\Node $subNode, $parentClass, int $subStartPos, int $subEndPos) : string { switch ($fixup) { case self::FIXUP_PREC_LEFT: case self::FIXUP_PREC_RIGHT: if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) { list($precedence, $associativity) = $this->precedenceMap[$parentClass]; return $this->pPrec($subNode, $precedence, $associativity, $fixup === self::FIXUP_PREC_LEFT ? -1 : 1); } break; case self::FIXUP_CALL_LHS: if ($this->callLhsRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos)) { return '(' . $this->p($subNode) . ')'; } break; case self::FIXUP_DEREF_LHS: if ($this->dereferenceLhsRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos)) { return '(' . $this->p($subNode) . ')'; } break; case self::FIXUP_BRACED_NAME: case self::FIXUP_VAR_BRACED_NAME: if ($subNode instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr && !$this->origTokens->haveBraces($subStartPos, $subEndPos)) { return ($fixup === self::FIXUP_VAR_BRACED_NAME ? '$' : '') . '{' . $this->p($subNode) . '}'; } break; case self::FIXUP_ENCAPSED: if (!$subNode instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart && !$this->origTokens->haveBraces($subStartPos, $subEndPos)) { return '{' . $this->p($subNode) . '}'; } break; default: throw new \Exception('Cannot happen'); } // Nothing special to do return $this->p($subNode); } /** * Appends to a string, ensuring whitespace between label characters. * * Example: "echo" and "$x" result in "echo$x", but "echo" and "x" result in "echo x". * Without safeAppend the result would be "echox", which does not preserve semantics. * * @param string $str * @param string $append */ protected function safeAppend(string &$str, string $append) { if ($str === "") { $str = $append; return; } if ($append === "") { return; } if (!$this->labelCharMap[$append[0]] || !$this->labelCharMap[$str[\strlen($str) - 1]]) { $str .= $append; } else { $str .= " " . $append; } } /** * Determines whether the LHS of a call must be wrapped in parenthesis. * * @param Node $node LHS of a call * * @return bool Whether parentheses are required */ protected function callLhsRequiresParens(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : bool { return !($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafeMethodCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_); } /** * Determines whether the LHS of a dereferencing operation must be wrapped in parenthesis. * * @param Node $node LHS of dereferencing operation * * @return bool Whether parentheses are required */ protected function dereferenceLhsRequiresParens(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : bool { return !($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafePropertyFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafeMethodCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch); } /** * Print modifiers, including trailing whitespace. * * @param int $modifiers Modifier mask to print * * @return string Printed modifiers */ protected function pModifiers(int $modifiers) { return ($modifiers & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') . ($modifiers & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') . ($modifiers & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') . ($modifiers & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') . ($modifiers & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') . ($modifiers & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL ? 'final ' : ''); } /** * Determine whether a list of nodes uses multiline formatting. * * @param (Node|null)[] $nodes Node list * * @return bool Whether multiline formatting is used */ protected function isMultiline(array $nodes) : bool { if (\count($nodes) < 2) { return \false; } $pos = -1; foreach ($nodes as $node) { if (null === $node) { continue; } $endPos = $node->getEndTokenPos() + 1; if ($pos >= 0) { $text = $this->origTokens->getTokenCode($pos, $endPos, 0); if (\false === \strpos($text, "\n")) { // We require that a newline is present between *every* item. If the formatting // is inconsistent, with only some items having newlines, we don't consider it // as multiline return \false; } } $pos = $endPos; } return \true; } /** * Lazily initializes label char map. * * The label char map determines whether a certain character may occur in a label. */ protected function initializeLabelCharMap() { if ($this->labelCharMap) { return; } $this->labelCharMap = []; for ($i = 0; $i < 256; $i++) { // Since PHP 7.1 The lower range is 0x80. However, we also want to support code for // older versions. $this->labelCharMap[\chr($i)] = $i >= 0x7f || \ctype_alnum($i); } } /** * Lazily initializes node list differ. * * The node list differ is used to determine differences between two array subnodes. */ protected function initializeNodeListDiffer() { if ($this->nodeListDiffer) { return; } $this->nodeListDiffer = new \_HumbugBoxd02f763d3c56\PhpParser\Internal\Differ(function ($a, $b) { if ($a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { return $a === $b->getAttribute('origNode'); } // Can happen for array destructuring return $a === null && $b === null; }); } /** * Lazily initializes fixup map. * * The fixup map is used to determine whether a certain subnode of a certain node may require * some kind of "fixup" operation, e.g. the addition of parenthesis or braces. */ protected function initializeFixupMap() { if ($this->fixupMap) { return; } $this->fixupMap = [ \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc::class => ['var' => self::FIXUP_PREC_RIGHT], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec::class => ['var' => self::FIXUP_PREC_RIGHT], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc::class => ['var' => self::FIXUP_PREC_LEFT], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec::class => ['var' => self::FIXUP_PREC_LEFT], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_::class => ['expr' => self::FIXUP_PREC_LEFT, 'class' => self::FIXUP_PREC_RIGHT], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary::class => ['cond' => self::FIXUP_PREC_LEFT, 'else' => self::FIXUP_PREC_RIGHT], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall::class => ['class' => self::FIXUP_DEREF_LHS], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch::class => ['var' => self::FIXUP_DEREF_LHS], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_::class => ['class' => self::FIXUP_DEREF_LHS], // TODO: FIXUP_NEW_VARIABLE \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall::class => ['var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafeMethodCall::class => ['var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch::class => ['class' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_VAR_BRACED_NAME], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch::class => ['var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafePropertyFetch::class => ['var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME], \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\Encapsed::class => ['parts' => self::FIXUP_ENCAPSED], ]; $binaryOps = [\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Pow::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftLeft::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftRight::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Spaceship::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr::class]; foreach ($binaryOps as $binaryOp) { $this->fixupMap[$binaryOp] = ['left' => self::FIXUP_PREC_LEFT, 'right' => self::FIXUP_PREC_RIGHT]; } $assignOps = [\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Plus::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Minus::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mul::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Div::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Concat::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mod::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseAnd::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseOr::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseXor::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftLeft::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftRight::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Pow::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Coalesce::class]; foreach ($assignOps as $assignOp) { $this->fixupMap[$assignOp] = ['var' => self::FIXUP_PREC_LEFT, 'expr' => self::FIXUP_PREC_RIGHT]; } $prefixOps = [\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BitwiseNot::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Int_::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\String_::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Array_::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Object_::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Bool_::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Unset_::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ErrorSuppress::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Print_::class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::class]; foreach ($prefixOps as $prefixOp) { $this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_RIGHT]; } } /** * Lazily initializes the removal map. * * The removal map is used to determine which additional tokens should be returned when a * certain node is replaced by null. */ protected function initializeRemovalMap() { if ($this->removalMap) { return; } $stripBoth = ['left' => \T_WHITESPACE, 'right' => \T_WHITESPACE]; $stripLeft = ['left' => \T_WHITESPACE]; $stripRight = ['right' => \T_WHITESPACE]; $stripDoubleArrow = ['right' => \T_DOUBLE_ARROW]; $stripColon = ['left' => ':']; $stripEquals = ['left' => '=']; $this->removalMap = ['Expr_ArrayDimFetch->dim' => $stripBoth, 'Expr_ArrayItem->key' => $stripDoubleArrow, 'Expr_ArrowFunction->returnType' => $stripColon, 'Expr_Closure->returnType' => $stripColon, 'Expr_Exit->expr' => $stripBoth, 'Expr_Ternary->if' => $stripBoth, 'Expr_Yield->key' => $stripDoubleArrow, 'Expr_Yield->value' => $stripBoth, 'Param->type' => $stripRight, 'Param->default' => $stripEquals, 'Stmt_Break->num' => $stripBoth, 'Stmt_Catch->var' => $stripLeft, 'Stmt_ClassMethod->returnType' => $stripColon, 'Stmt_Class->extends' => ['left' => \T_EXTENDS], 'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS], 'Stmt_Continue->num' => $stripBoth, 'Stmt_Foreach->keyVar' => $stripDoubleArrow, 'Stmt_Function->returnType' => $stripColon, 'Stmt_If->else' => $stripLeft, 'Stmt_Namespace->name' => $stripLeft, 'Stmt_Property->type' => $stripRight, 'Stmt_PropertyProperty->default' => $stripEquals, 'Stmt_Return->expr' => $stripBoth, 'Stmt_StaticVar->default' => $stripEquals, 'Stmt_TraitUseAdaptation_Alias->newName' => $stripLeft, 'Stmt_TryCatch->finally' => $stripLeft]; } protected function initializeInsertionMap() { if ($this->insertionMap) { return; } // TODO: "yield" where both key and value are inserted doesn't work // [$find, $beforeToken, $extraLeft, $extraRight] $this->insertionMap = [ 'Expr_ArrayDimFetch->dim' => ['[', \false, null, null], 'Expr_ArrayItem->key' => [null, \false, null, ' => '], 'Expr_ArrowFunction->returnType' => [')', \false, ' : ', null], 'Expr_Closure->returnType' => [')', \false, ' : ', null], 'Expr_Ternary->if' => ['?', \false, ' ', ' '], 'Expr_Yield->key' => [\T_YIELD, \false, null, ' => '], 'Expr_Yield->value' => [\T_YIELD, \false, ' ', null], 'Param->type' => [null, \false, null, ' '], 'Param->default' => [null, \false, ' = ', null], 'Stmt_Break->num' => [\T_BREAK, \false, ' ', null], 'Stmt_Catch->var' => [null, \false, ' ', null], 'Stmt_ClassMethod->returnType' => [')', \false, ' : ', null], 'Stmt_Class->extends' => [null, \false, ' extends ', null], 'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null], 'Stmt_Continue->num' => [\T_CONTINUE, \false, ' ', null], 'Stmt_Foreach->keyVar' => [\T_AS, \false, null, ' => '], 'Stmt_Function->returnType' => [')', \false, ' : ', null], 'Stmt_If->else' => [null, \false, ' ', null], 'Stmt_Namespace->name' => [\T_NAMESPACE, \false, ' ', null], 'Stmt_Property->type' => [\T_VARIABLE, \true, null, ' '], 'Stmt_PropertyProperty->default' => [null, \false, ' = ', null], 'Stmt_Return->expr' => [\T_RETURN, \false, ' ', null], 'Stmt_StaticVar->default' => [null, \false, ' = ', null], //'Stmt_TraitUseAdaptation_Alias->newName' => [T_AS, false, ' ', null], // TODO 'Stmt_TryCatch->finally' => [null, \false, ' ', null], ]; } protected function initializeListInsertionMap() { if ($this->listInsertionMap) { return; } $this->listInsertionMap = [ // special //'Expr_ShellExec->parts' => '', // TODO These need to be treated more carefully //'Scalar_Encapsed->parts' => '', 'Stmt_Catch->types' => '|', 'UnionType->types' => '|', 'Stmt_If->elseifs' => ' ', 'Stmt_TryCatch->catches' => ' ', // comma-separated lists 'Expr_Array->items' => ', ', 'Expr_ArrowFunction->params' => ', ', 'Expr_Closure->params' => ', ', 'Expr_Closure->uses' => ', ', 'Expr_FuncCall->args' => ', ', 'Expr_Isset->vars' => ', ', 'Expr_List->items' => ', ', 'Expr_MethodCall->args' => ', ', 'Expr_NullsafeMethodCall->args' => ', ', 'Expr_New->args' => ', ', 'Expr_PrintableNewAnonClass->args' => ', ', 'Expr_StaticCall->args' => ', ', 'Stmt_ClassConst->consts' => ', ', 'Stmt_ClassMethod->params' => ', ', 'Stmt_Class->implements' => ', ', 'Expr_PrintableNewAnonClass->implements' => ', ', 'Stmt_Const->consts' => ', ', 'Stmt_Declare->declares' => ', ', 'Stmt_Echo->exprs' => ', ', 'Stmt_For->init' => ', ', 'Stmt_For->cond' => ', ', 'Stmt_For->loop' => ', ', 'Stmt_Function->params' => ', ', 'Stmt_Global->vars' => ', ', 'Stmt_GroupUse->uses' => ', ', 'Stmt_Interface->extends' => ', ', 'Stmt_Match->arms' => ', ', 'Stmt_Property->props' => ', ', 'Stmt_StaticVar->vars' => ', ', 'Stmt_TraitUse->traits' => ', ', 'Stmt_TraitUseAdaptation_Precedence->insteadof' => ', ', 'Stmt_Unset->vars' => ', ', 'Stmt_Use->uses' => ', ', 'MatchArm->conds' => ', ', 'AttributeGroup->attrs' => ', ', // statement lists 'Expr_Closure->stmts' => "\n", 'Stmt_Case->stmts' => "\n", 'Stmt_Catch->stmts' => "\n", 'Stmt_Class->stmts' => "\n", 'Expr_PrintableNewAnonClass->stmts' => "\n", 'Stmt_Interface->stmts' => "\n", 'Stmt_Trait->stmts' => "\n", 'Stmt_ClassMethod->stmts' => "\n", 'Stmt_Declare->stmts' => "\n", 'Stmt_Do->stmts' => "\n", 'Stmt_ElseIf->stmts' => "\n", 'Stmt_Else->stmts' => "\n", 'Stmt_Finally->stmts' => "\n", 'Stmt_Foreach->stmts' => "\n", 'Stmt_For->stmts' => "\n", 'Stmt_Function->stmts' => "\n", 'Stmt_If->stmts' => "\n", 'Stmt_Namespace->stmts' => "\n", 'Stmt_Class->attrGroups' => "\n", 'Stmt_Interface->attrGroups' => "\n", 'Stmt_Trait->attrGroups' => "\n", 'Stmt_Function->attrGroups' => "\n", 'Stmt_ClassMethod->attrGroups' => "\n", 'Stmt_ClassConst->attrGroups' => "\n", 'Stmt_Property->attrGroups' => "\n", 'Expr_PrintableNewAnonClass->attrGroups' => ' ', 'Expr_Closure->attrGroups' => ' ', 'Expr_ArrowFunction->attrGroups' => ' ', 'Param->attrGroups' => ' ', 'Stmt_Switch->cases' => "\n", 'Stmt_TraitUse->adaptations' => "\n", 'Stmt_TryCatch->stmts' => "\n", 'Stmt_While->stmts' => "\n", // dummy for top-level context 'File->stmts' => "\n", ]; } protected function initializeEmptyListInsertionMap() { if ($this->emptyListInsertionMap) { return; } // TODO Insertion into empty statement lists. // [$find, $extraLeft, $extraRight] $this->emptyListInsertionMap = ['Expr_ArrowFunction->params' => ['(', '', ''], 'Expr_Closure->uses' => [')', ' use(', ')'], 'Expr_Closure->params' => ['(', '', ''], 'Expr_FuncCall->args' => ['(', '', ''], 'Expr_MethodCall->args' => ['(', '', ''], 'Expr_NullsafeMethodCall->args' => ['(', '', ''], 'Expr_New->args' => ['(', '', ''], 'Expr_PrintableNewAnonClass->args' => ['(', '', ''], 'Expr_PrintableNewAnonClass->implements' => [null, ' implements ', ''], 'Expr_StaticCall->args' => ['(', '', ''], 'Stmt_Class->implements' => [null, ' implements ', ''], 'Stmt_ClassMethod->params' => ['(', '', ''], 'Stmt_Interface->extends' => [null, ' extends ', ''], 'Stmt_Function->params' => ['(', '', '']]; } protected function initializeModifierChangeMap() { if ($this->modifierChangeMap) { return; } $this->modifierChangeMap = ['Stmt_ClassConst->flags' => \T_CONST, 'Stmt_ClassMethod->flags' => \T_FUNCTION, 'Stmt_Class->flags' => \T_CLASS, 'Stmt_Property->flags' => \T_VARIABLE, 'Param->flags' => \T_VARIABLE]; // List of integer subnodes that are not modifiers: // Expr_Include->type // Stmt_GroupUse->type // Stmt_Use->type // Stmt_UseUse->type } } dumpComments = !empty($options['dumpComments']); $this->dumpPositions = !empty($options['dumpPositions']); } /** * Dumps a node or array. * * @param array|Node $node Node or array to dump * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if * the dumpPositions option is enabled and the dumping of node offsets * is desired. * * @return string Dumped value */ public function dump($node, string $code = null) : string { $this->code = $code; return $this->dumpRecursive($node); } protected function dumpRecursive($node) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $r = $node->getType(); if ($this->dumpPositions && null !== ($p = $this->dumpPosition($node))) { $r .= $p; } $r .= '('; foreach ($node->getSubNodeNames() as $key) { $r .= "\n " . $key . ': '; $value = $node->{$key}; if (null === $value) { $r .= 'null'; } elseif (\false === $value) { $r .= 'false'; } elseif (\true === $value) { $r .= 'true'; } elseif (\is_scalar($value)) { if ('flags' === $key || 'newModifier' === $key) { $r .= $this->dumpFlags($value); } elseif ('type' === $key && $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_) { $r .= $this->dumpIncludeType($value); } elseif ('type' === $key && ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse)) { $r .= $this->dumpUseType($value); } else { $r .= $value; } } else { $r .= \str_replace("\n", "\n ", $this->dumpRecursive($value)); } } if ($this->dumpComments && ($comments = $node->getComments())) { $r .= "\n comments: " . \str_replace("\n", "\n ", $this->dumpRecursive($comments)); } } elseif (\is_array($node)) { $r = 'array('; foreach ($node as $key => $value) { $r .= "\n " . $key . ': '; if (null === $value) { $r .= 'null'; } elseif (\false === $value) { $r .= 'false'; } elseif (\true === $value) { $r .= 'true'; } elseif (\is_scalar($value)) { $r .= $value; } else { $r .= \str_replace("\n", "\n ", $this->dumpRecursive($value)); } } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Comment) { return $node->getReformattedText(); } else { throw new \InvalidArgumentException('Can only dump nodes and arrays.'); } return $r . "\n)"; } protected function dumpFlags($flags) { $strs = []; if ($flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC) { $strs[] = 'MODIFIER_PUBLIC'; } if ($flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED) { $strs[] = 'MODIFIER_PROTECTED'; } if ($flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE) { $strs[] = 'MODIFIER_PRIVATE'; } if ($flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT) { $strs[] = 'MODIFIER_ABSTRACT'; } if ($flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC) { $strs[] = 'MODIFIER_STATIC'; } if ($flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL) { $strs[] = 'MODIFIER_FINAL'; } if ($strs) { return \implode(' | ', $strs) . ' (' . $flags . ')'; } else { return $flags; } } protected function dumpIncludeType($type) { $map = [\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_INCLUDE => 'TYPE_INCLUDE', \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE', \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_REQUIRE => 'TYPE_REQUIRE', \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE']; if (!isset($map[$type])) { return $type; } return $map[$type] . ' (' . $type . ')'; } protected function dumpUseType($type) { $map = [\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN => 'TYPE_UNKNOWN', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL => 'TYPE_NORMAL', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION => 'TYPE_FUNCTION', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT => 'TYPE_CONSTANT']; if (!isset($map[$type])) { return $type; } return $map[$type] . ' (' . $type . ')'; } /** * Dump node position, if possible. * * @param Node $node Node for which to dump position * * @return string|null Dump of position, or null if position information not available */ protected function dumpPosition(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) { return null; } $start = $node->getStartLine(); $end = $node->getEndLine(); if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos') && null !== $this->code) { $start .= ':' . $this->toColumn($this->code, $node->getStartFilePos()); $end .= ':' . $this->toColumn($this->code, $node->getEndFilePos()); } return "[{$start} - {$end}]"; } // Copied from Error class private function toColumn($code, $pos) { if ($pos > \strlen($code)) { throw new \RuntimeException('Invalid position information'); } $lineStartPos = \strrpos($code, "\n", $pos - \strlen($code)); if (\false === $lineStartPos) { $lineStartPos = -1; } return $pos - $lineStartPos; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Stmt_Expression'; } } attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } public function getType() : string { return 'Stmt_InlineHTML'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Stmt_Throw'; } } attributes = $attributes; $this->name = $name; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['name', 'stmts']; } public function getType() : string { return 'Stmt_Namespace'; } } array(): Statements * 'elseifs' => array(): Elseif clauses * 'else' => null : Else clause * @param array $attributes Additional attributes */ public function __construct(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $cond, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $subNodes['stmts'] ?? []; $this->elseifs = $subNodes['elseifs'] ?? []; $this->else = $subNodes['else'] ?? null; } public function getSubNodeNames() : array { return ['cond', 'stmts', 'elseifs', 'else']; } public function getType() : string { return 'Stmt_If'; } } attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; } public function getType() : string { return 'Stmt_While'; } } attributes = $attributes; $this->num = $num; } public function getSubNodeNames() : array { return ['num']; } public function getType() : string { return 'Stmt_Continue'; } } attributes = $attributes; $this->exprs = $exprs; } public function getSubNodeNames() : array { return ['exprs']; } public function getType() : string { return 'Stmt_Echo'; } } attributes = $attributes; $this->types = $types; $this->var = $var; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['types', 'var', 'stmts']; } public function getType() : string { return 'Stmt_Catch'; } } attributes = $attributes; $this->flags = $flags; $this->consts = $consts; $this->attrGroups = $attrGroups; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'consts']; } /** * Whether constant is explicitly or implicitly public. * * @return bool */ public function isPublic() : bool { return ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::VISIBILITY_MODIFIER_MASK) === 0; } /** * Whether constant is protected. * * @return bool */ public function isProtected() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED); } /** * Whether constant is private. * * @return bool */ public function isPrivate() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE); } public function getType() : string { return 'Stmt_ClassConst'; } } attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames() : array { return ['vars']; } public function getType() : string { return 'Stmt_Global'; } } attributes = $attributes; $this->stmts = $stmts; $this->catches = $catches; $this->finally = $finally; } public function getSubNodeNames() : array { return ['stmts', 'catches', 'finally']; } public function getType() : string { return 'Stmt_TryCatch'; } } attributes = $attributes; $this->consts = $consts; } public function getSubNodeNames() : array { return ['consts']; } public function getType() : string { return 'Stmt_Const'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Stmt_Return'; } } attributes = $attributes; $this->type = $type; $this->name = $name; $this->alias = \is_string($alias) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($alias) : $alias; } public function getSubNodeNames() : array { return ['type', 'name', 'alias']; } /** * Get alias. If not explicitly given this is the last component of the used name. * * @return Identifier */ public function getAlias() : \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier { if (null !== $this->alias) { return $this->alias; } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($this->name->getLast()); } public function getType() : string { return 'Stmt_UseUse'; } } attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames() : array { return ['vars']; } public function getType() : string { return 'Stmt_Static'; } } attributes = $attributes; $this->var = $var; $this->default = $default; } public function getSubNodeNames() : array { return ['var', 'default']; } public function getType() : string { return 'Stmt_StaticVar'; } } attributes = $attributes; $this->type = $type; $this->uses = $uses; } public function getSubNodeNames() : array { return ['type', 'uses']; } public function getType() : string { return 'Stmt_Use'; } } 0 : Flags * 'extends' => null : Name of extended class * 'implements' => array(): Names of implemented interfaces * 'stmts' => array(): Statements * '$attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; $this->extends = $subNodes['extends'] ?? null; $this->implements = $subNodes['implements'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'name', 'extends', 'implements', 'stmts']; } /** * Whether the class is explicitly abstract. * * @return bool */ public function isAbstract() : bool { return (bool) ($this->flags & self::MODIFIER_ABSTRACT); } /** * Whether the class is final. * * @return bool */ public function isFinal() : bool { return (bool) ($this->flags & self::MODIFIER_FINAL); } /** * Whether the class is anonymous. * * @return bool */ public function isAnonymous() : bool { return null === $this->name; } /** * @internal */ public static function verifyModifier($a, $b) { if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) { throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('Multiple access type modifiers are not allowed'); } if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('Multiple abstract modifiers are not allowed'); } if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) { throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('Multiple static modifiers are not allowed'); } if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('Multiple final modifiers are not allowed'); } if ($a & 48 && $b & 48) { throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('Cannot use the final modifier on an abstract class member'); } } public function getType() : string { return 'Stmt_Class'; } } attributes = $attributes; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['stmts']; } public function getType() : string { return 'Stmt_Finally'; } } array(): Name of extended interfaces * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; $this->extends = $subNodes['extends'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'name', 'extends', 'stmts']; } public function getType() : string { return 'Stmt_Interface'; } } attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames() : array { return ['vars']; } public function getType() : string { return 'Stmt_Unset'; } } value pair node. * * @param string|Node\Identifier $key Key * @param Node\Expr $value Value * @param array $attributes Additional attributes */ public function __construct($key, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $value, array $attributes = []) { $this->attributes = $attributes; $this->key = \is_string($key) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($key) : $key; $this->value = $value; } public function getSubNodeNames() : array { return ['key', 'value']; } public function getType() : string { return 'Stmt_DeclareDeclare'; } } null : Variable to assign key to * 'byRef' => false : Whether to assign value by reference * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $valueVar, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; $this->keyVar = $subNodes['keyVar'] ?? null; $this->byRef = $subNodes['byRef'] ?? \false; $this->valueVar = $valueVar; $this->stmts = $subNodes['stmts'] ?? []; } public function getSubNodeNames() : array { return ['expr', 'keyVar', 'byRef', 'valueVar', 'stmts']; } public function getType() : string { return 'Stmt_Foreach'; } } attributes = $attributes; $this->declares = $declares; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['declares', 'stmts']; } public function getType() : string { return 'Stmt_Declare'; } } attributes = $attributes; $this->cond = $cond; $this->cases = $cases; } public function getSubNodeNames() : array { return ['cond', 'cases']; } public function getType() : string { return 'Stmt_Switch'; } } array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'name', 'stmts']; } public function getType() : string { return 'Stmt_Trait'; } } attributes = $attributes; $this->flags = $flags; $this->props = $props; $this->type = \is_string($type) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($type) : $type; $this->attrGroups = $attrGroups; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'props']; } /** * Whether the property is explicitly or implicitly public. * * @return bool */ public function isPublic() : bool { return ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::VISIBILITY_MODIFIER_MASK) === 0; } /** * Whether the property is protected. * * @return bool */ public function isProtected() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED); } /** * Whether the property is private. * * @return bool */ public function isPrivate() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE); } /** * Whether the property is static. * * @return bool */ public function isStatic() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC); } public function getType() : string { return 'Stmt_Property'; } } attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; } public function getType() : string { return 'Stmt_Case'; } } attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['stmts', 'cond']; } public function getType() : string { return 'Stmt_Do'; } } attributes = $attributes; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; } public function getSubNodeNames() : array { return ['name']; } public function getType() : string { return 'Stmt_Label'; } } attributes = $attributes; $this->type = $type; $this->prefix = $prefix; $this->uses = $uses; } public function getSubNodeNames() : array { return ['type', 'prefix', 'uses']; } public function getType() : string { return 'Stmt_GroupUse'; } } attributes = $attributes; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier($name) : $name; $this->default = $default; } public function getSubNodeNames() : array { return ['name', 'default']; } public function getType() : string { return 'Stmt_PropertyProperty'; } } attributes = $attributes; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['stmts']; } public function getType() : string { return 'Stmt_Else'; } } array(): Init expressions * 'cond' => array(): Loop conditions * 'loop' => array(): Loop expressions * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct(array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->init = $subNodes['init'] ?? []; $this->cond = $subNodes['cond'] ?? []; $this->loop = $subNodes['loop'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; } public function getSubNodeNames() : array { return ['init', 'cond', 'loop', 'stmts']; } public function getType() : string { return 'Stmt_For'; } } attributes = $attributes; $this->remaining = $remaining; } public function getSubNodeNames() : array { return ['remaining']; } public function getType() : string { return 'Stmt_HaltCompiler'; } } stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { $traitUses[] = $stmt; } } return $traitUses; } /** * @return ClassConst[] */ public function getConstants() : array { $constants = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst) { $constants[] = $stmt; } } return $constants; } /** * @return Property[] */ public function getProperties() : array { $properties = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { $properties[] = $stmt; } } return $properties; } /** * Gets property with the given name defined directly in this class/interface/trait. * * @param string $name Name of the property * * @return Property|null Property node or null if the property does not exist */ public function getProperty(string $name) { foreach ($this->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { foreach ($stmt->props as $prop) { if ($prop instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\PropertyProperty && $name === $prop->name->toString()) { return $stmt; } } } } return null; } /** * Gets all methods defined directly in this class/interface/trait * * @return ClassMethod[] */ public function getMethods() : array { $methods = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $methods[] = $stmt; } } return $methods; } /** * Gets method with the given name defined directly in this class/interface/trait. * * @param string $name Name of the method (compared case-insensitively) * * @return ClassMethod|null Method node or null if the method does not exist */ public function getMethod(string $name) { $lowerName = \strtolower($name); foreach ($this->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && $lowerName === $stmt->name->toLowerString()) { return $stmt; } } return null; } } \true, '__destruct' => \true, '__call' => \true, '__callstatic' => \true, '__get' => \true, '__set' => \true, '__isset' => \true, '__unset' => \true, '__sleep' => \true, '__wakeup' => \true, '__tostring' => \true, '__set_state' => \true, '__clone' => \true, '__invoke' => \true, '__debuginfo' => \true]; /** * Constructs a class method node. * * @param string|Node\Identifier $name Name * @param array $subNodes Array of the following optional subnodes: * 'flags => MODIFIER_PUBLIC: Flags * 'byRef' => false : Whether to return by reference * 'params' => array() : Parameters * 'returnType' => null : Return type * 'stmts' => array() : Statements * 'attrGroups' => array() : PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; $this->byRef = $subNodes['byRef'] ?? \false; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; $this->params = $subNodes['params'] ?? []; $returnType = $subNodes['returnType'] ?? null; $this->returnType = \is_string($returnType) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($returnType) : $returnType; $this->stmts = \array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'returnType', 'stmts']; } public function returnsByRef() : bool { return $this->byRef; } public function getParams() : array { return $this->params; } public function getReturnType() { return $this->returnType; } public function getStmts() { return $this->stmts; } public function getAttrGroups() : array { return $this->attrGroups; } /** * Whether the method is explicitly or implicitly public. * * @return bool */ public function isPublic() : bool { return ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::VISIBILITY_MODIFIER_MASK) === 0; } /** * Whether the method is protected. * * @return bool */ public function isProtected() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED); } /** * Whether the method is private. * * @return bool */ public function isPrivate() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE); } /** * Whether the method is abstract. * * @return bool */ public function isAbstract() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT); } /** * Whether the method is final. * * @return bool */ public function isFinal() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL); } /** * Whether the method is static. * * @return bool */ public function isStatic() : bool { return (bool) ($this->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC); } /** * Whether the method is magic. * * @return bool */ public function isMagic() : bool { return isset(self::$magicNames[$this->name->toLowerString()]); } public function getType() : string { return 'Stmt_ClassMethod'; } } attributes = $attributes; $this->num = $num; } public function getSubNodeNames() : array { return ['num']; } public function getType() : string { return 'Stmt_Break'; } } false : Whether to return by reference * 'params' => array(): Parameters * 'returnType' => null : Return type * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->byRef = $subNodes['byRef'] ?? \false; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; $this->params = $subNodes['params'] ?? []; $returnType = $subNodes['returnType'] ?? null; $this->returnType = \is_string($returnType) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($returnType) : $returnType; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } public function returnsByRef() : bool { return $this->byRef; } public function getParams() : array { return $this->params; } public function getReturnType() { return $this->returnType; } public function getAttrGroups() : array { return $this->attrGroups; } /** @return Node\Stmt[] */ public function getStmts() : array { return $this->stmts; } public function getType() : string { return 'Stmt_Function'; } } attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() : array { return ['cond', 'stmts']; } public function getType() : string { return 'Stmt_ElseIf'; } } attributes = $attributes; $this->traits = $traits; $this->adaptations = $adaptations; } public function getSubNodeNames() : array { return ['traits', 'adaptations']; } public function getType() : string { return 'Stmt_TraitUse'; } } attributes = $attributes; $this->trait = $trait; $this->method = \is_string($method) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($method) : $method; $this->newModifier = $newModifier; $this->newName = \is_string($newName) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($newName) : $newName; } public function getSubNodeNames() : array { return ['trait', 'method', 'newModifier', 'newName']; } public function getType() : string { return 'Stmt_TraitUseAdaptation_Alias'; } } attributes = $attributes; $this->trait = $trait; $this->method = \is_string($method) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($method) : $method; $this->insteadof = $insteadof; } public function getSubNodeNames() : array { return ['trait', 'method', 'insteadof']; } public function getType() : string { return 'Stmt_TraitUseAdaptation_Precedence'; } } attributes = $attributes; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; } public function getSubNodeNames() : array { return ['name']; } public function getType() : string { return 'Stmt_Goto'; } } conds = $conds; $this->body = $body; $this->attributes = $attributes; } public function getSubNodeNames() : array { return ['conds', 'body']; } public function getType() : string { return 'MatchArm'; } } attributes = $attributes; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; $this->value = $value; } public function getSubNodeNames() : array { return ['name', 'value']; } public function getType() : string { return 'Const'; } } toString(); } public function getType() : string { return 'Name_Relative'; } } toString(); } public function getType() : string { return 'Name_FullyQualified'; } } attributes = $attributes; $this->name = $name; } public function getSubNodeNames() : array { return ['name']; } public function getType() : string { return 'Expr_ConstFetch'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Throw'; } } attributes = $attributes; $this->var = $var; } public function getSubNodeNames() : array { return ['var']; } public function getType() : string { return 'Expr_PostDec'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Print'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Empty'; } } attributes = $attributes; $this->name = $name; $this->args = $args; } public function getSubNodeNames() : array { return ['name', 'args']; } public function getType() : string { return 'Expr_FuncCall'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_YieldFrom'; } } attributes = $attributes; $this->var = $var; $this->expr = $expr; } public function getSubNodeNames() : array { return ['var', 'expr']; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Eval'; } } attributes = $attributes; $this->var = $var; $this->dim = $dim; } public function getSubNodeNames() : array { return ['var', 'dim']; } public function getType() : string { return 'Expr_ArrayDimFetch'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Exit'; } } attributes = $attributes; $this->class = $class; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; $this->args = $args; } public function getSubNodeNames() : array { return ['class', 'name', 'args']; } public function getType() : string { return 'Expr_StaticCall'; } } '; } public function getType() : string { return 'Expr_BinaryOp_Greater'; } } ='; } public function getType() : string { return 'Expr_BinaryOp_GreaterOrEqual'; } } '; } public function getType() : string { return 'Expr_BinaryOp_Spaceship'; } } >'; } public function getType() : string { return 'Expr_BinaryOp_ShiftRight'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } } attributes = $attributes; $this->class = $class; $this->args = $args; } public function getSubNodeNames() : array { return ['class', 'args']; } public function getType() : string { return 'Expr_New'; } } attributes = $attributes; $this->var = $var; $this->expr = $expr; } public function getSubNodeNames() : array { return ['var', 'expr']; } public function getType() : string { return 'Expr_AssignRef'; } } attributes = $attributes; $this->parts = $parts; } public function getSubNodeNames() : array { return ['parts']; } public function getType() : string { return 'Expr_ShellExec'; } } attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; } public function getSubNodeNames() : array { return ['var', 'name']; } public function getType() : string { return 'Expr_PropertyFetch'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_ErrorSuppress'; } } attributes = $attributes; $this->expr = $expr; $this->type = $type; } public function getSubNodeNames() : array { return ['expr', 'type']; } public function getType() : string { return 'Expr_Include'; } } attributes = $attributes; $this->key = $key; $this->value = $value; } public function getSubNodeNames() : array { return ['key', 'value']; } public function getType() : string { return 'Expr_Yield'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_BitwiseNot'; } } attributes = $attributes; $this->cond = $cond; $this->arms = $arms; } public function getSubNodeNames() : array { return ['cond', 'arms']; } public function getType() : string { return 'Expr_Match'; } } false : Whether the closure is static * 'byRef' => false : Whether to return by reference * 'params' => array(): Parameters * 'uses' => array(): use()s * 'returnType' => null : Return type * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attributes groups * @param array $attributes Additional attributes */ public function __construct(array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->static = $subNodes['static'] ?? \false; $this->byRef = $subNodes['byRef'] ?? \false; $this->params = $subNodes['params'] ?? []; $this->uses = $subNodes['uses'] ?? []; $returnType = $subNodes['returnType'] ?? null; $this->returnType = \is_string($returnType) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($returnType) : $returnType; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'static', 'byRef', 'params', 'uses', 'returnType', 'stmts']; } public function returnsByRef() : bool { return $this->byRef; } public function getParams() : array { return $this->params; } public function getReturnType() { return $this->returnType; } /** @return Node\Stmt[] */ public function getStmts() : array { return $this->stmts; } public function getAttrGroups() : array { return $this->attrGroups; } public function getType() : string { return 'Expr_Closure'; } } attributes = $attributes; $this->var = $var; $this->byRef = $byRef; } public function getSubNodeNames() : array { return ['var', 'byRef']; } public function getType() : string { return 'Expr_ClosureUse'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_BooleanNot'; } } attributes = $attributes; $this->expr = $expr; $this->class = $class; } public function getSubNodeNames() : array { return ['expr', 'class']; } public function getType() : string { return 'Expr_Instanceof'; } } attributes = $attributes; $this->var = $var; $this->expr = $expr; } public function getSubNodeNames() : array { return ['var', 'expr']; } public function getType() : string { return 'Expr_Assign'; } } attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames() : array { return ['vars']; } public function getType() : string { return 'Expr_Isset'; } } attributes = $attributes; $this->items = $items; } public function getSubNodeNames() : array { return ['items']; } public function getType() : string { return 'Expr_List'; } } attributes = $attributes; $this->class = $class; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; } public function getSubNodeNames() : array { return ['class', 'name']; } public function getType() : string { return 'Expr_ClassConstFetch'; } } attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; $this->args = $args; } public function getSubNodeNames() : array { return ['var', 'name', 'args']; } public function getType() : string { return 'Expr_NullsafeMethodCall'; } } false : Whether the closure is static * 'byRef' => false : Whether to return by reference * 'params' => array() : Parameters * 'returnType' => null : Return type * 'expr' => Expr : Expression body * 'attrGroups' => array() : PHP attribute groups * @param array $attributes Additional attributes */ public function __construct(array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->static = $subNodes['static'] ?? \false; $this->byRef = $subNodes['byRef'] ?? \false; $this->params = $subNodes['params'] ?? []; $returnType = $subNodes['returnType'] ?? null; $this->returnType = \is_string($returnType) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($returnType) : $returnType; $this->expr = $subNodes['expr'] ?? null; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames() : array { return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr']; } public function returnsByRef() : bool { return $this->byRef; } public function getParams() : array { return $this->params; } public function getReturnType() { return $this->returnType; } public function getAttrGroups() : array { return $this->attrGroups; } /** * @return Node\Stmt\Return_[] */ public function getStmts() : array { return [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_($this->expr)]; } public function getType() : string { return 'Expr_ArrowFunction'; } } attributes = $attributes; $this->class = $class; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier($name) : $name; } public function getSubNodeNames() : array { return ['class', 'name']; } public function getType() : string { return 'Expr_StaticPropertyFetch'; } } attributes = $attributes; $this->var = $var; } public function getSubNodeNames() : array { return ['var']; } public function getType() : string { return 'Expr_PostInc'; } } attributes = $attributes; $this->var = $var; } public function getSubNodeNames() : array { return ['var']; } public function getType() : string { return 'Expr_PreDec'; } } attributes = $attributes; $this->var = $var; } public function getSubNodeNames() : array { return ['var']; } public function getType() : string { return 'Expr_PreInc'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_UnaryPlus'; } } attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; $this->args = $args; } public function getSubNodeNames() : array { return ['var', 'name', 'args']; } public function getType() : string { return 'Expr_MethodCall'; } } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_Clone'; } } attributes = $attributes; } public function getSubNodeNames() : array { return []; } public function getType() : string { return 'Expr_Error'; } } attributes = $attributes; $this->key = $key; $this->value = $value; $this->byRef = $byRef; $this->unpack = $unpack; } public function getSubNodeNames() : array { return ['key', 'value', 'byRef', 'unpack']; } public function getType() : string { return 'Expr_ArrayItem'; } } attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name) : $name; } public function getSubNodeNames() : array { return ['var', 'name']; } public function getType() : string { return 'Expr_NullsafePropertyFetch'; } } attributes = $attributes; $this->items = $items; } public function getSubNodeNames() : array { return ['items']; } public function getType() : string { return 'Expr_Array'; } } attributes = $attributes; $this->cond = $cond; $this->if = $if; $this->else = $else; } public function getSubNodeNames() : array { return ['cond', 'if', 'else']; } public function getType() : string { return 'Expr_Ternary'; } } attributes = $attributes; $this->left = $left; $this->right = $right; } public function getSubNodeNames() : array { return ['left', 'right']; } /** * Get the operator sigil for this binary operation. * * In the case there are multiple possible sigils for an operator, this method does not * necessarily return the one used in the parsed code. * * @return string */ public abstract function getOperatorSigil() : string; } attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames() : array { return ['expr']; } public function getType() : string { return 'Expr_UnaryMinus'; } } attributes = $attributes; $this->name = $name; } public function getSubNodeNames() : array { return ['name']; } public function getType() : string { return 'Expr_Variable'; } } attributes = $attributes; $this->type = \is_string($type) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($type) : $type; $this->byRef = $byRef; $this->variadic = $variadic; $this->var = $var; $this->default = $default; $this->flags = $flags; $this->attrGroups = $attrGroups; } public function getSubNodeNames() : array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; } public function getType() : string { return 'Param'; } } \true, 'parent' => \true, 'static' => \true]; /** * Constructs an identifier node. * * @param string $name Identifier as string * @param array $attributes Additional attributes */ public function __construct(string $name, array $attributes = []) { $this->attributes = $attributes; $this->name = $name; } public function getSubNodeNames() : array { return ['name']; } /** * Get identifier as string. * * @return string Identifier as string. */ public function toString() : string { return $this->name; } /** * Get lowercased identifier as string. * * @return string Lowercased identifier as string */ public function toLowerString() : string { return \strtolower($this->name); } /** * Checks whether the identifier is a special class name (self, parent or static). * * @return bool Whether identifier is a special class name */ public function isSpecialClassName() : bool { return isset(self::$specialClassNames[\strtolower($this->name)]); } /** * Get identifier as string. * * @return string Identifier as string */ public function __toString() : string { return $this->name; } public function getType() : string { return 'Identifier'; } } attributes = $attributes; $this->attrs = $attrs; } public function getSubNodeNames() : array { return ['attrs']; } public function getType() : string { return 'AttributeGroup'; } } attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } public function getType() : string { return 'Scalar_EncapsedStringPart'; } } attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } /** * @internal * * Parses a DNUMBER token like PHP would. * * @param string $str A string number * * @return float The parsed number */ public static function parse(string $str) : float { $str = \str_replace('_', '', $str); // if string contains any of .eE just cast it to float if (\false !== \strpbrk($str, '.eE')) { return (float) $str; } // otherwise it's an integer notation that overflowed into a float // if it starts with 0 it's one of the special integer notations if ('0' === $str[0]) { // hex if ('x' === $str[1] || 'X' === $str[1]) { return \hexdec($str); } // bin if ('b' === $str[1] || 'B' === $str[1]) { return \bindec($str); } // oct // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit (8 or 9) // so that only the digits before that are used return \octdec(\substr($str, 0, \strcspn($str, '89'))); } // dec return (float) $str; } public function getType() : string { return 'Scalar_DNumber'; } } attributes = $attributes; } public function getSubNodeNames() : array { return []; } /** * Get name of magic constant. * * @return string Name of magic constant */ public abstract function getName() : string; } attributes = $attributes; $this->parts = $parts; } public function getSubNodeNames() : array { return ['parts']; } public function getType() : string { return 'Scalar_Encapsed'; } } attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } /** * Constructs an LNumber node from a string number literal. * * @param string $str String number literal (decimal, octal, hex or binary) * @param array $attributes Additional attributes * @param bool $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5) * * @return LNumber The constructed LNumber, including kind attribute */ public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = \false) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber { $str = \str_replace('_', '', $str); if ('0' !== $str[0] || '0' === $str) { $attributes['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::KIND_DEC; return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber((int) $str, $attributes); } if ('x' === $str[1] || 'X' === $str[1]) { $attributes['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::KIND_HEX; return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(\hexdec($str), $attributes); } if ('b' === $str[1] || 'B' === $str[1]) { $attributes['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::KIND_BIN; return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(\bindec($str), $attributes); } if (!$allowInvalidOctal && \strpbrk($str, '89')) { throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('Invalid numeric literal', $attributes); } // use intval instead of octdec to get proper cutting behavior with malformed numbers $attributes['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::KIND_OCT; return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(\intval($str, 8), $attributes); } public function getType() : string { return 'Scalar_LNumber'; } } '\\', '$' => '$', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\33"]; /** * Constructs a string scalar node. * * @param string $value Value of the string * @param array $attributes Additional attributes */ public function __construct(string $value, array $attributes = []) { $this->attributes = $attributes; $this->value = $value; } public function getSubNodeNames() : array { return ['value']; } /** * @internal * * Parses a string token. * * @param string $str String token content * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes * * @return string The parsed string */ public static function parse(string $str, bool $parseUnicodeEscape = \true) : string { $bLength = 0; if ('b' === $str[0] || 'B' === $str[0]) { $bLength = 1; } if ('\'' === $str[$bLength]) { return \str_replace(['\\\\', '\\\''], ['\\', '\''], \substr($str, $bLength + 1, -1)); } else { return self::parseEscapeSequences(\substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape); } } /** * @internal * * Parses escape sequences in strings (all string types apart from single quoted). * * @param string $str String without quotes * @param null|string $quote Quote type * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes * * @return string String with escape sequences parsed */ public static function parseEscapeSequences(string $str, $quote, bool $parseUnicodeEscape = \true) : string { if (null !== $quote) { $str = \str_replace('\\' . $quote, $quote, $str); } $extra = ''; if ($parseUnicodeEscape) { $extra = '|u\\{([0-9a-fA-F]+)\\}'; } return \preg_replace_callback('~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~', function ($matches) { $str = $matches[1]; if (isset(self::$replacements[$str])) { return self::$replacements[$str]; } elseif ('x' === $str[0] || 'X' === $str[0]) { return \chr(\hexdec(\substr($str, 1))); } elseif ('u' === $str[0]) { return self::codePointToUtf8(\hexdec($matches[2])); } else { return \chr(\octdec($str)); } }, $str); } /** * Converts a Unicode code point to its UTF-8 encoded representation. * * @param int $num Code point * * @return string UTF-8 representation of code point */ private static function codePointToUtf8(int $num) : string { if ($num <= 0x7f) { return \chr($num); } if ($num <= 0x7ff) { return \chr(($num >> 6) + 0xc0) . \chr(($num & 0x3f) + 0x80); } if ($num <= 0xffff) { return \chr(($num >> 12) + 0xe0) . \chr(($num >> 6 & 0x3f) + 0x80) . \chr(($num & 0x3f) + 0x80); } if ($num <= 0x1fffff) { return \chr(($num >> 18) + 0xf0) . \chr(($num >> 12 & 0x3f) + 0x80) . \chr(($num >> 6 & 0x3f) + 0x80) . \chr(($num & 0x3f) + 0x80); } throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large'); } public function getType() : string { return 'Scalar_String'; } } attributes = $attributes; $this->types = $types; } public function getSubNodeNames() : array { return ['types']; } public function getType() : string { return 'UnionType'; } } attributes = $attributes; $this->type = \is_string($type) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($type) : $type; } public function getSubNodeNames() : array { return ['type']; } public function getType() : string { return 'NullableType'; } } attributes = $attributes; $this->name = $name; $this->value = $value; $this->byRef = $byRef; $this->unpack = $unpack; } public function getSubNodeNames() : array { return ['name', 'value', 'byRef', 'unpack']; } public function getType() : string { return 'Arg'; } } \true, 'parent' => \true, 'static' => \true]; /** * Constructs a name node. * * @param string|string[]|self $name Name as string, part array or Name instance (copy ctor) * @param array $attributes Additional attributes */ public function __construct($name, array $attributes = []) { $this->attributes = $attributes; $this->parts = self::prepareName($name); } public function getSubNodeNames() : array { return ['parts']; } /** * Gets the first part of the name, i.e. everything before the first namespace separator. * * @return string First part of the name */ public function getFirst() : string { return $this->parts[0]; } /** * Gets the last part of the name, i.e. everything after the last namespace separator. * * @return string Last part of the name */ public function getLast() : string { return $this->parts[\count($this->parts) - 1]; } /** * Checks whether the name is unqualified. (E.g. Name) * * @return bool Whether the name is unqualified */ public function isUnqualified() : bool { return 1 === \count($this->parts); } /** * Checks whether the name is qualified. (E.g. Name\Name) * * @return bool Whether the name is qualified */ public function isQualified() : bool { return 1 < \count($this->parts); } /** * Checks whether the name is fully qualified. (E.g. \Name) * * @return bool Whether the name is fully qualified */ public function isFullyQualified() : bool { return \false; } /** * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) * * @return bool Whether the name is relative */ public function isRelative() : bool { return \false; } /** * Returns a string representation of the name itself, without taking the name type into * account (e.g., not including a leading backslash for fully qualified names). * * @return string String representation */ public function toString() : string { return \implode('\\', $this->parts); } /** * Returns a string representation of the name as it would occur in code (e.g., including * leading backslash for fully qualified names. * * @return string String representation */ public function toCodeString() : string { return $this->toString(); } /** * Returns lowercased string representation of the name, without taking the name type into * account (e.g., no leading backslash for fully qualified names). * * @return string Lowercased string representation */ public function toLowerString() : string { return \strtolower(\implode('\\', $this->parts)); } /** * Checks whether the identifier is a special class name (self, parent or static). * * @return bool Whether identifier is a special class name */ public function isSpecialClassName() : bool { return \count($this->parts) === 1 && isset(self::$specialClassNames[\strtolower($this->parts[0])]); } /** * Returns a string representation of the name by imploding the namespace parts with the * namespace separator. * * @return string String representation */ public function __toString() : string { return \implode('\\', $this->parts); } /** * Gets a slice of a name (similar to array_slice). * * This method returns a new instance of the same type as the original and with the same * attributes. * * If the slice is empty, null is returned. The null value will be correctly handled in * concatenations using concat(). * * Offset and length have the same meaning as in array_slice(). * * @param int $offset Offset to start the slice at (may be negative) * @param int|null $length Length of the slice (may be negative) * * @return static|null Sliced name */ public function slice(int $offset, int $length = null) { $numParts = \count($this->parts); $realOffset = $offset < 0 ? $offset + $numParts : $offset; if ($realOffset < 0 || $realOffset > $numParts) { throw new \OutOfBoundsException(\sprintf('Offset %d is out of bounds', $offset)); } if (null === $length) { $realLength = $numParts - $realOffset; } else { $realLength = $length < 0 ? $length + $numParts - $realOffset : $length; if ($realLength < 0 || $realLength > $numParts) { throw new \OutOfBoundsException(\sprintf('Length %d is out of bounds', $length)); } } if ($realLength === 0) { // Empty slice is represented as null return null; } return new static(\array_slice($this->parts, $realOffset, $realLength), $this->attributes); } /** * Concatenate two names, yielding a new Name instance. * * The type of the generated instance depends on which class this method is called on, for * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance. * * If one of the arguments is null, a new instance of the other name will be returned. If both * arguments are null, null will be returned. As such, writing * Name::concat($namespace, $shortName) * where $namespace is a Name node or null will work as expected. * * @param string|string[]|self|null $name1 The first name * @param string|string[]|self|null $name2 The second name * @param array $attributes Attributes to assign to concatenated name * * @return static|null Concatenated name */ public static function concat($name1, $name2, array $attributes = []) { if (null === $name1 && null === $name2) { return null; } elseif (null === $name1) { return new static(self::prepareName($name2), $attributes); } elseif (null === $name2) { return new static(self::prepareName($name1), $attributes); } else { return new static(\array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes); } } /** * Prepares a (string, array or Name node) name for use in name changing methods by converting * it to an array. * * @param string|string[]|self $name Name to prepare * * @return string[] Prepared name */ private static function prepareName($name) : array { if (\is_string($name)) { if ('' === $name) { throw new \InvalidArgumentException('Name cannot be empty'); } return \explode('\\', $name); } elseif (\is_array($name)) { if (empty($name)) { throw new \InvalidArgumentException('Name cannot be empty'); } return $name; } elseif ($name instanceof self) { return $name->parts; } throw new \InvalidArgumentException('Expected string, array of parts or Name instance'); } public function getType() : string { return 'Name'; } } attributes = $attributes; $this->name = $name; $this->args = $args; } public function getSubNodeNames() : array { return ['name', 'args']; } public function getType() : string { return 'Attribute'; } } fallbackEvaluator = $fallbackEvaluator ?? function (\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr) { throw new \_HumbugBoxd02f763d3c56\PhpParser\ConstExprEvaluationException("Expression of type {$expr->getType()} cannot be evaluated"); }; } /** * Silently evaluates a constant expression into a PHP value. * * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException. * The original source of the exception is available through getPrevious(). * * If some part of the expression cannot be evaluated, the fallback evaluator passed to the * constructor will be invoked. By default, if no fallback is provided, an exception of type * ConstExprEvaluationException is thrown. * * See class doc comment for caveats and limitations. * * @param Expr $expr Constant expression to evaluate * @return mixed Result of evaluation * * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred */ public function evaluateSilently(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr) { \set_error_handler(function ($num, $str, $file, $line) { throw new \ErrorException($str, 0, $num, $file, $line); }); try { return $this->evaluate($expr); } catch (\Throwable $e) { if (!$e instanceof \_HumbugBoxd02f763d3c56\PhpParser\ConstExprEvaluationException) { $e = new \_HumbugBoxd02f763d3c56\PhpParser\ConstExprEvaluationException("An error occurred during constant expression evaluation", 0, $e); } throw $e; } finally { \restore_error_handler(); } } /** * Directly evaluates a constant expression into a PHP value. * * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these * into a ConstExprEvaluationException. * * If some part of the expression cannot be evaluated, the fallback evaluator passed to the * constructor will be invoked. By default, if no fallback is provided, an exception of type * ConstExprEvaluationException is thrown. * * See class doc comment for caveats and limitations. * * @param Expr $expr Constant expression to evaluate * @return mixed Result of evaluation * * @throws ConstExprEvaluationException if the expression cannot be evaluated */ public function evaluateDirectly(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr) { return $this->evaluate($expr); } private function evaluate(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr) { if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || $expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber || $expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { return $expr->value; } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_) { return $this->evaluateArray($expr); } // Unary operators if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus) { return +$this->evaluate($expr->expr); } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus) { return -$this->evaluate($expr->expr); } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot) { return !$this->evaluate($expr->expr); } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BitwiseNot) { return ~$this->evaluate($expr->expr); } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp) { return $this->evaluateBinaryOp($expr); } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary) { return $this->evaluateTernary($expr); } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch && null !== $expr->dim) { return $this->evaluate($expr->var)[$this->evaluate($expr->dim)]; } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { return $this->evaluateConstFetch($expr); } return ($this->fallbackEvaluator)($expr); } private function evaluateArray(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ $expr) { $array = []; foreach ($expr->items as $item) { if (null !== $item->key) { $array[$this->evaluate($item->key)] = $this->evaluate($item->value); } else { $array[] = $this->evaluate($item->value); } } return $array; } private function evaluateTernary(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary $expr) { if (null === $expr->if) { return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else); } return $this->evaluate($expr->cond) ? $this->evaluate($expr->if) : $this->evaluate($expr->else); } private function evaluateBinaryOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $expr) { if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce && $expr->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { // This needs to be special cased to respect BP_VAR_IS fetch semantics return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)] ?? $this->evaluate($expr->right); } // The evaluate() calls are repeated in each branch, because some of the operators are // short-circuiting and evaluating the RHS in advance may be illegal in that case $l = $expr->left; $r = $expr->right; switch ($expr->getOperatorSigil()) { case '&': return $this->evaluate($l) & $this->evaluate($r); case '|': return $this->evaluate($l) | $this->evaluate($r); case '^': return $this->evaluate($l) ^ $this->evaluate($r); case '&&': return $this->evaluate($l) && $this->evaluate($r); case '||': return $this->evaluate($l) || $this->evaluate($r); case '??': return $this->evaluate($l) ?? $this->evaluate($r); case '.': return $this->evaluate($l) . $this->evaluate($r); case '/': return $this->evaluate($l) / $this->evaluate($r); case '==': return $this->evaluate($l) == $this->evaluate($r); case '>': return $this->evaluate($l) > $this->evaluate($r); case '>=': return $this->evaluate($l) >= $this->evaluate($r); case '===': return $this->evaluate($l) === $this->evaluate($r); case 'and': return $this->evaluate($l) and $this->evaluate($r); case 'or': return $this->evaluate($l) or $this->evaluate($r); case 'xor': return $this->evaluate($l) xor $this->evaluate($r); case '-': return $this->evaluate($l) - $this->evaluate($r); case '%': return $this->evaluate($l) % $this->evaluate($r); case '*': return $this->evaluate($l) * $this->evaluate($r); case '!=': return $this->evaluate($l) != $this->evaluate($r); case '!==': return $this->evaluate($l) !== $this->evaluate($r); case '+': return $this->evaluate($l) + $this->evaluate($r); case '**': return $this->evaluate($l) ** $this->evaluate($r); case '<<': return $this->evaluate($l) << $this->evaluate($r); case '>>': return $this->evaluate($l) >> $this->evaluate($r); case '<': return $this->evaluate($l) < $this->evaluate($r); case '<=': return $this->evaluate($l) <= $this->evaluate($r); case '<=>': return $this->evaluate($l) <=> $this->evaluate($r); } throw new \Exception('Should not happen'); } private function evaluateConstFetch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch $expr) { $name = $expr->name->toLowerString(); switch ($name) { case 'null': return null; case 'false': return \false; case 'true': return \true; } return ($this->fallbackEvaluator)($expr); } } decodeRecursive($value); } private function decodeRecursive($value) { if (\is_array($value)) { if (isset($value['nodeType'])) { if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') { return $this->decodeComment($value); } return $this->decodeNode($value); } return $this->decodeArray($value); } return $value; } private function decodeArray(array $array) : array { $decodedArray = []; foreach ($array as $key => $value) { $decodedArray[$key] = $this->decodeRecursive($value); } return $decodedArray; } private function decodeNode(array $value) : \_HumbugBoxd02f763d3c56\PhpParser\Node { $nodeType = $value['nodeType']; if (!\is_string($nodeType)) { throw new \RuntimeException('Node type must be a string'); } $reflectionClass = $this->reflectionClassFromNodeType($nodeType); /** @var Node $node */ $node = $reflectionClass->newInstanceWithoutConstructor(); if (isset($value['attributes'])) { if (!\is_array($value['attributes'])) { throw new \RuntimeException('Attributes must be an array'); } $node->setAttributes($this->decodeArray($value['attributes'])); } foreach ($value as $name => $subNode) { if ($name === 'nodeType' || $name === 'attributes') { continue; } $node->{$name} = $this->decodeRecursive($subNode); } return $node; } private function decodeComment(array $value) : \_HumbugBoxd02f763d3c56\PhpParser\Comment { $className = $value['nodeType'] === 'Comment' ? \_HumbugBoxd02f763d3c56\PhpParser\Comment::class : \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc::class; if (!isset($value['text'])) { throw new \RuntimeException('Comment must have text'); } return new $className($value['text'], $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1, $value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1); } private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass { if (!isset($this->reflectionClassCache[$nodeType])) { $className = $this->classNameFromNodeType($nodeType); $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className); } return $this->reflectionClassCache[$nodeType]; } private function classNameFromNodeType(string $nodeType) : string { $className = 'PhpParser\\Node\\' . \strtr($nodeType, '_', '\\'); if (\class_exists($className)) { return $className; } $className .= '_'; if (\class_exists($className)) { return $className; } throw new \RuntimeException("Unknown node type \"{$nodeType}\""); } } pAttrGroups($node->attrGroups, \true) . $this->pModifiers($node->flags) . ($node->type ? $this->p($node->type) . ' ' : '') . ($node->byRef ? '&' : '') . ($node->variadic ? '...' : '') . $this->p($node->var) . ($node->default ? ' = ' . $this->p($node->default) : ''); } protected function pArg(\_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $node) { return ($node->name ? $node->name->toString() . ': ' : '') . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value); } protected function pConst(\_HumbugBoxd02f763d3c56\PhpParser\Node\Const_ $node) { return $node->name . ' = ' . $this->p($node->value); } protected function pNullableType(\_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType $node) { return '?' . $this->p($node->type); } protected function pUnionType(\_HumbugBoxd02f763d3c56\PhpParser\Node\UnionType $node) { return $this->pImplode($node->types, '|'); } protected function pIdentifier(\_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier $node) { return $node->name; } protected function pVarLikeIdentifier(\_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier $node) { return '$' . $node->name; } protected function pAttribute(\_HumbugBoxd02f763d3c56\PhpParser\Node\Attribute $node) { return $this->p($node->name) . ($node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : ''); } protected function pAttributeGroup(\_HumbugBoxd02f763d3c56\PhpParser\Node\AttributeGroup $node) { return '#[' . $this->pCommaSeparated($node->attrs) . ']'; } // Names protected function pName(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $node) { return \implode('\\', $node->parts); } protected function pName_FullyQualified(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified $node) { return '\\' . \implode('\\', $node->parts); } protected function pName_Relative(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name\Relative $node) { return 'namespace\\' . \implode('\\', $node->parts); } // Magic Constants protected function pScalar_MagicConst_Class(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Class_ $node) { return '__CLASS__'; } protected function pScalar_MagicConst_Dir(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Dir $node) { return '__DIR__'; } protected function pScalar_MagicConst_File(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\File $node) { return '__FILE__'; } protected function pScalar_MagicConst_Function(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Function_ $node) { return '__FUNCTION__'; } protected function pScalar_MagicConst_Line(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Line $node) { return '__LINE__'; } protected function pScalar_MagicConst_Method(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Method $node) { return '__METHOD__'; } protected function pScalar_MagicConst_Namespace(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Namespace_ $node) { return '__NAMESPACE__'; } protected function pScalar_MagicConst_Trait(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Trait_ $node) { return '__TRAIT__'; } // Scalars protected function pScalar_String(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ $node) { $kind = $node->getAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_SINGLE_QUOTED); switch ($kind) { case \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_NOWDOC: $label = $node->getAttribute('docLabel'); if ($label && !$this->containsEndLabel($node->value, $label)) { if ($node->value === '') { return "<<<'{$label}'\n{$label}" . $this->docStringEndToken; } return "<<<'{$label}'\n{$node->value}\n{$label}" . $this->docStringEndToken; } /* break missing intentionally */ case \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_SINGLE_QUOTED: return $this->pSingleQuotedString($node->value); case \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_HEREDOC: $label = $node->getAttribute('docLabel'); if ($label && !$this->containsEndLabel($node->value, $label)) { if ($node->value === '') { return "<<<{$label}\n{$label}" . $this->docStringEndToken; } $escaped = $this->escapeString($node->value, null); return "<<<{$label}\n" . $escaped . "\n{$label}" . $this->docStringEndToken; } /* break missing intentionally */ case \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_DOUBLE_QUOTED: return '"' . $this->escapeString($node->value, '"') . '"'; } throw new \Exception('Invalid string kind'); } protected function pScalar_Encapsed(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\Encapsed $node) { if ($node->getAttribute('kind') === \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_HEREDOC) { $label = $node->getAttribute('docLabel'); if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) { if (\count($node->parts) === 1 && $node->parts[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart && $node->parts[0]->value === '') { return "<<<{$label}\n{$label}" . $this->docStringEndToken; } return "<<<{$label}\n" . $this->pEncapsList($node->parts, null) . "\n{$label}" . $this->docStringEndToken; } } return '"' . $this->pEncapsList($node->parts, '"') . '"'; } protected function pScalar_LNumber(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber $node) { if ($node->value === -\PHP_INT_MAX - 1) { // PHP_INT_MIN cannot be represented as a literal, // because the sign is not part of the literal return '(-' . \PHP_INT_MAX . '-1)'; } $kind = $node->getAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::KIND_DEC); if (\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::KIND_DEC === $kind) { return (string) $node->value; } if ($node->value < 0) { $sign = '-'; $str = (string) -$node->value; } else { $sign = ''; $str = (string) $node->value; } switch ($kind) { case \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::KIND_BIN: return $sign . '0b' . \base_convert($str, 10, 2); case \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::KIND_OCT: return $sign . '0' . \base_convert($str, 10, 8); case \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::KIND_HEX: return $sign . '0x' . \base_convert($str, 10, 16); } throw new \Exception('Invalid number kind'); } protected function pScalar_DNumber(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber $node) { if (!\is_finite($node->value)) { if ($node->value === \INF) { return '\\INF'; } elseif ($node->value === -\INF) { return '-\\INF'; } else { return '\\NAN'; } } // Try to find a short full-precision representation $stringValue = \sprintf('%.16G', $node->value); if ($node->value !== (double) $stringValue) { $stringValue = \sprintf('%.17G', $node->value); } // %G is locale dependent and there exists no locale-independent alternative. We don't want // mess with switching locales here, so let's assume that a comma is the only non-standard // decimal separator we may encounter... $stringValue = \str_replace(',', '.', $stringValue); // ensure that number is really printed as float return \preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; } protected function pScalar_EncapsedStringPart(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart $node) { throw new \LogicException('Cannot directly print EncapsedStringPart'); } // Assignments protected function pExpr_Assign(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign::class, $node->var, ' = ', $node->expr); } protected function pExpr_AssignRef(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef::class, $node->var, ' =& ', $node->expr); } protected function pExpr_AssignOp_Plus(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Plus $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Plus::class, $node->var, ' += ', $node->expr); } protected function pExpr_AssignOp_Minus(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Minus $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Minus::class, $node->var, ' -= ', $node->expr); } protected function pExpr_AssignOp_Mul(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mul $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mul::class, $node->var, ' *= ', $node->expr); } protected function pExpr_AssignOp_Div(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Div $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Div::class, $node->var, ' /= ', $node->expr); } protected function pExpr_AssignOp_Concat(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Concat $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Concat::class, $node->var, ' .= ', $node->expr); } protected function pExpr_AssignOp_Mod(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mod $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mod::class, $node->var, ' %= ', $node->expr); } protected function pExpr_AssignOp_BitwiseAnd(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseAnd $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseAnd::class, $node->var, ' &= ', $node->expr); } protected function pExpr_AssignOp_BitwiseOr(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseOr $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseOr::class, $node->var, ' |= ', $node->expr); } protected function pExpr_AssignOp_BitwiseXor(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseXor $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseXor::class, $node->var, ' ^= ', $node->expr); } protected function pExpr_AssignOp_ShiftLeft(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftLeft $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftLeft::class, $node->var, ' <<= ', $node->expr); } protected function pExpr_AssignOp_ShiftRight(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftRight $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftRight::class, $node->var, ' >>= ', $node->expr); } protected function pExpr_AssignOp_Pow(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Pow $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Pow::class, $node->var, ' **= ', $node->expr); } protected function pExpr_AssignOp_Coalesce(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Coalesce $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Coalesce::class, $node->var, ' ??= ', $node->expr); } // Binary expressions protected function pExpr_BinaryOp_Plus(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus::class, $node->left, ' + ', $node->right); } protected function pExpr_BinaryOp_Minus(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus::class, $node->left, ' - ', $node->right); } protected function pExpr_BinaryOp_Mul(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul::class, $node->left, ' * ', $node->right); } protected function pExpr_BinaryOp_Div(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div::class, $node->left, ' / ', $node->right); } protected function pExpr_BinaryOp_Concat(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat::class, $node->left, ' . ', $node->right); } protected function pExpr_BinaryOp_Mod(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod::class, $node->left, ' % ', $node->right); } protected function pExpr_BinaryOp_BooleanAnd(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd::class, $node->left, ' && ', $node->right); } protected function pExpr_BinaryOp_BooleanOr(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr::class, $node->left, ' || ', $node->right); } protected function pExpr_BinaryOp_BitwiseAnd(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd::class, $node->left, ' & ', $node->right); } protected function pExpr_BinaryOp_BitwiseOr(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr::class, $node->left, ' | ', $node->right); } protected function pExpr_BinaryOp_BitwiseXor(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor::class, $node->left, ' ^ ', $node->right); } protected function pExpr_BinaryOp_ShiftLeft(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftLeft $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftLeft::class, $node->left, ' << ', $node->right); } protected function pExpr_BinaryOp_ShiftRight(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftRight $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftRight::class, $node->left, ' >> ', $node->right); } protected function pExpr_BinaryOp_Pow(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Pow $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Pow::class, $node->left, ' ** ', $node->right); } protected function pExpr_BinaryOp_LogicalAnd(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd::class, $node->left, ' and ', $node->right); } protected function pExpr_BinaryOp_LogicalOr(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr::class, $node->left, ' or ', $node->right); } protected function pExpr_BinaryOp_LogicalXor(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor::class, $node->left, ' xor ', $node->right); } protected function pExpr_BinaryOp_Equal(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal::class, $node->left, ' == ', $node->right); } protected function pExpr_BinaryOp_NotEqual(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual::class, $node->left, ' != ', $node->right); } protected function pExpr_BinaryOp_Identical(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical::class, $node->left, ' === ', $node->right); } protected function pExpr_BinaryOp_NotIdentical(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical::class, $node->left, ' !== ', $node->right); } protected function pExpr_BinaryOp_Spaceship(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Spaceship $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Spaceship::class, $node->left, ' <=> ', $node->right); } protected function pExpr_BinaryOp_Greater(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater::class, $node->left, ' > ', $node->right); } protected function pExpr_BinaryOp_GreaterOrEqual(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual::class, $node->left, ' >= ', $node->right); } protected function pExpr_BinaryOp_Smaller(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller::class, $node->left, ' < ', $node->right); } protected function pExpr_BinaryOp_SmallerOrEqual(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual::class, $node->left, ' <= ', $node->right); } protected function pExpr_BinaryOp_Coalesce(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce $node) { return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce::class, $node->left, ' ?? ', $node->right); } protected function pExpr_Instanceof(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_ $node) { list($precedence, $associativity) = $this->precedenceMap[\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_::class]; return $this->pPrec($node->expr, $precedence, $associativity, -1) . ' instanceof ' . $this->pNewVariable($node->class); } // Unary expressions protected function pExpr_BooleanNot(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot::class, '!', $node->expr); } protected function pExpr_BitwiseNot(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BitwiseNot $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BitwiseNot::class, '~', $node->expr); } protected function pExpr_UnaryMinus(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus $node) { if ($node->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus || $node->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec) { // Enforce -(-$expr) instead of --$expr return '-(' . $this->p($node->expr) . ')'; } return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus::class, '-', $node->expr); } protected function pExpr_UnaryPlus(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus $node) { if ($node->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus || $node->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc) { // Enforce +(+$expr) instead of ++$expr return '+(' . $this->p($node->expr) . ')'; } return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus::class, '+', $node->expr); } protected function pExpr_PreInc(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc::class, '++', $node->var); } protected function pExpr_PreDec(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec::class, '--', $node->var); } protected function pExpr_PostInc(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc $node) { return $this->pPostfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc::class, $node->var, '++'); } protected function pExpr_PostDec(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec $node) { return $this->pPostfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec::class, $node->var, '--'); } protected function pExpr_ErrorSuppress(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ErrorSuppress $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ErrorSuppress::class, '@', $node->expr); } protected function pExpr_YieldFrom(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom::class, 'yield from ', $node->expr); } protected function pExpr_Print(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Print_ $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Print_::class, 'print ', $node->expr); } // Casts protected function pExpr_Cast_Int(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Int_ $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Int_::class, '(int) ', $node->expr); } protected function pExpr_Cast_Double(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double $node) { $kind = $node->getAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::KIND_DOUBLE); if ($kind === \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::KIND_DOUBLE) { $cast = '(double)'; } elseif ($kind === \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::KIND_FLOAT) { $cast = '(float)'; } elseif ($kind === \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::KIND_REAL) { $cast = '(real)'; } return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::class, $cast . ' ', $node->expr); } protected function pExpr_Cast_String(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\String_ $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\String_::class, '(string) ', $node->expr); } protected function pExpr_Cast_Array(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Array_ $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Array_::class, '(array) ', $node->expr); } protected function pExpr_Cast_Object(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Object_ $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Object_::class, '(object) ', $node->expr); } protected function pExpr_Cast_Bool(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Bool_ $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Bool_::class, '(bool) ', $node->expr); } protected function pExpr_Cast_Unset(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Unset_ $node) { return $this->pPrefixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Unset_::class, '(unset) ', $node->expr); } // Function calls and similar constructs protected function pExpr_FuncCall(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $node) { return $this->pCallLhs($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_MethodCall(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall $node) { return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_NullsafeMethodCall(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafeMethodCall $node) { return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_StaticCall(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall $node) { return $this->pDereferenceLhs($node->class) . '::' . ($node->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr ? $node->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable ? $this->p($node->name) : '{' . $this->p($node->name) . '}' : $node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_Empty(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Empty_ $node) { return 'empty(' . $this->p($node->expr) . ')'; } protected function pExpr_Isset(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Isset_ $node) { return 'isset(' . $this->pCommaSeparated($node->vars) . ')'; } protected function pExpr_Eval(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Eval_ $node) { return 'eval(' . $this->p($node->expr) . ')'; } protected function pExpr_Include(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_ $node) { static $map = [\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_INCLUDE => 'include', \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_REQUIRE => 'require', \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once']; return $map[$node->type] . ' ' . $this->p($node->expr); } protected function pExpr_List(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\List_ $node) { return 'list(' . $this->pCommaSeparated($node->items) . ')'; } // Other protected function pExpr_Error(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error $node) { throw new \LogicException('Cannot pretty-print AST with Error nodes'); } protected function pExpr_Variable(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable $node) { if ($node->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { return '${' . $this->p($node->name) . '}'; } else { return '$' . $node->name; } } protected function pExpr_Array(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ $node) { $syntax = $node->getAttribute('kind', $this->options['shortArraySyntax'] ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_::KIND_SHORT : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_::KIND_LONG); if ($syntax === \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_::KIND_SHORT) { return '[' . $this->pMaybeMultiline($node->items, \true) . ']'; } else { return 'array(' . $this->pMaybeMultiline($node->items, \true) . ')'; } } protected function pExpr_ArrayItem(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem $node) { return (null !== $node->key ? $this->p($node->key) . ' => ' : '') . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value); } protected function pExpr_ArrayDimFetch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch $node) { return $this->pDereferenceLhs($node->var) . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']'; } protected function pExpr_ConstFetch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch $node) { return $this->p($node->name); } protected function pExpr_ClassConstFetch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch $node) { return $this->pDereferenceLhs($node->class) . '::' . $this->p($node->name); } protected function pExpr_PropertyFetch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch $node) { return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name); } protected function pExpr_NullsafePropertyFetch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafePropertyFetch $node) { return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name); } protected function pExpr_StaticPropertyFetch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch $node) { return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name); } protected function pExpr_ShellExec(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ShellExec $node) { return '`' . $this->pEncapsList($node->parts, '`') . '`'; } protected function pExpr_Closure(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure $node) { return $this->pAttrGroups($node->attrGroups, \true) . ($node->static ? 'static ' : '') . 'function ' . ($node->byRef ? '&' : '') . '(' . $this->pCommaSeparated($node->params) . ')' . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')' : '') . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pExpr_Match(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Match_ $node) { return 'match (' . $this->p($node->cond) . ') {' . $this->pCommaSeparatedMultiline($node->arms, \true) . $this->nl . '}'; } protected function pMatchArm(\_HumbugBoxd02f763d3c56\PhpParser\Node\MatchArm $node) { return ($node->conds ? $this->pCommaSeparated($node->conds) : 'default') . ' => ' . $this->p($node->body); } protected function pExpr_ArrowFunction(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction $node) { return $this->pAttrGroups($node->attrGroups, \true) . ($node->static ? 'static ' : '') . 'fn' . ($node->byRef ? '&' : '') . '(' . $this->pCommaSeparated($node->params) . ')' . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') . ' => ' . $this->p($node->expr); } protected function pExpr_ClosureUse(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClosureUse $node) { return ($node->byRef ? '&' : '') . $this->p($node->var); } protected function pExpr_New(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ $node) { if ($node->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : ''; return 'new ' . $this->pClassCommon($node->class, $args); } return 'new ' . $this->pNewVariable($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_Clone(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Clone_ $node) { return 'clone ' . $this->p($node->expr); } protected function pExpr_Ternary(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary $node) { // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator. // this is okay because the part between ? and : never needs parentheses. return $this->pInfixOp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary::class, $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else); } protected function pExpr_Exit(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_ $node) { $kind = $node->getAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_::KIND_DIE); return ($kind === \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_::KIND_EXIT ? 'exit' : 'die') . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : ''); } protected function pExpr_Throw(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Throw_ $node) { return 'throw ' . $this->p($node->expr); } protected function pExpr_Yield(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_ $node) { if ($node->value === null) { return 'yield'; } else { // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary return '(yield ' . ($node->key !== null ? $this->p($node->key) . ' => ' : '') . $this->p($node->value) . ')'; } } // Declarations protected function pStmt_Namespace(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_ $node) { if ($this->canUseSemicolonNamespaces) { return 'namespace ' . $this->p($node->name) . ';' . $this->nl . $this->pStmts($node->stmts, \false); } else { return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; } } protected function pStmt_Use(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ $node) { return 'use ' . $this->pUseType($node->type) . $this->pCommaSeparated($node->uses) . ';'; } protected function pStmt_GroupUse(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse $node) { return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix) . '\\{' . $this->pCommaSeparated($node->uses) . '};'; } protected function pStmt_UseUse(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse $node) { return $this->pUseType($node->type) . $this->p($node->name) . (null !== $node->alias ? ' as ' . $node->alias : ''); } protected function pUseType($type) { return $type === \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION ? 'function ' : ($type === \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT ? 'const ' : ''); } protected function pStmt_Interface(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ $node) { return $this->pAttrGroups($node->attrGroups) . 'interface ' . $node->name . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Class(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ $node) { return $this->pClassCommon($node, ' ' . $node->name); } protected function pStmt_Trait(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_ $node) { return $this->pAttrGroups($node->attrGroups) . 'trait ' . $node->name . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_TraitUse(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse $node) { return 'use ' . $this->pCommaSeparated($node->traits) . (empty($node->adaptations) ? ';' : ' {' . $this->pStmts($node->adaptations) . $this->nl . '}'); } protected function pStmt_TraitUseAdaptation_Precedence(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Precedence $node) { return $this->p($node->trait) . '::' . $node->method . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';'; } protected function pStmt_TraitUseAdaptation_Alias(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias $node) { return (null !== $node->trait ? $this->p($node->trait) . '::' : '') . $node->method . ' as' . (null !== $node->newModifier ? ' ' . \rtrim($this->pModifiers($node->newModifier), ' ') : '') . (null !== $node->newName ? ' ' . $node->newName : '') . ';'; } protected function pStmt_Property(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property $node) { return $this->pAttrGroups($node->attrGroups) . (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) . ($node->type ? $this->p($node->type) . ' ' : '') . $this->pCommaSeparated($node->props) . ';'; } protected function pStmt_PropertyProperty(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\PropertyProperty $node) { return '$' . $node->name . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); } protected function pStmt_ClassMethod(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod $node) { return $this->pAttrGroups($node->attrGroups) . $this->pModifiers($node->flags) . 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pMaybeMultiline($node->params) . ')' . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . (null !== $node->stmts ? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}' : ';'); } protected function pStmt_ClassConst(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst $node) { return $this->pAttrGroups($node->attrGroups) . $this->pModifiers($node->flags) . 'const ' . $this->pCommaSeparated($node->consts) . ';'; } protected function pStmt_Function(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ $node) { return $this->pAttrGroups($node->attrGroups) . 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pCommaSeparated($node->params) . ')' . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Const(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_ $node) { return 'const ' . $this->pCommaSeparated($node->consts) . ';'; } protected function pStmt_Declare(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Declare_ $node) { return 'declare (' . $this->pCommaSeparated($node->declares) . ')' . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . $this->nl . '}' : ';'); } protected function pStmt_DeclareDeclare(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\DeclareDeclare $node) { return $node->key . '=' . $this->p($node->value); } // Control flow protected function pStmt_If(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_ $node) { return 'if (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}' . ($node->elseifs ? ' ' . $this->pImplode($node->elseifs, ' ') : '') . (null !== $node->else ? ' ' . $this->p($node->else) : ''); } protected function pStmt_ElseIf(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ElseIf_ $node) { return 'elseif (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Else(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Else_ $node) { return 'else {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_For(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\For_ $node) { return 'for (' . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') . $this->pCommaSeparated($node->loop) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Foreach(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_ $node) { return 'foreach (' . $this->p($node->expr) . ' as ' . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_While(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\While_ $node) { return 'while (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Do(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Do_ $node) { return 'do {' . $this->pStmts($node->stmts) . $this->nl . '} while (' . $this->p($node->cond) . ');'; } protected function pStmt_Switch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Switch_ $node) { return 'switch (' . $this->p($node->cond) . ') {' . $this->pStmts($node->cases) . $this->nl . '}'; } protected function pStmt_Case(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Case_ $node) { return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' . $this->pStmts($node->stmts); } protected function pStmt_TryCatch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TryCatch $node) { return 'try {' . $this->pStmts($node->stmts) . $this->nl . '}' . ($node->catches ? ' ' . $this->pImplode($node->catches, ' ') : '') . ($node->finally !== null ? ' ' . $this->p($node->finally) : ''); } protected function pStmt_Catch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Catch_ $node) { return 'catch (' . $this->pImplode($node->types, '|') . ($node->var !== null ? ' ' . $this->p($node->var) : '') . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Finally(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Finally_ $node) { return 'finally {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Break(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Break_ $node) { return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; } protected function pStmt_Continue(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Continue_ $node) { return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; } protected function pStmt_Return(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_ $node) { return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';'; } protected function pStmt_Throw(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Throw_ $node) { return 'throw ' . $this->p($node->expr) . ';'; } protected function pStmt_Label(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Label $node) { return $node->name . ':'; } protected function pStmt_Goto(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Goto_ $node) { return 'goto ' . $node->name . ';'; } // Other protected function pStmt_Expression(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression $node) { return $this->p($node->expr) . ';'; } protected function pStmt_Echo(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Echo_ $node) { return 'echo ' . $this->pCommaSeparated($node->exprs) . ';'; } protected function pStmt_Static(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Static_ $node) { return 'static ' . $this->pCommaSeparated($node->vars) . ';'; } protected function pStmt_Global(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Global_ $node) { return 'global ' . $this->pCommaSeparated($node->vars) . ';'; } protected function pStmt_StaticVar(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\StaticVar $node) { return $this->p($node->var) . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); } protected function pStmt_Unset(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Unset_ $node) { return 'unset(' . $this->pCommaSeparated($node->vars) . ');'; } protected function pStmt_InlineHTML(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\InlineHTML $node) { $newline = $node->getAttribute('hasLeadingNewline', \true) ? "\n" : ''; return '?>' . $newline . $node->value . 'remaining; } protected function pStmt_Nop(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop $node) { return ''; } // Helpers protected function pClassCommon(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ $node, $afterClassToken) { return $this->pAttrGroups($node->attrGroups, $node->name === null) . $this->pModifiers($node->flags) . 'class' . $afterClassToken . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pObjectProperty($node) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { return '{' . $this->p($node) . '}'; } else { return $node; } } protected function pEncapsList(array $encapsList, $quote) { $return = ''; foreach ($encapsList as $element) { if ($element instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart) { $return .= $this->escapeString($element->value, $quote); } else { $return .= '{' . $this->p($element) . '}'; } } return $return; } protected function pSingleQuotedString(string $string) { return '\'' . \addcslashes($string, '\'\\') . '\''; } protected function escapeString($string, $quote) { if (null === $quote) { // For doc strings, don't escape newlines $escaped = \addcslashes($string, "\t\f\v\$\\"); } else { $escaped = \addcslashes($string, "\n\r\t\f\v\$" . $quote . "\\"); } // Escape other control characters return \preg_replace_callback('/([\\0-\\10\\16-\\37])(?=([0-7]?))/', function ($matches) { $oct = \decoct(\ord($matches[1])); if ($matches[2] !== '') { // If there is a trailing digit, use the full three character form return '\\' . \str_pad($oct, 3, '0', \STR_PAD_LEFT); } return '\\' . $oct; }, $escaped); } protected function containsEndLabel($string, $label, $atStart = \true, $atEnd = \true) { $start = $atStart ? '(?:^|[\\r\\n])' : '[\\r\\n]'; $end = $atEnd ? '(?:$|[;\\r\\n])' : '[;\\r\\n]'; return \false !== \strpos($string, $label) && \preg_match('/' . $start . $label . $end . '/', $string); } protected function encapsedContainsEndLabel(array $parts, $label) { foreach ($parts as $i => $part) { $atStart = $i === 0; $atEnd = $i === \count($parts) - 1; if ($part instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart && $this->containsEndLabel($part->value, $label, $atStart, $atEnd)) { return \true; } } return \false; } protected function pDereferenceLhs(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { if (!$this->dereferenceLhsRequiresParens($node)) { return $this->p($node); } else { return '(' . $this->p($node) . ')'; } } protected function pCallLhs(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { if (!$this->callLhsRequiresParens($node)) { return $this->p($node); } else { return '(' . $this->p($node) . ')'; } } protected function pNewVariable(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { // TODO: This is not fully accurate. return $this->pDereferenceLhs($node); } /** * @param Node[] $nodes * @return bool */ private function hasNodeWithComments(array $nodes) { foreach ($nodes as $node) { if ($node && $node->getComments()) { return \true; } } return \false; } private function pMaybeMultiline(array $nodes, bool $trailingComma = \false) { if (!$this->hasNodeWithComments($nodes)) { return $this->pCommaSeparated($nodes); } else { return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl; } } private function pAttrGroups(array $nodes, bool $inline = \false) : string { $result = ''; $sep = $inline ? ' ' : $this->nl; foreach ($nodes as $node) { $result .= $this->p($node) . $sep; } return $result; } } defineCompatibilityTokens(); $this->tokenMap = $this->createTokenMap(); $this->identifierTokens = $this->createIdentifierTokenMap(); // map of tokens to drop while lexing (the map is only used for isset lookup, // that's why the value is simply set to 1; the value is never actually used.) $this->dropTokens = \array_fill_keys([\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1); $defaultAttributes = ['comments', 'startLine', 'endLine']; $usedAttributes = \array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, \true); // Create individual boolean properties to make these checks faster. $this->attributeStartLineUsed = isset($usedAttributes['startLine']); $this->attributeEndLineUsed = isset($usedAttributes['endLine']); $this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']); $this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']); $this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']); $this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']); $this->attributeCommentsUsed = isset($usedAttributes['comments']); } /** * Initializes the lexer for lexing the provided source code. * * This function does not throw if lexing errors occur. Instead, errors may be retrieved using * the getErrors() method. * * @param string $code The source code to lex * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to * ErrorHandler\Throwing */ public function startLexing(string $code, \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler $errorHandler = null) { if (null === $errorHandler) { $errorHandler = new \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler\Throwing(); } $this->code = $code; // keep the code around for __halt_compiler() handling $this->pos = -1; $this->line = 1; $this->filePos = 0; // If inline HTML occurs without preceding code, treat it as if it had a leading newline. // This ensures proper composability, because having a newline is the "safe" assumption. $this->prevCloseTagHasNewline = \true; $scream = \ini_set('xdebug.scream', '0'); \error_clear_last(); $this->tokens = @\token_get_all($code); $this->postprocessTokens($errorHandler); if (\false !== $scream) { \ini_set('xdebug.scream', $scream); } } private function handleInvalidCharacterRange($start, $end, $line, \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler $errorHandler) { $tokens = []; for ($i = $start; $i < $end; $i++) { $chr = $this->code[$i]; if ($chr === "\0") { // PHP cuts error message after null byte, so need special case $errorMsg = 'Unexpected null byte'; } else { $errorMsg = \sprintf('Unexpected character "%s" (ASCII %d)', $chr, \ord($chr)); } $tokens[] = [\T_BAD_CHARACTER, $chr, $line]; $errorHandler->handleError(new \_HumbugBoxd02f763d3c56\PhpParser\Error($errorMsg, ['startLine' => $line, 'endLine' => $line, 'startFilePos' => $i, 'endFilePos' => $i])); } return $tokens; } /** * Check whether comment token is unterminated. * * @return bool */ private function isUnterminatedComment($token) : bool { return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT) && \substr($token[1], 0, 2) === '/*' && \substr($token[1], -2) !== '*/'; } protected function postprocessTokens(\_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler $errorHandler) { // PHP's error handling for token_get_all() is rather bad, so if we want detailed // error information we need to compute it ourselves. Invalid character errors are // detected by finding "gaps" in the token array. Unterminated comments are detected // by checking if a trailing comment has a "*/" at the end. // // Additionally, we canonicalize to the PHP 8 comment format here, which does not include // the trailing whitespace anymore. // // We also canonicalize to the PHP 8 T_NAME_* tokens. $filePos = 0; $line = 1; $numTokens = \count($this->tokens); for ($i = 0; $i < $numTokens; $i++) { $token = $this->tokens[$i]; // Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token. // In this case we only need to emit an error. if ($token[0] === \T_BAD_CHARACTER) { $this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler); } if ($token[0] === \T_COMMENT && \substr($token[1], 0, 2) !== '/*' && \preg_match('/(\\r\\n|\\n|\\r)$/D', $token[1], $matches)) { $trailingNewline = $matches[0]; $token[1] = \substr($token[1], 0, -\strlen($trailingNewline)); $this->tokens[$i] = $token; if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) { // Move trailing newline into following T_WHITESPACE token, if it already exists. $this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1]; $this->tokens[$i + 1][2]--; } else { // Otherwise, we need to create a new T_WHITESPACE token. \array_splice($this->tokens, $i + 1, 0, [[\T_WHITESPACE, $trailingNewline, $line]]); $numTokens++; } } // Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING // into a single token. if (\is_array($token) && ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) { $lastWasSeparator = $token[0] === \T_NS_SEPARATOR; $text = $token[1]; for ($j = $i + 1; isset($this->tokens[$j]); $j++) { if ($lastWasSeparator) { if (!isset($this->identifierTokens[$this->tokens[$j][0]])) { break; } $lastWasSeparator = \false; } else { if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) { break; } $lastWasSeparator = \true; } $text .= $this->tokens[$j][1]; } if ($lastWasSeparator) { // Trailing separator is not part of the name. $j--; $text = \substr($text, 0, -1); } if ($j > $i + 1) { if ($token[0] === \T_NS_SEPARATOR) { $type = \T_NAME_FULLY_QUALIFIED; } else { if ($token[0] === \T_NAMESPACE) { $type = \T_NAME_RELATIVE; } else { $type = \T_NAME_QUALIFIED; } } $token = [$type, $text, $line]; \array_splice($this->tokens, $i, $j - $i, [$token]); $numTokens -= $j - $i - 1; } } $tokenValue = \is_string($token) ? $token : $token[1]; $tokenLen = \strlen($tokenValue); if (\substr($this->code, $filePos, $tokenLen) !== $tokenValue) { // Something is missing, must be an invalid character $nextFilePos = \strpos($this->code, $tokenValue, $filePos); $badCharTokens = $this->handleInvalidCharacterRange($filePos, $nextFilePos, $line, $errorHandler); $filePos = (int) $nextFilePos; \array_splice($this->tokens, $i, 0, $badCharTokens); $numTokens += \count($badCharTokens); $i += \count($badCharTokens); } $filePos += $tokenLen; $line += \substr_count($tokenValue, "\n"); } if ($filePos !== \strlen($this->code)) { if (\substr($this->code, $filePos, 2) === '/*') { // Unlike PHP, HHVM will drop unterminated comments entirely $comment = \substr($this->code, $filePos); $errorHandler->handleError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Unterminated comment', ['startLine' => $line, 'endLine' => $line + \substr_count($comment, "\n"), 'startFilePos' => $filePos, 'endFilePos' => $filePos + \strlen($comment)])); // Emulate the PHP behavior $isDocComment = isset($comment[3]) && $comment[3] === '*'; $this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line]; } else { // Invalid characters at the end of the input $badCharTokens = $this->handleInvalidCharacterRange($filePos, \strlen($this->code), $line, $errorHandler); $this->tokens = \array_merge($this->tokens, $badCharTokens); } return; } if (\count($this->tokens) > 0) { // Check for unterminated comment $lastToken = $this->tokens[\count($this->tokens) - 1]; if ($this->isUnterminatedComment($lastToken)) { $errorHandler->handleError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Unterminated comment', ['startLine' => $line - \substr_count($lastToken[1], "\n"), 'endLine' => $line, 'startFilePos' => $filePos - \strlen($lastToken[1]), 'endFilePos' => $filePos])); } } } /** * Fetches the next token. * * The available attributes are determined by the 'usedAttributes' option, which can * be specified in the constructor. The following attributes are supported: * * * 'comments' => Array of PhpParser\Comment or PhpParser\Comment\Doc instances, * representing all comments that occurred between the previous * non-discarded token and the current one. * * 'startLine' => Line in which the node starts. * * 'endLine' => Line in which the node ends. * * 'startTokenPos' => Offset into the token array of the first token in the node. * * 'endTokenPos' => Offset into the token array of the last token in the node. * * 'startFilePos' => Offset into the code string of the first character that is part of the node. * * 'endFilePos' => Offset into the code string of the last character that is part of the node. * * @param mixed $value Variable to store token content in * @param mixed $startAttributes Variable to store start attributes in * @param mixed $endAttributes Variable to store end attributes in * * @return int Token id */ public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int { $startAttributes = []; $endAttributes = []; while (1) { if (isset($this->tokens[++$this->pos])) { $token = $this->tokens[$this->pos]; } else { // EOF token with ID 0 $token = "\0"; } if ($this->attributeStartLineUsed) { $startAttributes['startLine'] = $this->line; } if ($this->attributeStartTokenPosUsed) { $startAttributes['startTokenPos'] = $this->pos; } if ($this->attributeStartFilePosUsed) { $startAttributes['startFilePos'] = $this->filePos; } if (\is_string($token)) { $value = $token; if (isset($token[1])) { // bug in token_get_all $this->filePos += 2; $id = \ord('"'); } else { $this->filePos += 1; $id = \ord($token); } } elseif (!isset($this->dropTokens[$token[0]])) { $value = $token[1]; $id = $this->tokenMap[$token[0]]; if (\T_CLOSE_TAG === $token[0]) { $this->prevCloseTagHasNewline = \false !== \strpos($token[1], "\n"); } elseif (\T_INLINE_HTML === $token[0]) { $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline; } $this->line += \substr_count($value, "\n"); $this->filePos += \strlen($value); } else { $origLine = $this->line; $origFilePos = $this->filePos; $this->line += \substr_count($token[1], "\n"); $this->filePos += \strlen($token[1]); if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) { if ($this->attributeCommentsUsed) { $comment = \T_DOC_COMMENT === $token[0] ? new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc($token[1], $origLine, $origFilePos, $this->pos, $this->line, $this->filePos - 1, $this->pos) : new \_HumbugBoxd02f763d3c56\PhpParser\Comment($token[1], $origLine, $origFilePos, $this->pos, $this->line, $this->filePos - 1, $this->pos); $startAttributes['comments'][] = $comment; } } continue; } if ($this->attributeEndLineUsed) { $endAttributes['endLine'] = $this->line; } if ($this->attributeEndTokenPosUsed) { $endAttributes['endTokenPos'] = $this->pos; } if ($this->attributeEndFilePosUsed) { $endAttributes['endFilePos'] = $this->filePos - 1; } return $id; } throw new \RuntimeException('Reached end of lexer loop'); } /** * Returns the token array for current code. * * The token array is in the same format as provided by the * token_get_all() function and does not discard tokens (i.e. * whitespace and comments are included). The token position * attributes are against this token array. * * @return array Array of tokens in token_get_all() format */ public function getTokens() : array { return $this->tokens; } /** * Handles __halt_compiler() by returning the text after it. * * @return string Remaining text */ public function handleHaltCompiler() : string { // text after T_HALT_COMPILER, still including (); $textAfter = \substr($this->code, $this->filePos); // ensure that it is followed by (); // this simplifies the situation, by not allowing any comments // in between of the tokens. if (!\preg_match('~^\\s*\\(\\s*\\)\\s*(?:;|\\?>\\r?\\n?)~', $textAfter, $matches)) { throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('__HALT_COMPILER must be followed by "();"'); } // prevent the lexer from returning any further tokens $this->pos = \count($this->tokens); // return with (); removed return \substr($textAfter, \strlen($matches[0])); } private function defineCompatibilityTokens() { static $compatTokensDefined = \false; if ($compatTokensDefined) { return; } $compatTokens = [ // PHP 7.4 'T_BAD_CHARACTER', 'T_FN', 'T_COALESCE_EQUAL', // PHP 8.0 'T_NAME_QUALIFIED', 'T_NAME_FULLY_QUALIFIED', 'T_NAME_RELATIVE', 'T_MATCH', 'T_NULLSAFE_OBJECT_OPERATOR', 'T_ATTRIBUTE', ]; // PHP-Parser might be used together with another library that also emulates some or all // of these tokens. Perform a sanity-check that all already defined tokens have been // assigned a unique ID. $usedTokenIds = []; foreach ($compatTokens as $token) { if (\defined($token)) { $tokenId = \constant($token); $clashingToken = $usedTokenIds[$tokenId] ?? null; if ($clashingToken !== null) { throw new \Error(\sprintf('Token %s has same ID as token %s, ' . 'you may be using a library with broken token emulation', $token, $clashingToken)); } $usedTokenIds[$tokenId] = $token; } } // Now define any tokens that have not yet been emulated. Try to assign IDs from -1 // downwards, but skip any IDs that may already be in use. $newTokenId = -1; foreach ($compatTokens as $token) { if (!\defined($token)) { while (isset($usedTokenIds[$newTokenId])) { $newTokenId--; } \define($token, $newTokenId); $newTokenId--; } } $compatTokensDefined = \true; } /** * Creates the token map. * * The token map maps the PHP internal token identifiers * to the identifiers used by the Parser. Additionally it * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'. * * @return array The token map */ protected function createTokenMap() : array { $tokenMap = []; // 256 is the minimum possible token number, as everything below // it is an ASCII value for ($i = 256; $i < 1000; ++$i) { if (\T_DOUBLE_COLON === $i) { // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM $tokenMap[$i] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_PAAMAYIM_NEKUDOTAYIM; } elseif (\T_OPEN_TAG_WITH_ECHO === $i) { // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO $tokenMap[$i] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_ECHO; } elseif (\T_CLOSE_TAG === $i) { // T_CLOSE_TAG is equivalent to ';' $tokenMap[$i] = \ord(';'); } elseif ('UNKNOWN' !== ($name = \token_name($i))) { if ('T_HASHBANG' === $name) { // HHVM uses a special token for #! hashbang lines $tokenMap[$i] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_INLINE_HTML; } elseif (\defined($name = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::class . '::' . $name)) { // Other tokens can be mapped directly $tokenMap[$i] = \constant($name); } } } // HHVM uses a special token for numbers that overflow to double if (\defined('T_ONUMBER')) { $tokenMap[\T_ONUMBER] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_DNUMBER; } // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant if (\defined('T_COMPILER_HALT_OFFSET')) { $tokenMap[\T_COMPILER_HALT_OFFSET] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_STRING; } // Assign tokens for which we define compatibility constants, as token_name() does not know them. $tokenMap[\T_FN] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_FN; $tokenMap[\T_COALESCE_EQUAL] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_COALESCE_EQUAL; $tokenMap[\T_NAME_QUALIFIED] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_NAME_QUALIFIED; $tokenMap[\T_NAME_FULLY_QUALIFIED] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_NAME_FULLY_QUALIFIED; $tokenMap[\T_NAME_RELATIVE] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_NAME_RELATIVE; $tokenMap[\T_MATCH] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_MATCH; $tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_NULLSAFE_OBJECT_OPERATOR; $tokenMap[\T_ATTRIBUTE] = \_HumbugBoxd02f763d3c56\PhpParser\Parser\Tokens::T_ATTRIBUTE; return $tokenMap; } private function createIdentifierTokenMap() : array { // Based on semi_reserved production. return \array_fill_keys([\T_STRING, \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND, \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE, \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH, \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO, \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT, \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS, \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN, \T_MATCH], \true); } } [aliasName => originalName]] */ protected $aliases = []; /** @var Name[][] Same as $aliases but preserving original case */ protected $origAliases = []; /** @var ErrorHandler Error handler */ protected $errorHandler; /** * Create a name context. * * @param ErrorHandler $errorHandler Error handling used to report errors */ public function __construct(\_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler $errorHandler) { $this->errorHandler = $errorHandler; } /** * Start a new namespace. * * This also resets the alias table. * * @param Name|null $namespace Null is the global namespace */ public function startNamespace(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $namespace = null) { $this->namespace = $namespace; $this->origAliases = $this->aliases = [\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL => [], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION => [], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT => []]; } /** * Add an alias / import. * * @param Name $name Original name * @param string $aliasName Aliased name * @param int $type One of Stmt\Use_::TYPE_* * @param array $errorAttrs Attributes to use to report an error */ public function addAlias(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $name, string $aliasName, int $type, array $errorAttrs = []) { // Constant names are case sensitive, everything else case insensitive if ($type === \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT) { $aliasLookupName = $aliasName; } else { $aliasLookupName = \strtolower($aliasName); } if (isset($this->aliases[$type][$aliasLookupName])) { $typeStringMap = [\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL => '', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION => 'function ', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT => 'const ']; $this->errorHandler->handleError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Cannot use %s%s as %s because the name is already in use', $typeStringMap[$type], $name, $aliasName), $errorAttrs)); return; } $this->aliases[$type][$aliasLookupName] = $name; $this->origAliases[$type][$aliasName] = $name; } /** * Get current namespace. * * @return null|Name Namespace (or null if global namespace) */ public function getNamespace() { return $this->namespace; } /** * Get resolved name. * * @param Name $name Name to resolve * @param int $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT} * * @return null|Name Resolved name, or null if static resolution is not possible */ public function getResolvedName(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $name, int $type) { // don't resolve special class names if ($type === \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) { if (!$name->isUnqualified()) { $this->errorHandler->handleError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf("'\\%s' is an invalid class name", $name->toString()), $name->getAttributes())); } return $name; } // fully qualified names are already resolved if ($name->isFullyQualified()) { return $name; } // Try to resolve aliases if (null !== ($resolvedName = $this->resolveAlias($name, $type))) { return $resolvedName; } if ($type !== \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL && $name->isUnqualified()) { if (null === $this->namespace) { // outside of a namespace unaliased unqualified is same as fully qualified return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($name, $name->getAttributes()); } // Cannot resolve statically return null; } // if no alias exists prepend current namespace return \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified::concat($this->namespace, $name, $name->getAttributes()); } /** * Get resolved class name. * * @param Name $name Class ame to resolve * * @return Name Resolved name */ public function getResolvedClassName(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $name) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Name { return $this->getResolvedName($name, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL); } /** * Get possible ways of writing a fully qualified name (e.g., by making use of aliases). * * @param string $name Fully-qualified name (without leading namespace separator) * @param int $type One of Stmt\Use_::TYPE_* * * @return Name[] Possible representations of the name */ public function getPossibleNames(string $name, int $type) : array { $lcName = \strtolower($name); if ($type === \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL) { // self, parent and static must always be unqualified if ($lcName === "self" || $lcName === "parent" || $lcName === "static") { return [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($name)]; } } // Collect possible ways to write this name, starting with the fully-qualified name $possibleNames = [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($name)]; if (null !== ($nsRelativeName = $this->getNamespaceRelativeName($name, $lcName, $type))) { // Make sure there is no alias that makes the normally namespace-relative name // into something else if (null === $this->resolveAlias($nsRelativeName, $type)) { $possibleNames[] = $nsRelativeName; } } // Check for relevant namespace use statements foreach ($this->origAliases[\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL] as $alias => $orig) { $lcOrig = $orig->toLowerString(); if (0 === \strpos($lcName, $lcOrig . '\\')) { $possibleNames[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($alias . \substr($name, \strlen($lcOrig))); } } // Check for relevant type-specific use statements foreach ($this->origAliases[$type] as $alias => $orig) { if ($type === \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT) { // Constants are are complicated-sensitive $normalizedOrig = $this->normalizeConstName($orig->toString()); if ($normalizedOrig === $this->normalizeConstName($name)) { $possibleNames[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($alias); } } else { // Everything else is case-insensitive if ($orig->toLowerString() === $lcName) { $possibleNames[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($alias); } } } return $possibleNames; } /** * Get shortest representation of this fully-qualified name. * * @param string $name Fully-qualified name (without leading namespace separator) * @param int $type One of Stmt\Use_::TYPE_* * * @return Name Shortest representation */ public function getShortName(string $name, int $type) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Name { $possibleNames = $this->getPossibleNames($name, $type); // Find shortest name $shortestName = null; $shortestLength = \INF; foreach ($possibleNames as $possibleName) { $length = \strlen($possibleName->toCodeString()); if ($length < $shortestLength) { $shortestName = $possibleName; $shortestLength = $length; } } return $shortestName; } private function resolveAlias(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $name, $type) { $firstPart = $name->getFirst(); if ($name->isQualified()) { // resolve aliases for qualified names, always against class alias table $checkName = \strtolower($firstPart); if (isset($this->aliases[\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL][$checkName])) { $alias = $this->aliases[\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL][$checkName]; return \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); } } elseif ($name->isUnqualified()) { // constant aliases are case-sensitive, function aliases case-insensitive $checkName = $type === \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT ? $firstPart : \strtolower($firstPart); if (isset($this->aliases[$type][$checkName])) { // resolve unqualified aliases return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($this->aliases[$type][$checkName], $name->getAttributes()); } } // No applicable aliases return null; } private function getNamespaceRelativeName(string $name, string $lcName, int $type) { if (null === $this->namespace) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($name); } if ($type === \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT) { // The constants true/false/null always resolve to the global symbols, even inside a // namespace, so they may be used without qualification if ($lcName === "true" || $lcName === "false" || $lcName === "null") { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($name); } } $namespacePrefix = \strtolower($this->namespace . '\\'); if (0 === \strpos($lcName, $namespacePrefix)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name(\substr($name, \strlen($namespacePrefix))); } return null; } private function normalizeConstName(string $name) { $nsSep = \strrpos($name, '\\'); if (\false === $nsSep) { return $name; } // Constants have case-insensitive namespace and case-sensitive short-name $ns = \substr($name, 0, $nsSep); $shortName = \substr($name, $nsSep + 1); return \strtolower($ns) . '\\' . $shortName; } } args($args)); } /** * Creates a method call node. * * @param Expr $var Variable the method is called on * @param string|Identifier|Expr $name Method name * @param array $args Method arguments * * @return Expr\MethodCall */ public function methodCall(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $var, $name, array $args = []) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($var, \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeIdentifierOrExpr($name), $this->args($args)); } /** * Creates a static method call node. * * @param string|Name|Expr $class Class name * @param string|Identifier|Expr $name Method name * @param array $args Method arguments * * @return Expr\StaticCall */ public function staticCall($class, $name, array $args = []) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall(\_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeNameOrExpr($class), \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeIdentifierOrExpr($name), $this->args($args)); } /** * Creates an object creation node. * * @param string|Name|Expr $class Class name * @param array $args Constructor arguments * * @return Expr\New_ */ public function new($class, array $args = []) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_(\_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeNameOrExpr($class), $this->args($args)); } /** * Creates a constant fetch node. * * @param string|Name $name Constant name * * @return Expr\ConstFetch */ public function constFetch($name) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(\_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeName($name)); } /** * Creates a property fetch node. * * @param Expr $var Variable holding object * @param string|Identifier|Expr $name Property name * * @return Expr\PropertyFetch */ public function propertyFetch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $var, $name) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($var, \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeIdentifierOrExpr($name)); } /** * Creates a class constant fetch node. * * @param string|Name|Expr $class Class name * @param string|Identifier $name Constant name * * @return Expr\ClassConstFetch */ public function classConstFetch($class, $name) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch(\_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeNameOrExpr($class), \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeIdentifier($name)); } /** * Creates nested Concat nodes from a list of expressions. * * @param Expr|string ...$exprs Expressions or literal strings * * @return Concat */ public function concat(...$exprs) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat { $numExprs = \count($exprs); if ($numExprs < 2) { throw new \LogicException('Expected at least two expressions'); } $lastConcat = $this->normalizeStringExpr($exprs[0]); for ($i = 1; $i < $numExprs; $i++) { $lastConcat = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat($lastConcat, $this->normalizeStringExpr($exprs[$i])); } return $lastConcat; } /** * @param string|Expr $expr * @return Expr */ private function normalizeStringExpr($expr) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr { if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { return $expr; } if (\is_string($expr)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($expr); } throw new \LogicException('Expected string or Expr'); } } attrGroups = $attrGroups; $this->args = $args; $this->extends = $extends; $this->implements = $implements; $this->stmts = $stmts; } public static function fromNewNode(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ $newNode) { $class = $newNode->class; \assert($class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_); // We don't assert that $class->name is null here, to allow consumers to assign unique names // to anonymous classes for their own purposes. We simplify ignore the name here. return new self($class->attrGroups, $newNode->args, $class->extends, $class->implements, $class->stmts, $newNode->getAttributes()); } public function getType() : string { return 'Expr_PrintableNewAnonClass'; } public function getSubNodeNames() : array { return ['attrGroups', 'args', 'extends', 'implements', 'stmts']; } } isEqual = $isEqual; } /** * Calculate diff (edit script) from $old to $new. * * @param array $old Original array * @param array $new New array * * @return DiffElem[] Diff (edit script) */ public function diff(array $old, array $new) { list($trace, $x, $y) = $this->calculateTrace($old, $new); return $this->extractDiff($trace, $x, $y, $old, $new); } /** * Calculate diff, including "replace" operations. * * If a sequence of remove operations is followed by the same number of add operations, these * will be coalesced into replace operations. * * @param array $old Original array * @param array $new New array * * @return DiffElem[] Diff (edit script), including replace operations */ public function diffWithReplacements(array $old, array $new) { return $this->coalesceReplacements($this->diff($old, $new)); } private function calculateTrace(array $a, array $b) { $n = \count($a); $m = \count($b); $max = $n + $m; $v = [1 => 0]; $trace = []; for ($d = 0; $d <= $max; $d++) { $trace[] = $v; for ($k = -$d; $k <= $d; $k += 2) { if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) { $x = $v[$k + 1]; } else { $x = $v[$k - 1] + 1; } $y = $x - $k; while ($x < $n && $y < $m && ($this->isEqual)($a[$x], $b[$y])) { $x++; $y++; } $v[$k] = $x; if ($x >= $n && $y >= $m) { return [$trace, $x, $y]; } } } throw new \Exception('Should not happen'); } private function extractDiff(array $trace, int $x, int $y, array $a, array $b) { $result = []; for ($d = \count($trace) - 1; $d >= 0; $d--) { $v = $trace[$d]; $k = $x - $y; if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) { $prevK = $k + 1; } else { $prevK = $k - 1; } $prevX = $v[$prevK]; $prevY = $prevX - $prevK; while ($x > $prevX && $y > $prevY) { $result[] = new \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem(\_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_KEEP, $a[$x - 1], $b[$y - 1]); $x--; $y--; } if ($d === 0) { break; } while ($x > $prevX) { $result[] = new \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem(\_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_REMOVE, $a[$x - 1], null); $x--; } while ($y > $prevY) { $result[] = new \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem(\_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_ADD, null, $b[$y - 1]); $y--; } } return \array_reverse($result); } /** * Coalesce equal-length sequences of remove+add into a replace operation. * * @param DiffElem[] $diff * @return DiffElem[] */ private function coalesceReplacements(array $diff) { $newDiff = []; $c = \count($diff); for ($i = 0; $i < $c; $i++) { $diffType = $diff[$i]->type; if ($diffType !== \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_REMOVE) { $newDiff[] = $diff[$i]; continue; } $j = $i; while ($j < $c && $diff[$j]->type === \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_REMOVE) { $j++; } $k = $j; while ($k < $c && $diff[$k]->type === \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_ADD) { $k++; } if ($j - $i === $k - $j) { $len = $j - $i; for ($n = 0; $n < $len; $n++) { $newDiff[] = new \_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem(\_HumbugBoxd02f763d3c56\PhpParser\Internal\DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new); } } else { for (; $i < $k; $i++) { $newDiff[] = $diff[$i]; } } $i = $k - 1; } return $newDiff; } } tokens = $tokens; $this->indentMap = $this->calcIndentMap(); } /** * Whether the given position is immediately surrounded by parenthesis. * * @param int $startPos Start position * @param int $endPos End position * * @return bool */ public function haveParens(int $startPos, int $endPos) : bool { return $this->haveTokenImmediatelyBefore($startPos, '(') && $this->haveTokenImmediatelyAfter($endPos, ')'); } /** * Whether the given position is immediately surrounded by braces. * * @param int $startPos Start position * @param int $endPos End position * * @return bool */ public function haveBraces(int $startPos, int $endPos) : bool { return $this->haveTokenImmediatelyBefore($startPos, '{') && $this->haveTokenImmediatelyAfter($endPos, '}'); } /** * Check whether the position is directly preceded by a certain token type. * * During this check whitespace and comments are skipped. * * @param int $pos Position before which the token should occur * @param int|string $expectedTokenType Token to check for * * @return bool Whether the expected token was found */ public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool { $tokens = $this->tokens; $pos--; for (; $pos >= 0; $pos--) { $tokenType = $tokens[$pos][0]; if ($tokenType === $expectedTokenType) { return \true; } if ($tokenType !== \T_WHITESPACE && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { break; } } return \false; } /** * Check whether the position is directly followed by a certain token type. * * During this check whitespace and comments are skipped. * * @param int $pos Position after which the token should occur * @param int|string $expectedTokenType Token to check for * * @return bool Whether the expected token was found */ public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType) : bool { $tokens = $this->tokens; $pos++; for (; $pos < \count($tokens); $pos++) { $tokenType = $tokens[$pos][0]; if ($tokenType === $expectedTokenType) { return \true; } if ($tokenType !== \T_WHITESPACE && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { break; } } return \false; } public function skipLeft(int $pos, $skipTokenType) { $tokens = $this->tokens; $pos = $this->skipLeftWhitespace($pos); if ($skipTokenType === \T_WHITESPACE) { return $pos; } if ($tokens[$pos][0] !== $skipTokenType) { // Shouldn't happen. The skip token MUST be there throw new \Exception('Encountered unexpected token'); } $pos--; return $this->skipLeftWhitespace($pos); } public function skipRight(int $pos, $skipTokenType) { $tokens = $this->tokens; $pos = $this->skipRightWhitespace($pos); if ($skipTokenType === \T_WHITESPACE) { return $pos; } if ($tokens[$pos][0] !== $skipTokenType) { // Shouldn't happen. The skip token MUST be there throw new \Exception('Encountered unexpected token'); } $pos++; return $this->skipRightWhitespace($pos); } /** * Return first non-whitespace token position smaller or equal to passed position. * * @param int $pos Token position * @return int Non-whitespace token position */ public function skipLeftWhitespace(int $pos) { $tokens = $this->tokens; for (; $pos >= 0; $pos--) { $type = $tokens[$pos][0]; if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { break; } } return $pos; } /** * Return first non-whitespace position greater or equal to passed position. * * @param int $pos Token position * @return int Non-whitespace token position */ public function skipRightWhitespace(int $pos) { $tokens = $this->tokens; for ($count = \count($tokens); $pos < $count; $pos++) { $type = $tokens[$pos][0]; if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { break; } } return $pos; } public function findRight(int $pos, $findTokenType) { $tokens = $this->tokens; for ($count = \count($tokens); $pos < $count; $pos++) { $type = $tokens[$pos][0]; if ($type === $findTokenType) { return $pos; } } return -1; } /** * Whether the given position range contains a certain token type. * * @param int $startPos Starting position (inclusive) * @param int $endPos Ending position (exclusive) * @param int|string $tokenType Token type to look for * @return bool Whether the token occurs in the given range */ public function haveTokenInRange(int $startPos, int $endPos, $tokenType) { $tokens = $this->tokens; for ($pos = $startPos; $pos < $endPos; $pos++) { if ($tokens[$pos][0] === $tokenType) { return \true; } } return \false; } public function haveBracesInRange(int $startPos, int $endPos) { return $this->haveTokenInRange($startPos, $endPos, '{') || $this->haveTokenInRange($startPos, $endPos, '}'); } /** * Get indentation before token position. * * @param int $pos Token position * * @return int Indentation depth (in spaces) */ public function getIndentationBefore(int $pos) : int { return $this->indentMap[$pos]; } /** * Get the code corresponding to a token offset range, optionally adjusted for indentation. * * @param int $from Token start position (inclusive) * @param int $to Token end position (exclusive) * @param int $indent By how much the code should be indented (can be negative as well) * * @return string Code corresponding to token range, adjusted for indentation */ public function getTokenCode(int $from, int $to, int $indent) : string { $tokens = $this->tokens; $result = ''; for ($pos = $from; $pos < $to; $pos++) { $token = $tokens[$pos]; if (\is_array($token)) { $type = $token[0]; $content = $token[1]; if ($type === \T_CONSTANT_ENCAPSED_STRING || $type === \T_ENCAPSED_AND_WHITESPACE) { $result .= $content; } else { // TODO Handle non-space indentation if ($indent < 0) { $result .= \str_replace("\n" . \str_repeat(" ", -$indent), "\n", $content); } elseif ($indent > 0) { $result .= \str_replace("\n", "\n" . \str_repeat(" ", $indent), $content); } else { $result .= $content; } } } else { $result .= $token; } } return $result; } /** * Precalculate the indentation at every token position. * * @return int[] Token position to indentation map */ private function calcIndentMap() { $indentMap = []; $indent = 0; foreach ($this->tokens as $token) { $indentMap[] = $indent; if ($token[0] === \T_WHITESPACE) { $content = $token[1]; $newlinePos = \strrpos($content, "\n"); if (\false !== $newlinePos) { $indent = \strlen($content) - $newlinePos - 1; } } } // Add a sentinel for one past end of the file $indentMap[] = $indent; return $indentMap; } } type = $type; $this->old = $old; $this->new = $new; } } targetPhpVersion = $options['phpVersion'] ?? \_HumbugBoxd02f763d3c56\PhpParser\Lexer\Emulative::PHP_8_0; unset($options['phpVersion']); parent::__construct($options); $emulators = [new \_HumbugBoxd02f763d3c56\PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator(), new \_HumbugBoxd02f763d3c56\PhpParser\Lexer\TokenEmulator\FnTokenEmulator(), new \_HumbugBoxd02f763d3c56\PhpParser\Lexer\TokenEmulator\MatchTokenEmulator(), new \_HumbugBoxd02f763d3c56\PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator(), new \_HumbugBoxd02f763d3c56\PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator(), new \_HumbugBoxd02f763d3c56\PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator(), new \_HumbugBoxd02f763d3c56\PhpParser\Lexer\TokenEmulator\AttributeEmulator()]; // Collect emulators that are relevant for the PHP version we're running // and the PHP version we're targeting for emulation. foreach ($emulators as $emulator) { $emulatorPhpVersion = $emulator->getPhpVersion(); if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) { $this->emulators[] = $emulator; } else { if ($this->isReverseEmulationNeeded($emulatorPhpVersion)) { $this->emulators[] = new \_HumbugBoxd02f763d3c56\PhpParser\Lexer\TokenEmulator\ReverseEmulator($emulator); } } } } public function startLexing(string $code, \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler $errorHandler = null) { $emulators = \array_filter($this->emulators, function ($emulator) use($code) { return $emulator->isEmulationNeeded($code); }); if (empty($emulators)) { // Nothing to emulate, yay parent::startLexing($code, $errorHandler); return; } $this->patches = []; foreach ($emulators as $emulator) { $code = $emulator->preprocessCode($code, $this->patches); } $collector = new \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler\Collecting(); parent::startLexing($code, $collector); $this->sortPatches(); $this->fixupTokens(); $errors = $collector->getErrors(); if (!empty($errors)) { $this->fixupErrors($errors); foreach ($errors as $error) { $errorHandler->handleError($error); } } foreach ($emulators as $emulator) { $this->tokens = $emulator->emulate($code, $this->tokens); } } private function isForwardEmulationNeeded(string $emulatorPhpVersion) : bool { return \version_compare(\PHP_VERSION, $emulatorPhpVersion, '<') && \version_compare($this->targetPhpVersion, $emulatorPhpVersion, '>='); } private function isReverseEmulationNeeded(string $emulatorPhpVersion) : bool { return \version_compare(\PHP_VERSION, $emulatorPhpVersion, '>=') && \version_compare($this->targetPhpVersion, $emulatorPhpVersion, '<'); } private function sortPatches() { // Patches may be contributed by different emulators. // Make sure they are sorted by increasing patch position. \usort($this->patches, function ($p1, $p2) { return $p1[0] <=> $p2[0]; }); } private function fixupTokens() { if (\count($this->patches) === 0) { return; } // Load first patch $patchIdx = 0; list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; // We use a manual loop over the tokens, because we modify the array on the fly $pos = 0; for ($i = 0, $c = \count($this->tokens); $i < $c; $i++) { $token = $this->tokens[$i]; if (\is_string($token)) { if ($patchPos === $pos) { // Only support replacement for string tokens. \assert($patchType === 'replace'); $this->tokens[$i] = $patchText; // Fetch the next patch $patchIdx++; if ($patchIdx >= \count($this->patches)) { // No more patches, we're done return; } list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; } $pos += \strlen($token); continue; } $len = \strlen($token[1]); $posDelta = 0; while ($patchPos >= $pos && $patchPos < $pos + $len) { $patchTextLen = \strlen($patchText); if ($patchType === 'remove') { if ($patchPos === $pos && $patchTextLen === $len) { // Remove token entirely \array_splice($this->tokens, $i, 1, []); $i--; $c--; } else { // Remove from token string $this->tokens[$i][1] = \substr_replace($token[1], '', $patchPos - $pos + $posDelta, $patchTextLen); $posDelta -= $patchTextLen; } } elseif ($patchType === 'add') { // Insert into the token string $this->tokens[$i][1] = \substr_replace($token[1], $patchText, $patchPos - $pos + $posDelta, 0); $posDelta += $patchTextLen; } else { if ($patchType === 'replace') { // Replace inside the token string $this->tokens[$i][1] = \substr_replace($token[1], $patchText, $patchPos - $pos + $posDelta, $patchTextLen); } else { \assert(\false); } } // Fetch the next patch $patchIdx++; if ($patchIdx >= \count($this->patches)) { // No more patches, we're done return; } list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; // Multiple patches may apply to the same token. Reload the current one to check // If the new patch applies $token = $this->tokens[$i]; } $pos += $len; } // A patch did not apply \assert(\false); } /** * Fixup line and position information in errors. * * @param Error[] $errors */ private function fixupErrors(array $errors) { foreach ($errors as $error) { $attrs = $error->getAttributes(); $posDelta = 0; $lineDelta = 0; foreach ($this->patches as $patch) { list($patchPos, $patchType, $patchText) = $patch; if ($patchPos >= $attrs['startFilePos']) { // No longer relevant break; } if ($patchType === 'add') { $posDelta += \strlen($patchText); $lineDelta += \substr_count($patchText, "\n"); } else { if ($patchType === 'remove') { $posDelta -= \strlen($patchText); $lineDelta -= \substr_count($patchText, "\n"); } } } $attrs['startFilePos'] += $posDelta; $attrs['endFilePos'] += $posDelta; $attrs['startLine'] += $lineDelta; $attrs['endLine'] += $lineDelta; $error->setAttributes($attrs); } } } resolveIntegerOrFloatToken($match); $newTokens = [[$tokenKind, $match, $token[2]]]; $numTokens = 1; $len = $tokenLen; while ($matchLen > $len) { $nextToken = $tokens[$i + $numTokens]; $nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken; $nextTokenLen = \strlen($nextTokenText); $numTokens++; if ($matchLen < $len + $nextTokenLen) { // Split trailing characters into a partial token. \assert(\is_array($nextToken), "Partial token should be an array token"); $partialText = \substr($nextTokenText, $matchLen - $len); $newTokens[] = [$nextToken[0], $partialText, $nextToken[2]]; break; } $len += $nextTokenLen; } \array_splice($tokens, $i, $numTokens, $newTokens); $c -= $numTokens - \count($newTokens); $codeOffset += $matchLen; } return $tokens; } private function resolveIntegerOrFloatToken(string $str) : int { $str = \str_replace('_', '', $str); if (\stripos($str, '0b') === 0) { $num = \bindec($str); } elseif (\stripos($str, '0x') === 0) { $num = \hexdec($str); } elseif (\stripos($str, '0') === 0 && \ctype_digit($str)) { $num = \octdec($str); } else { $num = +$str; } return \is_float($num) ? \T_DNUMBER : \T_LNUMBER; } public function reverseEmulate(string $code, array $tokens) : array { // Numeric separators were not legal code previously, don't bother. return $tokens; } } emulator = $emulator; } public function getPhpVersion() : string { return $this->emulator->getPhpVersion(); } public function isEmulationNeeded(string $code) : bool { return $this->emulator->isEmulationNeeded($code); } public function emulate(string $code, array $tokens) : array { return $this->emulator->reverseEmulate($code, $tokens); } public function reverseEmulate(string $code, array $tokens) : array { return $this->emulator->emulate($code, $tokens); } public function preprocessCode(string $code, array &$patches) : string { return $code; } } \h*)\2(?![a-zA-Z0-9_\x80-\xff])(?(?:;?[\r\n])?)/x REGEX; public function getPhpVersion() : string { return \_HumbugBoxd02f763d3c56\PhpParser\Lexer\Emulative::PHP_7_3; } public function isEmulationNeeded(string $code) : bool { return \strpos($code, '<<<') !== \false; } public function emulate(string $code, array $tokens) : array { // Handled by preprocessing + fixup. return $tokens; } public function reverseEmulate(string $code, array $tokens) : array { // Not supported. return $tokens; } public function preprocessCode(string $code, array &$patches) : string { if (!\preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, \PREG_SET_ORDER | \PREG_OFFSET_CAPTURE)) { // No heredoc/nowdoc found return $code; } // Keep track of how much we need to adjust string offsets due to the modifications we // already made $posDelta = 0; foreach ($matches as $match) { $indentation = $match['indentation'][0]; $indentationStart = $match['indentation'][1]; $separator = $match['separator'][0]; $separatorStart = $match['separator'][1]; if ($indentation === '' && $separator !== '') { // Ordinary heredoc/nowdoc continue; } if ($indentation !== '') { // Remove indentation $indentationLen = \strlen($indentation); $code = \substr_replace($code, '', $indentationStart + $posDelta, $indentationLen); $patches[] = [$indentationStart + $posDelta, 'add', $indentation]; $posDelta -= $indentationLen; } if ($separator === '') { // Insert newline as separator $code = \substr_replace($code, "\n", $separatorStart + $posDelta, 0); $patches[] = [$separatorStart + $posDelta, 'remove', "\n"]; $posDelta += 1; } } return $code; } } ') !== \false; } public function emulate(string $code, array $tokens) : array { // We need to manually iterate and manage a count because we'll change // the tokens array on the way $line = 1; for ($i = 0, $c = \count($tokens); $i < $c; ++$i) { if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) { \array_splice($tokens, $i, 2, [[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line]]); $c--; continue; } // Handle ?-> inside encapsed string. if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1]) && $tokens[$i - 1][0] === \T_VARIABLE && \preg_match('/^\\?->([a-zA-Z_\\x80-\\xff][a-zA-Z0-9_\\x80-\\xff]*)/', $tokens[$i][1], $matches)) { $replacement = [[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line], [\T_STRING, $matches[1], $line]]; if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) { $replacement[] = [\T_ENCAPSED_AND_WHITESPACE, \substr($tokens[$i][1], \strlen($matches[0])), $line]; } \array_splice($tokens, $i, 1, $replacement); $c += \count($replacement) - 1; continue; } if (\is_array($tokens[$i])) { $line += \substr_count($tokens[$i][1], "\n"); } } return $tokens; } public function reverseEmulate(string $code, array $tokens) : array { // ?-> was not valid code previously, don't bother. return $tokens; } } getKeywordString()) !== \false; } public function emulate(string $code, array $tokens) : array { $keywordString = $this->getKeywordString(); foreach ($tokens as $i => $token) { if ($token[0] === \T_STRING && \strtolower($token[1]) === $keywordString) { $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i); if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === \T_OBJECT_OPERATOR) { continue; } $tokens[$i][0] = $this->getKeywordToken(); } } return $tokens; } /** * @param mixed[] $tokens * @return mixed[]|null */ private function getPreviousNonSpaceToken(array $tokens, int $start) { for ($i = $start - 1; $i >= 0; --$i) { if ($tokens[$i][0] === \T_WHITESPACE) { continue; } return $tokens[$i]; } return null; } public function reverseEmulate(string $code, array $tokens) : array { $keywordToken = $this->getKeywordToken(); foreach ($tokens as $i => $token) { if ($token[0] === $keywordToken) { $tokens[$i][0] = \T_STRING; } } return $tokens; } } addVisitor($visitor); $traverser->traverse($nodes); return $visitor->getFoundNodes(); } /** * Find all nodes that are instances of a certain class. * * @param Node|Node[] $nodes Single node or array of nodes to search in * @param string $class Class name * * @return Node[] Found nodes (all instances of $class) */ public function findInstanceOf($nodes, string $class) : array { return $this->find($nodes, function ($node) use($class) { return $node instanceof $class; }); } /** * Find first node satisfying a filter callback. * * @param Node|Node[] $nodes Single node or array of nodes to search in * @param callable $filter Filter callback: function(Node $node) : bool * * @return null|Node Found node (or null if none found) */ public function findFirst($nodes, callable $filter) { if (!\is_array($nodes)) { $nodes = [$nodes]; } $visitor = new \_HumbugBoxd02f763d3c56\PhpParser\NodeVisitor\FirstFindingVisitor($filter); $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $traverser->addVisitor($visitor); $traverser->traverse($nodes); return $visitor->getFoundNode(); } /** * Find first node that is an instance of a certain class. * * @param Node|Node[] $nodes Single node or array of nodes to search in * @param string $class Class name * * @return null|Node Found node, which is an instance of $class (or null if none found) */ public function findFirstInstanceOf($nodes, string $class) { return $this->findFirst($nodes, function ($node) use($class) { return $node instanceof $class; }); } } getNode(); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { return $node; } throw new \LogicException('Expected node or builder object'); } /** * Normalizes a node to a statement. * * Expressions are wrapped in a Stmt\Expression node. * * @param Node|Builder $node The node to normalize * * @return Stmt The normalized statement node */ public static function normalizeStmt($node) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt { $node = self::normalizeNode($node); if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt) { return $node; } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression($node); } throw new \LogicException('Expected statement or expression node'); } /** * Normalizes strings to Identifier. * * @param string|Identifier $name The identifier to normalize * * @return Identifier The normalized identifier */ public static function normalizeIdentifier($name) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier { if ($name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { return $name; } if (\is_string($name)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name); } throw new \LogicException('_HumbugBoxd02f763d3c56\\Expected string or instance of Node\\Identifier'); } /** * Normalizes strings to Identifier, also allowing expressions. * * @param string|Identifier|Expr $name The identifier to normalize * * @return Identifier|Expr The normalized identifier or expression */ public static function normalizeIdentifierOrExpr($name) { if ($name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier || $name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { return $name; } if (\is_string($name)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($name); } throw new \LogicException('_HumbugBoxd02f763d3c56\\Expected string or instance of Node\\Identifier or Node\\Expr'); } /** * Normalizes a name: Converts string names to Name nodes. * * @param Name|string $name The name to normalize * * @return Name The normalized name */ public static function normalizeName($name) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Name { return self::normalizeNameCommon($name, \false); } /** * Normalizes a name: Converts string names to Name nodes, while also allowing expressions. * * @param Expr|Name|string $name The name to normalize * * @return Name|Expr The normalized name or expression */ public static function normalizeNameOrExpr($name) { return self::normalizeNameCommon($name, \true); } /** * Normalizes a name: Converts string names to Name nodes, optionally allowing expressions. * * @param Expr|Name|string $name The name to normalize * @param bool $allowExpr Whether to also allow expressions * * @return Name|Expr The normalized name, or expression (if allowed) */ private static function normalizeNameCommon($name, bool $allowExpr) { if ($name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { return $name; } elseif (\is_string($name)) { if (!$name) { throw new \LogicException('Name cannot be empty'); } if ($name[0] === '\\') { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified(\substr($name, 1)); } elseif (0 === \strpos($name, 'namespace\\')) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\Relative(\substr($name, \strlen('namespace\\'))); } else { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($name); } } if ($allowExpr) { if ($name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { return $name; } throw new \LogicException('_HumbugBoxd02f763d3c56\\Name must be a string or an instance of Node\\Name or Node\\Expr'); } else { throw new \LogicException('_HumbugBoxd02f763d3c56\\Name must be a string or an instance of Node\\Name'); } } /** * Normalizes a type: Converts plain-text type names into proper AST representation. * * In particular, builtin types become Identifiers, custom types become Names and nullables * are wrapped in NullableType nodes. * * @param string|Name|Identifier|NullableType|UnionType $type The type to normalize * * @return Name|Identifier|NullableType|UnionType The normalized type */ public static function normalizeType($type) { if (!\is_string($type)) { if (!$type instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && !$type instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && !$type instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType && !$type instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\UnionType) { throw new \LogicException('Type must be a string, or an instance of Name, Identifier, NullableType or UnionType'); } return $type; } $nullable = \false; if (\strlen($type) > 0 && $type[0] === '?') { $nullable = \true; $type = \substr($type, 1); } $builtinTypes = ['array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object', 'mixed']; $lowerType = \strtolower($type); if (\in_array($lowerType, $builtinTypes)) { $type = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($lowerType); } else { $type = self::normalizeName($type); } if ($nullable && (string) $type === 'void') { throw new \LogicException('void type cannot be nullable'); } if ($nullable && (string) $type === 'mixed') { throw new \LogicException('mixed type cannot be nullable'); } return $nullable ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType($type) : $type; } /** * Normalizes a value: Converts nulls, booleans, integers, * floats, strings and arrays into their respective nodes * * @param Node\Expr|bool|null|int|float|string|array $value The value to normalize * * @return Expr The normalized value */ public static function normalizeValue($value) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr { if ($value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { return $value; } elseif (\is_null($value)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('null')); } elseif (\is_bool($value)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($value ? 'true' : 'false')); } elseif (\is_int($value)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber($value); } elseif (\is_float($value)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber($value); } elseif (\is_string($value)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($value); } elseif (\is_array($value)) { $items = []; $lastKey = -1; foreach ($value as $itemKey => $itemValue) { // for consecutive, numeric keys don't generate keys if (null !== $lastKey && ++$lastKey === $itemKey) { $items[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem(self::normalizeValue($itemValue)); } else { $lastKey = null; $items[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem(self::normalizeValue($itemValue), self::normalizeValue($itemKey)); } } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($items); } else { throw new \LogicException('Invalid value'); } } /** * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc. * * @param Comment\Doc|string $docComment The doc comment to normalize * * @return Comment\Doc The normalized doc comment */ public static function normalizeDocComment($docComment) : \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc { if ($docComment instanceof \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc) { return $docComment; } elseif (\is_string($docComment)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc($docComment); } else { throw new \LogicException('_HumbugBoxd02f763d3c56\\Doc comment must be a string or an instance of PhpParser\\Comment\\Doc'); } } /** * Adds a modifier and returns new modifier bitmask. * * @param int $modifiers Existing modifiers * @param int $modifier Modifier to set * * @return int New modifiers */ public static function addModifier(int $modifiers, int $modifier) : int { \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::verifyModifier($modifiers, $modifier); return $modifiers | $modifier; } } filterCallback = $filterCallback; } /** * Get found nodes satisfying the filter callback. * * Nodes are returned in pre-order. * * @return Node[] Found nodes */ public function getFoundNodes() : array { return $this->foundNodes; } public function beforeTraverse(array $nodes) { $this->foundNodes = []; return null; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { $filterCallback = $this->filterCallback; if ($filterCallback($node)) { $this->foundNodes[] = $node; } return null; } } nameContext = new \_HumbugBoxd02f763d3c56\PhpParser\NameContext($errorHandler ?? new \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler\Throwing()); $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? \false; $this->replaceNodes = $options['replaceNodes'] ?? \true; } /** * Get name resolution context. * * @return NameContext */ public function getNameContext() : \_HumbugBoxd02f763d3c56\PhpParser\NameContext { return $this->nameContext; } public function beforeTraverse(array $nodes) { $this->nameContext->startNamespace(); return null; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { $this->nameContext->startNamespace($node->name); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type, null); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type, $node->prefix); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { if (null !== $node->extends) { $node->extends = $this->resolveClassName($node->extends); } foreach ($node->implements as &$interface) { $interface = $this->resolveClassName($interface); } $this->resolveAttrGroups($node); if (null !== $node->name) { $this->addNamespacedName($node); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_) { foreach ($node->extends as &$interface) { $interface = $this->resolveClassName($interface); } $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_) { $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_) { $this->resolveSignature($node); $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { $this->resolveSignature($node); $this->resolveAttrGroups($node); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { if (null !== $node->type) { $node->type = $this->resolveType($node->type); } $this->resolveAttrGroups($node); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_) { foreach ($node->consts as $const) { $this->addNamespacedName($const); } } else { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst) { $this->resolveAttrGroups($node); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_) { if ($node->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $node->class = $this->resolveClassName($node->class); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Catch_) { foreach ($node->types as &$type) { $type = $this->resolveClassName($type); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { if ($node->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $node->name = $this->resolveName($node->name, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { $node->name = $this->resolveName($node->name, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { foreach ($node->traits as &$trait) { $trait = $this->resolveClassName($trait); } foreach ($node->adaptations as $adaptation) { if (null !== $adaptation->trait) { $adaptation->trait = $this->resolveClassName($adaptation->trait); } if ($adaptation instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Precedence) { foreach ($adaptation->insteadof as &$insteadof) { $insteadof = $this->resolveClassName($insteadof); } } } } } return null; } private function addAlias(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse $use, $type, \_HumbugBoxd02f763d3c56\PhpParser\Node\Name $prefix = null) { // Add prefix for group uses $name = $prefix ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Name::concat($prefix, $use->name) : $use->name; // Type is determined either by individual element or whole use declaration $type |= $use->type; $this->nameContext->addAlias($name, (string) $use->getAlias(), $type, $use->getAttributes()); } /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ private function resolveSignature($node) { foreach ($node->params as $param) { $param->type = $this->resolveType($param->type); $this->resolveAttrGroups($param); } $node->returnType = $this->resolveType($node->returnType); } private function resolveType($node) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { return $this->resolveClassName($node); } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType) { $node->type = $this->resolveType($node->type); return $node; } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\UnionType) { foreach ($node->types as &$type) { $type = $this->resolveType($type); } return $node; } return $node; } /** * Resolve name, according to name resolver options. * * @param Name $name Function or constant name to resolve * @param int $type One of Stmt\Use_::TYPE_* * * @return Name Resolved name, or original name with attribute */ protected function resolveName(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $name, int $type) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Name { if (!$this->replaceNodes) { $resolvedName = $this->nameContext->getResolvedName($name, $type); if (null !== $resolvedName) { $name->setAttribute('resolvedName', $resolvedName); } else { $name->setAttribute('namespacedName', \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified::concat($this->nameContext->getNamespace(), $name, $name->getAttributes())); } return $name; } if ($this->preserveOriginalNames) { // Save the original name $originalName = $name; $name = clone $originalName; $name->setAttribute('originalName', $originalName); } $resolvedName = $this->nameContext->getResolvedName($name, $type); if (null !== $resolvedName) { return $resolvedName; } // unqualified names inside a namespace cannot be resolved at compile-time // add the namespaced version of the name as an attribute $name->setAttribute('namespacedName', \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified::concat($this->nameContext->getNamespace(), $name, $name->getAttributes())); return $name; } protected function resolveClassName(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $name) { return $this->resolveName($name, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL); } protected function addNamespacedName(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { $node->namespacedName = \_HumbugBoxd02f763d3c56\PhpParser\Node\Name::concat($this->nameContext->getNamespace(), (string) $node->name); } protected function resolveAttrGroups(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { foreach ($node->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { $attr->name = $this->resolveClassName($attr->name); } } } } $node->getAttribute('parent'), the previous * node can be accessed through $node->getAttribute('previous'), * and the next node can be accessed through $node->getAttribute('next'). */ final class NodeConnectingVisitor extends \_HumbugBoxd02f763d3c56\PhpParser\NodeVisitorAbstract { /** * @var Node[] */ private $stack = []; /** * @var ?Node */ private $previous; public function beforeTraverse(array $nodes) { $this->stack = []; $this->previous = null; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { if (!empty($this->stack)) { $node->setAttribute('parent', $this->stack[\count($this->stack) - 1]); } if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) { $node->setAttribute('previous', $this->previous); $this->previous->setAttribute('next', $node); } $this->stack[] = $node; } public function leaveNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { $this->previous = $node; \array_pop($this->stack); } } $node->getAttribute('parent'). */ final class ParentConnectingVisitor extends \_HumbugBoxd02f763d3c56\PhpParser\NodeVisitorAbstract { /** * @var Node[] */ private $stack = []; public function beforeTraverse(array $nodes) { $this->stack = []; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { if (!empty($this->stack)) { $node->setAttribute('parent', $this->stack[\count($this->stack) - 1]); } $this->stack[] = $node; } public function leaveNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { \array_pop($this->stack); } } filterCallback = $filterCallback; } /** * Get found node satisfying the filter callback. * * Returns null if no node satisfies the filter callback. * * @return null|Node Found node (or null if not found) */ public function getFoundNode() { return $this->foundNode; } public function beforeTraverse(array $nodes) { $this->foundNode = null; return null; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { $filterCallback = $this->filterCallback; if ($filterCallback($node)) { $this->foundNode = $node; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } return null; } } setAttribute('origNode', $origNode); return $node; } } addStmt($stmt); } return $this; } /** * Sets doc comment for the declaration. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes['comments'] = [\_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeDocComment($docComment)]; return $this; } } name = $name; } /** * Makes the method public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC); return $this; } /** * Makes the method protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED); return $this; } /** * Makes the method private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE); return $this; } /** * Makes the method static. * * @return $this The builder instance (for fluid interface) */ public function makeStatic() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC); return $this; } /** * Makes the method abstract. * * @return $this The builder instance (for fluid interface) */ public function makeAbstract() { if (!empty($this->stmts)) { throw new \LogicException('Cannot make method with statements abstract'); } $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT); $this->stmts = null; // abstract methods don't have statements return $this; } /** * Makes the method final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL); return $this; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { if (null === $this->stmts) { throw new \LogicException('Cannot add statements to an abstract method'); } $this->stmts[] = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeStmt($stmt); return $this; } /** * Returns the built method node. * * @return Stmt\ClassMethod The built method node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod($this->name, ['flags' => $this->flags, 'byRef' => $this->returnByRef, 'params' => $this->params, 'returnType' => $this->returnType, 'stmts' => $this->stmts], $this->attributes); } } name = null !== $name ? \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeName($name) : null; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $this->stmts[] = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeStmt($stmt); return $this; } /** * Returns the built node. * * @return Node The built node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_($this->name, $this->stmts, $this->attributes); } } type = self::TYPE_UNDEFINED; $this->trait = \is_null($trait) ? null : \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeName($trait); $this->method = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeIdentifier($method); } /** * Sets alias of method. * * @param Node\Identifier|string $alias Alias for adaptated method * * @return $this The builder instance (for fluid interface) */ public function as($alias) { if ($this->type === self::TYPE_UNDEFINED) { $this->type = self::TYPE_ALIAS; } if ($this->type !== self::TYPE_ALIAS) { throw new \LogicException('Cannot set alias for not alias adaptation buider'); } $this->alias = $alias; return $this; } /** * Sets adaptated method public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->setModifier(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC); return $this; } /** * Sets adaptated method protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->setModifier(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED); return $this; } /** * Sets adaptated method private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->setModifier(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE); return $this; } /** * Adds overwritten traits. * * @param Node\Name|string ...$traits Traits for overwrite * * @return $this The builder instance (for fluid interface) */ public function insteadof(...$traits) { if ($this->type === self::TYPE_UNDEFINED) { if (\is_null($this->trait)) { throw new \LogicException('Precedence adaptation must have trait'); } $this->type = self::TYPE_PRECEDENCE; } if ($this->type !== self::TYPE_PRECEDENCE) { throw new \LogicException('Cannot add overwritten traits for not precedence adaptation buider'); } foreach ($traits as $trait) { $this->insteadof[] = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeName($trait); } return $this; } protected function setModifier(int $modifier) { if ($this->type === self::TYPE_UNDEFINED) { $this->type = self::TYPE_ALIAS; } if ($this->type !== self::TYPE_ALIAS) { throw new \LogicException('Cannot set access modifier for not alias adaptation buider'); } if (\is_null($this->modifier)) { $this->modifier = $modifier; } else { throw new \LogicException('Multiple access type modifiers are not allowed'); } } /** * Returns the built node. * * @return Node The built node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { switch ($this->type) { case self::TYPE_ALIAS: return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias); case self::TYPE_PRECEDENCE: return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof); default: throw new \LogicException('Type of adaptation is not defined'); } } } name = $name; } /** * Sets default value for the parameter. * * @param mixed $value Default value to use * * @return $this The builder instance (for fluid interface) */ public function setDefault($value) { $this->default = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeValue($value); return $this; } /** * Sets type for the parameter. * * @param string|Node\Name|Node\NullableType|Node\UnionType $type Parameter type * * @return $this The builder instance (for fluid interface) */ public function setType($type) { $this->type = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeType($type); if ($this->type == 'void') { throw new \LogicException('Parameter type cannot be void'); } return $this; } /** * Sets type for the parameter. * * @param string|Node\Name|Node\NullableType|Node\UnionType $type Parameter type * * @return $this The builder instance (for fluid interface) * * @deprecated Use setType() instead */ public function setTypeHint($type) { return $this->setType($type); } /** * Make the parameter accept the value by reference. * * @return $this The builder instance (for fluid interface) */ public function makeByRef() { $this->byRef = \true; return $this; } /** * Make the parameter variadic * * @return $this The builder instance (for fluid interface) */ public function makeVariadic() { $this->variadic = \true; return $this; } /** * Returns the built parameter node. * * @return Node\Param The built parameter node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Param(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->name), $this->default, $this->type, $this->byRef, $this->variadic); } } name = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeName($name); $this->type = $type; } /** * Sets alias for used name. * * @param string $alias Alias to use (last component of full name by default) * * @return $this The builder instance (for fluid interface) */ public function as(string $alias) { $this->alias = $alias; return $this; } /** * Returns the built node. * * @return Node The built node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_([new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse($this->name, $this->alias)], $this->type); } } name = $name; } /** * Extends a class. * * @param Name|string $class Name of class to extend * * @return $this The builder instance (for fluid interface) */ public function extend($class) { $this->extends = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeName($class); return $this; } /** * Implements one or more interfaces. * * @param Name|string ...$interfaces Names of interfaces to implement * * @return $this The builder instance (for fluid interface) */ public function implement(...$interfaces) { foreach ($interfaces as $interface) { $this->implements[] = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeName($interface); } return $this; } /** * Makes the class abstract. * * @return $this The builder instance (for fluid interface) */ public function makeAbstract() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT); return $this; } /** * Makes the class final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL); return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeNode($stmt); $targets = [\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse::class => &$this->uses, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst::class => &$this->constants, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property::class => &$this->properties, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod::class => &$this->methods]; $class = \get_class($stmt); if (!isset($targets[$class])) { throw new \LogicException(\sprintf('Unexpected node of type "%s"', $stmt->getType())); } $targets[$class][] = $stmt; return $this; } /** * Returns the built class node. * * @return Stmt\Class_ The built class node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_($this->name, ['flags' => $this->flags, 'extends' => $this->extends, 'implements' => $this->implements, 'stmts' => \array_merge($this->uses, $this->constants, $this->properties, $this->methods)], $this->attributes); } } name = $name; } /** * Extends one or more interfaces. * * @param Name|string ...$interfaces Names of interfaces to extend * * @return $this The builder instance (for fluid interface) */ public function extend(...$interfaces) { foreach ($interfaces as $interface) { $this->extends[] = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeName($interface); } return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeNode($stmt); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst) { $this->constants[] = $stmt; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { // we erase all statements in the body of an interface method $stmt->stmts = null; $this->methods[] = $stmt; } else { throw new \LogicException(\sprintf('Unexpected node of type "%s"', $stmt->getType())); } return $this; } /** * Returns the built interface node. * * @return Stmt\Interface_ The built interface node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_($this->name, ['extends' => $this->extends, 'stmts' => \array_merge($this->constants, $this->methods)], $this->attributes); } } name = $name; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeNode($stmt); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { $this->properties[] = $stmt; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $this->methods[] = $stmt; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { $this->uses[] = $stmt; } else { throw new \LogicException(\sprintf('Unexpected node of type "%s"', $stmt->getType())); } return $this; } /** * Returns the built trait node. * * @return Stmt\Trait_ The built interface node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_($this->name, ['stmts' => \array_merge($this->uses, $this->properties, $this->methods)], $this->attributes); } } name = $name; } /** * Makes the property public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC); return $this; } /** * Makes the property protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED); return $this; } /** * Makes the property private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE); return $this; } /** * Makes the property static. * * @return $this The builder instance (for fluid interface) */ public function makeStatic() { $this->flags = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::addModifier($this->flags, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC); return $this; } /** * Sets default value for the property. * * @param mixed $value Default value to use * * @return $this The builder instance (for fluid interface) */ public function setDefault($value) { $this->default = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeValue($value); return $this; } /** * Sets doc comment for the property. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes = ['comments' => [\_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeDocComment($docComment)]]; return $this; } /** * Sets the property type for PHP 7.4+. * * @param string|Name|NullableType|Identifier $type * * @return $this */ public function setType($type) { $this->type = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeType($type); return $this; } /** * Returns the built class node. * * @return Stmt\Property The built property node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property($this->flags !== 0 ? $this->flags : \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC, [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\PropertyProperty($this->name, $this->default)], $this->attributes, $this->type); } } name = $name; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $this->stmts[] = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeStmt($stmt); return $this; } /** * Returns the built function node. * * @return Stmt\Function_ The built function node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_($this->name, ['byRef' => $this->returnByRef, 'params' => $this->params, 'returnType' => $this->returnType, 'stmts' => $this->stmts], $this->attributes); } } returnByRef = \true; return $this; } /** * Adds a parameter. * * @param Node\Param|Param $param The parameter to add * * @return $this The builder instance (for fluid interface) */ public function addParam($param) { $param = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeNode($param); if (!$param instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Param) { throw new \LogicException(\sprintf('Expected parameter node, got "%s"', $param->getType())); } $this->params[] = $param; return $this; } /** * Adds multiple parameters. * * @param array $params The parameters to add * * @return $this The builder instance (for fluid interface) */ public function addParams(array $params) { foreach ($params as $param) { $this->addParam($param); } return $this; } /** * Sets the return type for PHP 7. * * @param string|Node\Name|Node\NullableType $type One of array, callable, string, int, float, * bool, iterable, or a class/interface name. * * @return $this The builder instance (for fluid interface) */ public function setReturnType($type) { $this->returnType = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeType($type); return $this; } } and($trait); } } /** * Adds used trait. * * @param Node\Name|string $trait Trait name * * @return $this The builder instance (for fluid interface) */ public function and($trait) { $this->traits[] = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeName($trait); return $this; } /** * Adds trait adaptation. * * @param Stmt\TraitUseAdaptation|Builder\TraitUseAdaptation $adaptation Trait adaptation * * @return $this The builder instance (for fluid interface) */ public function with($adaptation) { $adaptation = \_HumbugBoxd02f763d3c56\PhpParser\BuilderHelpers::normalizeNode($adaptation); if (!$adaptation instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation) { throw new \LogicException('Adaptation must have type TraitUseAdaptation'); } $this->adaptations[] = $adaptation; return $this; } /** * Returns the built node. * * @return Node The built node */ public function getNode() : \_HumbugBoxd02f763d3c56\PhpParser\Node { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse($this->traits, $this->adaptations); } } attributes = $attributes; } /** * Gets line the node started in (alias of getStartLine). * * @return int Start line (or -1 if not available) */ public function getLine() : int { return $this->attributes['startLine'] ?? -1; } /** * Gets line the node started in. * * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default). * * @return int Start line (or -1 if not available) */ public function getStartLine() : int { return $this->attributes['startLine'] ?? -1; } /** * Gets the line the node ended in. * * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default). * * @return int End line (or -1 if not available) */ public function getEndLine() : int { return $this->attributes['endLine'] ?? -1; } /** * Gets the token offset of the first token that is part of this node. * * The offset is an index into the array returned by Lexer::getTokens(). * * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default). * * @return int Token start position (or -1 if not available) */ public function getStartTokenPos() : int { return $this->attributes['startTokenPos'] ?? -1; } /** * Gets the token offset of the last token that is part of this node. * * The offset is an index into the array returned by Lexer::getTokens(). * * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default). * * @return int Token end position (or -1 if not available) */ public function getEndTokenPos() : int { return $this->attributes['endTokenPos'] ?? -1; } /** * Gets the file offset of the first character that is part of this node. * * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default). * * @return int File start position (or -1 if not available) */ public function getStartFilePos() : int { return $this->attributes['startFilePos'] ?? -1; } /** * Gets the file offset of the last character that is part of this node. * * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default). * * @return int File end position (or -1 if not available) */ public function getEndFilePos() : int { return $this->attributes['endFilePos'] ?? -1; } /** * Gets all comments directly preceding this node. * * The comments are also available through the "comments" attribute. * * @return Comment[] */ public function getComments() : array { return $this->attributes['comments'] ?? []; } /** * Gets the doc comment of the node. * * @return null|Comment\Doc Doc comment object or null */ public function getDocComment() { $comments = $this->getComments(); for ($i = \count($comments) - 1; $i >= 0; $i--) { $comment = $comments[$i]; if ($comment instanceof \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc) { return $comment; } } return null; } /** * Sets the doc comment of the node. * * This will either replace an existing doc comment or add it to the comments array. * * @param Comment\Doc $docComment Doc comment to set */ public function setDocComment(\_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $docComment) { $comments = $this->getComments(); for ($i = \count($comments) - 1; $i >= 0; $i--) { if ($comments[$i] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc) { // Replace existing doc comment. $comments[$i] = $docComment; $this->setAttribute('comments', $comments); return; } } // Append new doc comment. $comments[] = $docComment; $this->setAttribute('comments', $comments); } public function setAttribute(string $key, $value) { $this->attributes[$key] = $value; } public function hasAttribute(string $key) : bool { return \array_key_exists($key, $this->attributes); } public function getAttribute(string $key, $default = null) { if (\array_key_exists($key, $this->attributes)) { return $this->attributes[$key]; } return $default; } public function getAttributes() : array { return $this->attributes; } public function setAttributes(array $attributes) { $this->attributes = $attributes; } /** * @return array */ public function jsonSerialize() : array { return ['nodeType' => $this->getType()] + \get_object_vars($this); } } rawMessage = $message; if (\is_array($attributes)) { $this->attributes = $attributes; } else { $this->attributes = ['startLine' => $attributes]; } $this->updateMessage(); } /** * Gets the error message * * @return string Error message */ public function getRawMessage() : string { return $this->rawMessage; } /** * Gets the line the error starts in. * * @return int Error start line */ public function getStartLine() : int { return $this->attributes['startLine'] ?? -1; } /** * Gets the line the error ends in. * * @return int Error end line */ public function getEndLine() : int { return $this->attributes['endLine'] ?? -1; } /** * Gets the attributes of the node/token the error occurred at. * * @return array */ public function getAttributes() : array { return $this->attributes; } /** * Sets the attributes of the node/token the error occurred at. * * @param array $attributes */ public function setAttributes(array $attributes) { $this->attributes = $attributes; $this->updateMessage(); } /** * Sets the line of the PHP file the error occurred in. * * @param string $message Error message */ public function setRawMessage(string $message) { $this->rawMessage = $message; $this->updateMessage(); } /** * Sets the line the error starts in. * * @param int $line Error start line */ public function setStartLine(int $line) { $this->attributes['startLine'] = $line; $this->updateMessage(); } /** * Returns whether the error has start and end column information. * * For column information enable the startFilePos and endFilePos in the lexer options. * * @return bool */ public function hasColumnInfo() : bool { return isset($this->attributes['startFilePos'], $this->attributes['endFilePos']); } /** * Gets the start column (1-based) into the line where the error started. * * @param string $code Source code of the file * @return int */ public function getStartColumn(string $code) : int { if (!$this->hasColumnInfo()) { throw new \RuntimeException('Error does not have column information'); } return $this->toColumn($code, $this->attributes['startFilePos']); } /** * Gets the end column (1-based) into the line where the error ended. * * @param string $code Source code of the file * @return int */ public function getEndColumn(string $code) : int { if (!$this->hasColumnInfo()) { throw new \RuntimeException('Error does not have column information'); } return $this->toColumn($code, $this->attributes['endFilePos']); } /** * Formats message including line and column information. * * @param string $code Source code associated with the error, for calculation of the columns * * @return string Formatted message */ public function getMessageWithColumnInfo(string $code) : string { return \sprintf('%s from %d:%d to %d:%d', $this->getRawMessage(), $this->getStartLine(), $this->getStartColumn($code), $this->getEndLine(), $this->getEndColumn($code)); } /** * Converts a file offset into a column. * * @param string $code Source code that $pos indexes into * @param int $pos 0-based position in $code * * @return int 1-based column (relative to start of line) */ private function toColumn(string $code, int $pos) : int { if ($pos > \strlen($code)) { throw new \RuntimeException('Invalid position information'); } $lineStartPos = \strrpos($code, "\n", $pos - \strlen($code)); if (\false === $lineStartPos) { $lineStartPos = -1; } return $pos - $lineStartPos; } /** * Updates the exception message after a change to rawMessage or rawLine. */ protected function updateMessage() { $this->message = $this->rawMessage; if (-1 === $this->getStartLine()) { $this->message .= ' on unknown line'; } else { $this->message .= ' on line ' . $this->getStartLine(); } } } text = $text; $this->startLine = $startLine; $this->startFilePos = $startFilePos; $this->startTokenPos = $startTokenPos; $this->endLine = $endLine; $this->endFilePos = $endFilePos; $this->endTokenPos = $endTokenPos; } /** * Gets the comment text. * * @return string The comment text (including comment delimiters like /*) */ public function getText() : string { return $this->text; } /** * Gets the line number the comment started on. * * @return int Line number (or -1 if not available) */ public function getStartLine() : int { return $this->startLine; } /** * Gets the file offset the comment started on. * * @return int File offset (or -1 if not available) */ public function getStartFilePos() : int { return $this->startFilePos; } /** * Gets the token offset the comment started on. * * @return int Token offset (or -1 if not available) */ public function getStartTokenPos() : int { return $this->startTokenPos; } /** * Gets the line number the comment ends on. * * @return int Line number (or -1 if not available) */ public function getEndLine() : int { return $this->endLine; } /** * Gets the file offset the comment ends on. * * @return int File offset (or -1 if not available) */ public function getEndFilePos() : int { return $this->endFilePos; } /** * Gets the token offset the comment ends on. * * @return int Token offset (or -1 if not available) */ public function getEndTokenPos() : int { return $this->endTokenPos; } /** * Gets the line number the comment started on. * * @deprecated Use getStartLine() instead * * @return int Line number */ public function getLine() : int { return $this->startLine; } /** * Gets the file offset the comment started on. * * @deprecated Use getStartFilePos() instead * * @return int File offset */ public function getFilePos() : int { return $this->startFilePos; } /** * Gets the token offset the comment started on. * * @deprecated Use getStartTokenPos() instead * * @return int Token offset */ public function getTokenPos() : int { return $this->startTokenPos; } /** * Gets the comment text. * * @return string The comment text (including comment delimiters like /*) */ public function __toString() : string { return $this->text; } /** * Gets the reformatted comment text. * * "Reformatted" here means that we try to clean up the whitespace at the * starts of the lines. This is necessary because we receive the comments * without trailing whitespace on the first line, but with trailing whitespace * on all subsequent lines. * * @return mixed|string */ public function getReformattedText() { $text = \trim($this->text); $newlinePos = \strpos($text, "\n"); if (\false === $newlinePos) { // Single line comments don't need further processing return $text; } elseif (\preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\\R\\s+\\*.*)+$)', $text)) { // Multi line comment of the type // // /* // * Some text. // * Some more text. // */ // // is handled by replacing the whitespace sequences before the * by a single space return \preg_replace('(^\\s+\\*)m', ' *', $this->text); } elseif (\preg_match('(^/\\*\\*?\\s*[\\r\\n])', $text) && \preg_match('(\\n(\\s*)\\*/$)', $text, $matches)) { // Multi line comment of the type // // /* // Some text. // Some more text. // */ // // is handled by removing the whitespace sequence on the line before the closing // */ on all lines. So if the last line is " */", then " " is removed at the // start of all lines. return \preg_replace('(^' . \preg_quote($matches[1]) . ')m', '', $text); } elseif (\preg_match('(^/\\*\\*?\\s*(?!\\s))', $text, $matches)) { // Multi line comment of the type // // /* Some text. // Some more text. // Indented text. // Even more text. */ // // is handled by removing the difference between the shortest whitespace prefix on all // lines and the length of the "/* " opening sequence. $prefixLen = $this->getShortestWhitespacePrefixLen(\substr($text, $newlinePos + 1)); $removeLen = $prefixLen - \strlen($matches[0]); return \preg_replace('(^\\s{' . $removeLen . '})m', '', $text); } // No idea how to format this comment, so simply return as is return $text; } /** * Get length of shortest whitespace prefix (at the start of a line). * * If there is a line with no prefix whitespace, 0 is a valid return value. * * @param string $str String to check * @return int Length in characters. Tabs count as single characters. */ private function getShortestWhitespacePrefixLen(string $str) : int { $lines = \explode("\n", $str); $shortestPrefixLen = \INF; foreach ($lines as $line) { \preg_match('(^\\s*)', $line, $matches); $prefixLen = \strlen($matches[0]); if ($prefixLen < $shortestPrefixLen) { $shortestPrefixLen = $prefixLen; } } return $shortestPrefixLen; } /** * @return array * @psalm-return array{nodeType:string, text:mixed, line:mixed, filePos:mixed} */ public function jsonSerialize() : array { // Technically not a node, but we make it look like one anyway $type = $this instanceof \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc ? 'Comment_Doc' : 'Comment'; return [ 'nodeType' => $type, 'text' => $this->text, // TODO: Rename these to include "start". 'line' => $this->startLine, 'filePos' => $this->startFilePos, 'tokenPos' => $this->startTokenPos, 'endLine' => $this->endLine, 'endFilePos' => $this->endFilePos, 'endTokenPos' => $this->endTokenPos, ]; } } errors[] = $error; } /** * Get collected errors. * * @return Error[] */ public function getErrors() : array { return $this->errors; } /** * Check whether there are any errors. * * @return bool */ public function hasErrors() : bool { return !empty($this->errors); } /** * Reset/clear collected errors. */ public function clearErrors() { $this->errors = []; } } lexer = $lexer; if (isset($options['throwOnError'])) { throw new \LogicException('"throwOnError" is no longer supported, use "errorHandler" instead'); } $this->initReduceCallbacks(); } /** * Parses PHP code into a node tree. * * If a non-throwing error handler is used, the parser will continue parsing after an error * occurred and attempt to build a partial AST. * * @param string $code The source code to parse * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults * to ErrorHandler\Throwing. * * @return Node\Stmt[]|null Array of statements (or null non-throwing error handler is used and * the parser was unable to recover from an error). */ public function parse(string $code, \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler $errorHandler = null) { $this->errorHandler = $errorHandler ?: new \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler\Throwing(); $this->lexer->startLexing($code, $this->errorHandler); $result = $this->doParse(); // Clear out some of the interior state, so we don't hold onto unnecessary // memory between uses of the parser $this->startAttributeStack = []; $this->endAttributeStack = []; $this->semStack = []; $this->semValue = null; return $result; } protected function doParse() { // We start off with no lookahead-token $symbol = self::SYMBOL_NONE; // The attributes for a node are taken from the first and last token of the node. // From the first token only the startAttributes are taken and from the last only // the endAttributes. Both are merged using the array union operator (+). $startAttributes = []; $endAttributes = []; $this->endAttributes = $endAttributes; // Keep stack of start and end attributes $this->startAttributeStack = []; $this->endAttributeStack = [$endAttributes]; // Start off in the initial state and keep a stack of previous states $state = 0; $stateStack = [$state]; // Semantic value stack (contains values of tokens and semantic action results) $this->semStack = []; // Current position in the stack(s) $stackPos = 0; $this->errorState = 0; for (;;) { //$this->traceNewState($state, $symbol); if ($this->actionBase[$state] === 0) { $rule = $this->actionDefault[$state]; } else { if ($symbol === self::SYMBOL_NONE) { // Fetch the next token id from the lexer and fetch additional info by-ref. // The end attributes are fetched into a temporary variable and only set once the token is really // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is // reduced after a token was read but not yet shifted. $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes); // map the lexer token id to the internally used symbols $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize ? $this->tokenToSymbol[$tokenId] : $this->invalidSymbol; if ($symbol === $this->invalidSymbol) { throw new \RangeException(\sprintf('The lexer returned an invalid token (id=%d, value=%s)', $tokenId, $tokenValue)); } // This is necessary to assign some meaningful attributes to /* empty */ productions. They'll get // the attributes of the next token, even though they don't contain it themselves. $this->startAttributeStack[$stackPos + 1] = $startAttributes; $this->endAttributeStack[$stackPos + 1] = $endAttributes; $this->lookaheadStartAttributes = $startAttributes; //$this->traceRead($symbol); } $idx = $this->actionBase[$state] + $symbol; if (($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) && ($action = $this->action[$idx]) !== $this->defaultAction) { /* * >= numNonLeafStates: shift and reduce * > 0: shift * = 0: accept * < 0: reduce * = -YYUNEXPECTED: error */ if ($action > 0) { /* shift */ //$this->traceShift($symbol); ++$stackPos; $stateStack[$stackPos] = $state = $action; $this->semStack[$stackPos] = $tokenValue; $this->startAttributeStack[$stackPos] = $startAttributes; $this->endAttributeStack[$stackPos] = $endAttributes; $this->endAttributes = $endAttributes; $symbol = self::SYMBOL_NONE; if ($this->errorState) { --$this->errorState; } if ($action < $this->numNonLeafStates) { continue; } /* $yyn >= numNonLeafStates means shift-and-reduce */ $rule = $action - $this->numNonLeafStates; } else { $rule = -$action; } } else { $rule = $this->actionDefault[$state]; } } for (;;) { if ($rule === 0) { /* accept */ //$this->traceAccept(); return $this->semValue; } elseif ($rule !== $this->unexpectedTokenRule) { /* reduce */ //$this->traceReduce($rule); try { $this->reduceCallbacks[$rule]($stackPos); } catch (\_HumbugBoxd02f763d3c56\PhpParser\Error $e) { if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) { $e->setStartLine($startAttributes['startLine']); } $this->emitError($e); // Can't recover from this type of error return null; } /* Goto - shift nonterminal */ $lastEndAttributes = $this->endAttributeStack[$stackPos]; $stackPos -= $this->ruleToLength[$rule]; $nonTerminal = $this->ruleToNonTerminal[$rule]; $idx = $this->gotoBase[$nonTerminal] + $stateStack[$stackPos]; if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] === $nonTerminal) { $state = $this->goto[$idx]; } else { $state = $this->gotoDefault[$nonTerminal]; } ++$stackPos; $stateStack[$stackPos] = $state; $this->semStack[$stackPos] = $this->semValue; $this->endAttributeStack[$stackPos] = $lastEndAttributes; } else { /* error */ switch ($this->errorState) { case 0: $msg = $this->getErrorMessage($symbol, $state); $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error($msg, $startAttributes + $endAttributes)); // Break missing intentionally case 1: case 2: $this->errorState = 3; // Pop until error-expecting state uncovered while (!(($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) || ($action = $this->action[$idx]) === $this->defaultAction) { // Not totally sure about this if ($stackPos <= 0) { // Could not recover from error return null; } $state = $stateStack[--$stackPos]; //$this->tracePop($state); } //$this->traceShift($this->errorSymbol); ++$stackPos; $stateStack[$stackPos] = $state = $action; // We treat the error symbol as being empty, so we reset the end attributes // to the end attributes of the last non-error symbol $this->endAttributeStack[$stackPos] = $this->endAttributeStack[$stackPos - 1]; $this->endAttributes = $this->endAttributeStack[$stackPos - 1]; break; case 3: if ($symbol === 0) { // Reached EOF without recovering from error return null; } //$this->traceDiscard($symbol); $symbol = self::SYMBOL_NONE; break 2; } } if ($state < $this->numNonLeafStates) { break; } /* >= numNonLeafStates means shift-and-reduce */ $rule = $state - $this->numNonLeafStates; } } throw new \RuntimeException('Reached end of parser loop'); } protected function emitError(\_HumbugBoxd02f763d3c56\PhpParser\Error $error) { $this->errorHandler->handleError($error); } /** * Format error message including expected tokens. * * @param int $symbol Unexpected symbol * @param int $state State at time of error * * @return string Formatted error message */ protected function getErrorMessage(int $symbol, int $state) : string { $expectedString = ''; if ($expected = $this->getExpectedTokens($state)) { $expectedString = ', expecting ' . \implode(' or ', $expected); } return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString; } /** * Get limited number of expected tokens in given state. * * @param int $state State * * @return string[] Expected tokens. If too many, an empty array is returned. */ protected function getExpectedTokens(int $state) : array { $expected = []; $base = $this->actionBase[$state]; foreach ($this->symbolToName as $symbol => $name) { $idx = $base + $symbol; if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) { if ($this->action[$idx] !== $this->unexpectedTokenRule && $this->action[$idx] !== $this->defaultAction && $symbol !== $this->errorSymbol) { if (\count($expected) === 4) { /* Too many expected tokens */ return []; } $expected[] = $name; } } } return $expected; } /* * Tracing functions used for debugging the parser. */ /* protected function traceNewState($state, $symbol) { echo '% State ' . $state . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n"; } protected function traceRead($symbol) { echo '% Reading ' . $this->symbolToName[$symbol] . "\n"; } protected function traceShift($symbol) { echo '% Shift ' . $this->symbolToName[$symbol] . "\n"; } protected function traceAccept() { echo "% Accepted.\n"; } protected function traceReduce($n) { echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n"; } protected function tracePop($state) { echo '% Recovering, uncovered state ' . $state . "\n"; } protected function traceDiscard($symbol) { echo '% Discard ' . $this->symbolToName[$symbol] . "\n"; } */ /* * Helper functions invoked by semantic actions */ /** * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions. * * @param Node\Stmt[] $stmts * @return Node\Stmt[] */ protected function handleNamespaces(array $stmts) : array { $hasErrored = \false; $style = $this->getNamespacingStyle($stmts); if (null === $style) { // not namespaced, nothing to do return $stmts; } elseif ('brace' === $style) { // For braced namespaces we only have to check that there are no invalid statements between the namespaces $afterFirstNamespace = \false; foreach ($stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { $afterFirstNamespace = \true; } elseif (!$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\HaltCompiler && !$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop && $afterFirstNamespace && !$hasErrored) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('No code may exist outside of namespace {}', $stmt->getAttributes())); $hasErrored = \true; // Avoid one error for every statement } } return $stmts; } else { // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts $resultStmts = []; $targetStmts =& $resultStmts; $lastNs = null; foreach ($stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { if ($lastNs !== null) { $this->fixupNamespaceAttributes($lastNs); } if ($stmt->stmts === null) { $stmt->stmts = []; $targetStmts =& $stmt->stmts; $resultStmts[] = $stmt; } else { // This handles the invalid case of mixed style namespaces $resultStmts[] = $stmt; $targetStmts =& $resultStmts; } $lastNs = $stmt; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\HaltCompiler) { // __halt_compiler() is not moved into the namespace $resultStmts[] = $stmt; } else { $targetStmts[] = $stmt; } } if ($lastNs !== null) { $this->fixupNamespaceAttributes($lastNs); } return $resultStmts; } } private function fixupNamespaceAttributes(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_ $stmt) { // We moved the statements into the namespace node, as such the end of the namespace node // needs to be extended to the end of the statements. if (empty($stmt->stmts)) { return; } // We only move the builtin end attributes here. This is the best we can do with the // knowledge we have. $endAttributes = ['endLine', 'endFilePos', 'endTokenPos']; $lastStmt = $stmt->stmts[\count($stmt->stmts) - 1]; foreach ($endAttributes as $endAttribute) { if ($lastStmt->hasAttribute($endAttribute)) { $stmt->setAttribute($endAttribute, $lastStmt->getAttribute($endAttribute)); } } } /** * Determine namespacing style (semicolon or brace) * * @param Node[] $stmts Top-level statements. * * @return null|string One of "semicolon", "brace" or null (no namespaces) */ private function getNamespacingStyle(array $stmts) { $style = null; $hasNotAllowedStmts = \false; foreach ($stmts as $i => $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace'; if (null === $style) { $style = $currentStyle; if ($hasNotAllowedStmts) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Namespace declaration statement has to be the very first statement in the script', $stmt->getLine())); } } elseif ($style !== $currentStyle) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Cannot mix bracketed namespace declarations with unbracketed namespace declarations', $stmt->getLine())); // Treat like semicolon style for namespace normalization return 'semicolon'; } continue; } /* declare(), __halt_compiler() and nops can be used before a namespace declaration */ if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Declare_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\HaltCompiler || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop) { continue; } /* There may be a hashbang line at the very start of the file */ if ($i === 0 && $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\InlineHTML && \preg_match('/\\A#!.*\\r?\\n\\z/', $stmt->value)) { continue; } /* Everything else if forbidden before namespace declarations */ $hasNotAllowedStmts = \true; } return $style; } /** * Fix up parsing of static property calls in PHP 5. * * In PHP 5 A::$b[c][d] and A::$b[c][d]() have very different interpretation. The former is * interpreted as (A::$b)[c][d], while the latter is the same as A::{$b[c][d]}(). We parse the * latter as the former initially and this method fixes the AST into the correct form when we * encounter the "()". * * @param Node\Expr\StaticPropertyFetch|Node\Expr\ArrayDimFetch $prop * @param Node\Arg[] $args * @param array $attributes * * @return Expr\StaticCall */ protected function fixupPhp5StaticPropCall($prop, array $args, array $attributes) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall { if ($prop instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch) { $name = $prop->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier ? $prop->name->toString() : $prop->name; $var = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($name, $prop->name->getAttributes()); return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall($prop->class, $var, $args, $attributes); } elseif ($prop instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { $tmp = $prop; while ($tmp->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { $tmp = $tmp->var; } /** @var Expr\StaticPropertyFetch $staticProp */ $staticProp = $tmp->var; // Set start attributes to attributes of innermost node $tmp = $prop; $this->fixupStartAttributes($tmp, $staticProp->name); while ($tmp->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { $tmp = $tmp->var; $this->fixupStartAttributes($tmp, $staticProp->name); } $name = $staticProp->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier ? $staticProp->name->toString() : $staticProp->name; $tmp->var = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($name, $staticProp->name->getAttributes()); return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall($staticProp->class, $prop, $args, $attributes); } else { throw new \Exception(); } } protected function fixupStartAttributes(\_HumbugBoxd02f763d3c56\PhpParser\Node $to, \_HumbugBoxd02f763d3c56\PhpParser\Node $from) { $startAttributes = ['startLine', 'startFilePos', 'startTokenPos']; foreach ($startAttributes as $startAttribute) { if ($from->hasAttribute($startAttribute)) { $to->setAttribute($startAttribute, $from->getAttribute($startAttribute)); } } } protected function handleBuiltinTypes(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $name) { $builtinTypes = ['bool' => \true, 'int' => \true, 'float' => \true, 'string' => \true, 'iterable' => \true, 'void' => \true, 'object' => \true, 'null' => \true, 'false' => \true, 'mixed' => \true]; if (!$name->isUnqualified()) { return $name; } $lowerName = $name->toLowerString(); if (!isset($builtinTypes[$lowerName])) { return $name; } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($lowerName, $name->getAttributes()); } /** * Get combined start and end attributes at a stack location * * @param int $pos Stack location * * @return array Combined start and end attributes */ protected function getAttributesAt(int $pos) : array { return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos]; } protected function getFloatCastKind(string $cast) : int { $cast = \strtolower($cast); if (\strpos($cast, 'float') !== \false) { return \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::KIND_FLOAT; } if (\strpos($cast, 'real') !== \false) { return \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::KIND_REAL; } return \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double::KIND_DOUBLE; } protected function parseLNumber($str, $attributes, $allowInvalidOctal = \false) { try { return \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber::fromString($str, $attributes, $allowInvalidOctal); } catch (\_HumbugBoxd02f763d3c56\PhpParser\Error $error) { $this->emitError($error); // Use dummy value return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(0, $attributes); } } /** * Parse a T_NUM_STRING token into either an integer or string node. * * @param string $str Number string * @param array $attributes Attributes * * @return LNumber|String_ Integer or string node. */ protected function parseNumString(string $str, array $attributes) { if (!\preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($str, $attributes); } $num = +$str; if (!\is_int($num)) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($str, $attributes); } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber($num, $attributes); } protected function stripIndentation(string $string, int $indentLen, string $indentChar, bool $newlineAtStart, bool $newlineAtEnd, array $attributes) { if ($indentLen === 0) { return $string; } $start = $newlineAtStart ? '(?:(?<=\\n)|\\A)' : '(?<=\\n)'; $end = $newlineAtEnd ? '(?:(?=[\\r\\n])|\\z)' : '(?=[\\r\\n])'; $regex = '/' . $start . '([ \\t]*)(' . $end . ')?/'; return \preg_replace_callback($regex, function ($matches) use($indentLen, $indentChar, $attributes) { $prefix = \substr($matches[1], 0, $indentLen); if (\false !== \strpos($prefix, $indentChar === " " ? "\t" : " ")) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Invalid indentation - tabs and spaces cannot be mixed', $attributes)); } elseif (\strlen($prefix) < $indentLen && !isset($matches[2])) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Invalid body indentation level ' . '(expecting an indentation level of at least ' . $indentLen . ')', $attributes)); } return \substr($matches[0], \strlen($prefix)); }, $string); } protected function parseDocString(string $startToken, $contents, string $endToken, array $attributes, array $endTokenAttributes, bool $parseUnicodeEscape) { $kind = \strpos($startToken, "'") === \false ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_HEREDOC : \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_NOWDOC; $regex = '/\\A[bB]?<<<[ \\t]*[\'"]?([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)[\'"]?(?:\\r\\n|\\n|\\r)\\z/'; $result = \preg_match($regex, $startToken, $matches); \assert($result === 1); $label = $matches[1]; $result = \preg_match('/\\A[ \\t]*/', $endToken, $matches); \assert($result === 1); $indentation = $matches[0]; $attributes['kind'] = $kind; $attributes['docLabel'] = $label; $attributes['docIndentation'] = $indentation; $indentHasSpaces = \false !== \strpos($indentation, " "); $indentHasTabs = \false !== \strpos($indentation, "\t"); if ($indentHasSpaces && $indentHasTabs) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Invalid indentation - tabs and spaces cannot be mixed', $endTokenAttributes)); // Proceed processing as if this doc string is not indented $indentation = ''; } $indentLen = \strlen($indentation); $indentChar = $indentHasSpaces ? " " : "\t"; if (\is_string($contents)) { if ($contents === '') { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_('', $attributes); } $contents = $this->stripIndentation($contents, $indentLen, $indentChar, \true, \true, $attributes); $contents = \preg_replace('~(\\r\\n|\\n|\\r)\\z~', '', $contents); if ($kind === \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_HEREDOC) { $contents = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parseEscapeSequences($contents, null, $parseUnicodeEscape); } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($contents, $attributes); } else { \assert(\count($contents) > 0); if (!$contents[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart) { // If there is no leading encapsed string part, pretend there is an empty one $this->stripIndentation('', $indentLen, $indentChar, \true, \false, $contents[0]->getAttributes()); } $newContents = []; foreach ($contents as $i => $part) { if ($part instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart) { $isLast = $i === \count($contents) - 1; $part->value = $this->stripIndentation($part->value, $indentLen, $indentChar, $i === 0, $isLast, $part->getAttributes()); $part->value = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parseEscapeSequences($part->value, null, $parseUnicodeEscape); if ($isLast) { $part->value = \preg_replace('~(\\r\\n|\\n|\\r)\\z~', '', $part->value); } if ('' === $part->value) { continue; } } $newContents[] = $part; } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\Encapsed($newContents, $attributes); } } /** * Create attributes for a zero-length common-capturing nop. * * @param Comment[] $comments * @return array */ protected function createCommentNopAttributes(array $comments) { $comment = $comments[\count($comments) - 1]; $commentEndLine = $comment->getEndLine(); $commentEndFilePos = $comment->getEndFilePos(); $commentEndTokenPos = $comment->getEndTokenPos(); $attributes = ['comments' => $comments]; if (-1 !== $commentEndLine) { $attributes['startLine'] = $commentEndLine; $attributes['endLine'] = $commentEndLine; } if (-1 !== $commentEndFilePos) { $attributes['startFilePos'] = $commentEndFilePos + 1; $attributes['endFilePos'] = $commentEndFilePos; } if (-1 !== $commentEndTokenPos) { $attributes['startTokenPos'] = $commentEndTokenPos + 1; $attributes['endTokenPos'] = $commentEndTokenPos; } return $attributes; } protected function checkModifier($a, $b, $modifierPos) { // Jumping through some hoops here because verifyModifier() is also used elsewhere try { \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::verifyModifier($a, $b); } catch (\_HumbugBoxd02f763d3c56\PhpParser\Error $error) { $error->setAttributes($this->getAttributesAt($modifierPos)); $this->emitError($error); } } protected function checkParam(\_HumbugBoxd02f763d3c56\PhpParser\Node\Param $node) { if ($node->variadic && null !== $node->default) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Variadic parameter cannot have a default value', $node->default->getAttributes())); } } protected function checkTryCatch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TryCatch $node) { if (empty($node->catches) && null === $node->finally) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Cannot use try without catch or finally', $node->getAttributes())); } } protected function checkNamespace(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_ $node) { if (null !== $node->stmts) { foreach ($node->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Namespace declarations cannot be nested', $stmt->getAttributes())); } } } } protected function checkClass(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ $node, $namePos) { if (null !== $node->name && $node->name->isSpecialClassName()) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name), $this->getAttributesAt($namePos))); } if ($node->extends && $node->extends->isSpecialClassName()) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends), $node->extends->getAttributes())); } foreach ($node->implements as $interface) { if ($interface->isSpecialClassName()) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), $interface->getAttributes())); } } } protected function checkInterface(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ $node, $namePos) { if (null !== $node->name && $node->name->isSpecialClassName()) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name), $this->getAttributesAt($namePos))); } foreach ($node->extends as $interface) { if ($interface->isSpecialClassName()) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), $interface->getAttributes())); } } } protected function checkClassMethod(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod $node, $modifierPos) { if ($node->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC) { switch ($node->name->toLowerString()) { case '__construct': $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Constructor %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos))); break; case '__destruct': $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Destructor %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos))); break; case '__clone': $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Clone method %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos))); break; } } } protected function checkClassConst(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst $node, $modifierPos) { if ($node->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error("Cannot use 'static' as constant modifier", $this->getAttributesAt($modifierPos))); } if ($node->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error("Cannot use 'abstract' as constant modifier", $this->getAttributesAt($modifierPos))); } if ($node->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error("Cannot use 'final' as constant modifier", $this->getAttributesAt($modifierPos))); } } protected function checkProperty(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property $node, $modifierPos) { if ($node->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Properties cannot be declared abstract', $this->getAttributesAt($modifierPos))); } if ($node->flags & \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('Properties cannot be declared final', $this->getAttributesAt($modifierPos))); } } protected function checkUseUse(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse $node, $namePos) { if ($node->alias && $node->alias->isSpecialClassName()) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error(\sprintf('Cannot use %s as %s because \'%2$s\' is a special class name', $node->name, $node->alias), $this->getAttributesAt($namePos))); } } } $node stays as-is * * NodeTraverser::DONT_TRAVERSE_CHILDREN * => Children of $node are not traversed. $node stays as-is * * NodeTraverser::STOP_TRAVERSAL * => Traversal is aborted. $node stays as-is * * otherwise * => $node is set to the return value * * @param Node $node Node * * @return null|int|Node Replacement node (or special return value) */ public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node); /** * Called when leaving a node. * * Return value semantics: * * null * => $node stays as-is * * NodeTraverser::REMOVE_NODE * => $node is removed from the parent array * * NodeTraverser::STOP_TRAVERSAL * => Traversal is aborted. $node stays as-is * * array (of Nodes) * => The return value is merged into the parent array (at the position of the $node) * * otherwise * => $node is set to the return value * * @param Node $node Node * * @return null|int|Node|Node[] Replacement node (or special return value) */ public function leaveNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node); /** * Called once after traversal. * * Return value semantics: * * null: $nodes stays as-is * * otherwise: $nodes is set to the return value * * @param Node[] $nodes Array of nodes * * @return null|Node[] Array of nodes */ public function afterTraverse(array $nodes); } visitors[] = $visitor; } /** * Removes an added visitor. * * @param NodeVisitor $visitor */ public function removeVisitor(\_HumbugBoxd02f763d3c56\PhpParser\NodeVisitor $visitor) { foreach ($this->visitors as $index => $storedVisitor) { if ($storedVisitor === $visitor) { unset($this->visitors[$index]); break; } } } /** * Traverses an array of nodes using the registered visitors. * * @param Node[] $nodes Array of nodes * * @return Node[] Traversed array of nodes */ public function traverse(array $nodes) : array { $this->stopTraversal = \false; foreach ($this->visitors as $visitor) { if (null !== ($return = $visitor->beforeTraverse($nodes))) { $nodes = $return; } } $nodes = $this->traverseArray($nodes); foreach ($this->visitors as $visitor) { if (null !== ($return = $visitor->afterTraverse($nodes))) { $nodes = $return; } } return $nodes; } /** * Recursively traverse a node. * * @param Node $node Node to traverse. * * @return Node Result of traversal (may be original node or new one) */ protected function traverseNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : \_HumbugBoxd02f763d3c56\PhpParser\Node { foreach ($node->getSubNodeNames() as $name) { $subNode =& $node->{$name}; if (\is_array($subNode)) { $subNode = $this->traverseArray($subNode); if ($this->stopTraversal) { break; } } elseif ($subNode instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $traverseChildren = \true; $breakVisitorIndex = null; foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($subNode); if (null !== $return) { if ($return instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $this->ensureReplacementReasonable($subNode, $return); $subNode = $return; } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = \false; } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { $traverseChildren = \false; $breakVisitorIndex = $visitorIndex; break; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = \true; break 2; } else { throw new \LogicException('enterNode() returned invalid value of type ' . \gettype($return)); } } } if ($traverseChildren) { $subNode = $this->traverseNode($subNode); if ($this->stopTraversal) { break; } } foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->leaveNode($subNode); if (null !== $return) { if ($return instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $this->ensureReplacementReasonable($subNode, $return); $subNode = $return; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = \true; break 2; } elseif (\is_array($return)) { throw new \LogicException('leaveNode() may only return an array ' . 'if the parent structure is an array'); } else { throw new \LogicException('leaveNode() returned invalid value of type ' . \gettype($return)); } } if ($breakVisitorIndex === $visitorIndex) { break; } } } } return $node; } /** * Recursively traverse array (usually of nodes). * * @param array $nodes Array to traverse * * @return array Result of traversal (may be original array or changed one) */ protected function traverseArray(array $nodes) : array { $doNodes = []; foreach ($nodes as $i => &$node) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $traverseChildren = \true; $breakVisitorIndex = null; foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($node); if (null !== $return) { if ($return instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $this->ensureReplacementReasonable($node, $return); $node = $return; } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = \false; } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { $traverseChildren = \false; $breakVisitorIndex = $visitorIndex; break; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = \true; break 2; } else { throw new \LogicException('enterNode() returned invalid value of type ' . \gettype($return)); } } } if ($traverseChildren) { $node = $this->traverseNode($node); if ($this->stopTraversal) { break; } } foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->leaveNode($node); if (null !== $return) { if ($return instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $this->ensureReplacementReasonable($node, $return); $node = $return; } elseif (\is_array($return)) { $doNodes[] = [$i, $return]; break; } elseif (self::REMOVE_NODE === $return) { $doNodes[] = [$i, []]; break; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = \true; break 2; } elseif (\false === $return) { throw new \LogicException('bool(false) return from leaveNode() no longer supported. ' . 'Return NodeTraverser::REMOVE_NODE instead'); } else { throw new \LogicException('leaveNode() returned invalid value of type ' . \gettype($return)); } } if ($breakVisitorIndex === $visitorIndex) { break; } } } elseif (\is_array($node)) { throw new \LogicException('Invalid node structure: Contains nested arrays'); } } if (!empty($doNodes)) { while (list($i, $replace) = \array_pop($doNodes)) { \array_splice($nodes, $i, 1, $replace); } } return $nodes; } private function ensureReplacementReasonable($old, $new) { if ($old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt && $new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { throw new \LogicException("Trying to replace statement ({$old->getType()}) " . "with expression ({$new->getType()}). Are you missing a " . "Stmt_Expression wrapper?"); } if ($old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr && $new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt) { throw new \LogicException("Trying to replace expression ({$old->getType()}) " . "with statement ({$new->getType()})"); } } } parsers = $parsers; } public function parse(string $code, \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler $errorHandler = null) { if (null === $errorHandler) { $errorHandler = new \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler\Throwing(); } list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code); if ($firstError === null) { return $firstStmts; } for ($i = 1, $c = \count($this->parsers); $i < $c; ++$i) { list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code); if ($error === null) { return $stmts; } } throw $firstError; } private function tryParse(\_HumbugBoxd02f763d3c56\PhpParser\Parser $parser, \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler $errorHandler, $code) { $stmts = null; $error = null; try { $stmts = $parser->parse($code, $errorHandler); } catch (\_HumbugBoxd02f763d3c56\PhpParser\Error $error) { } return [$stmts, $error]; } } '", "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "'+'", "'-'", "'.'", "'*'", "'/'", "'%'", "'!'", "T_INSTANCEOF", "'~'", "T_INC", "T_DEC", "T_INT_CAST", "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", "T_BOOL_CAST", "T_UNSET_CAST", "'@'", "T_POW", "'['", "T_NEW", "T_CLONE", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_MATCH", "T_ENDSWITCH", "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_GOTO", "T_FUNCTION", "T_FN", "T_CONST", "T_RETURN", "T_TRY", "T_CATCH", "T_FINALLY", "T_USE", "T_INSTEADOF", "T_GLOBAL", "T_STATIC", "T_ABSTRACT", "T_FINAL", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", "T_VAR", "T_UNSET", "T_ISSET", "T_EMPTY", "T_HALT_COMPILER", "T_CLASS", "T_TRAIT", "T_INTERFACE", "T_EXTENDS", "T_IMPLEMENTS", "T_OBJECT_OPERATOR", "T_LIST", "T_ARRAY", "T_CALLABLE", "T_CLASS_C", "T_TRAIT_C", "T_METHOD_C", "T_FUNC_C", "T_LINE", "T_FILE", "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", "T_ELLIPSIS", "T_NAME_FULLY_QUALIFIED", "T_NAME_QUALIFIED", "T_NAME_RELATIVE", "';'", "'{'", "'}'", "'('", "')'", "'\$'", "'`'", "']'", "'\"'", "T_NULLSAFE_OBJECT_OPERATOR", "T_ATTRIBUTE"); protected $tokenToSymbol = array(0, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 55, 162, 165, 159, 54, 37, 165, 157, 158, 52, 49, 8, 50, 51, 53, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 31, 154, 43, 16, 45, 30, 67, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 69, 165, 161, 36, 165, 160, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 155, 35, 156, 57, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 38, 39, 40, 41, 42, 44, 46, 47, 48, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 163, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 164); protected $action = array(693, 663, 664, 665, 666, 667, 282, 668, 669, 670, 706, 707, 221, 222, 223, 224, 225, 226, 227, 228, 229, 0, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32767, -32767, -32767, -32767, 27, 242, 243, -32766, -32766, -32766, -32766, -32766, 671, -32766, 333, -32766, -32766, -32766, -32766, -32766, -32766, -32767, -32767, -32767, -32767, -32767, 672, 673, 674, 675, 676, 677, 678, 1034, 816, 740, 941, 942, 943, 940, 939, 938, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 709, 732, 710, 711, 712, 713, 701, 702, 703, 731, 704, 705, 690, 691, 692, 694, 695, 696, 734, 735, 736, 737, 738, 739, 697, 698, 699, 700, 730, 721, 719, 720, 716, 717, 437, 708, 714, 715, 722, 723, 725, 724, 726, 727, 55, 56, 417, 57, 58, 718, 729, 728, 28, 59, 60, -220, 61, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, 36, -32767, -32767, -32767, -32767, 1034, 35, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -32766, -32766, -32766, -32766, 62, 63, 1034, 125, 285, 292, 64, 748, 65, 290, 291, 66, 67, 68, 69, 70, 71, 72, 73, 763, 25, 298, 74, 409, 973, 975, 294, 294, 1086, 1087, 1064, 796, 748, 218, 219, 220, 465, -32766, -32766, -32766, 742, 864, 817, 54, 807, 9, -32766, -32766, -32766, 760, 320, 761, 410, 10, 202, 246, 428, 209, -32766, 933, -32766, -32766, -32766, -32766, -32766, -32766, 488, -32766, 438, -32766, -32766, -32766, -32766, -32766, 473, 474, 941, 942, 943, 940, 939, 938, -32766, 475, 476, 337, 1092, 1093, 1094, 1095, 1089, 1090, 315, 1214, -255, 747, 1215, -505, 1096, 1091, 888, 889, 1066, 1065, 1067, 218, 219, 220, 41, 414, 337, 330, 895, 332, 418, -126, -126, -126, 75, 52, 464, -4, 817, 54, 805, -224, 202, 40, 21, 419, -126, 466, -126, 467, -126, 468, -126, 359, 420, 128, 128, 748, 1171, 31, 32, 421, 422, 1034, 894, 33, 469, -32766, -32766, -32766, 1186, 351, 352, 470, 471, -32766, -32766, -32766, 309, 472, 865, 323, 788, 835, 423, 424, -32767, -32767, -32767, -32767, 97, 98, 99, 100, 101, 615, -32766, 313, -32766, -32766, -32766, -32766, 354, 1185, 1171, 218, 219, 220, 475, 748, 418, 819, 629, -126, 297, 915, 464, 817, 54, -32766, 805, 124, 748, 40, 21, 419, 202, 466, 48, 467, 534, 468, 129, 429, 420, 337, 341, 888, 889, 31, 32, 421, 422, 416, 405, 33, 469, -32766, -32766, 311, 298, 351, 352, 470, 471, -32766, -32766, -32766, 748, 472, 412, 748, 752, 835, 423, 424, 338, 1066, 1065, 1067, 219, 220, 919, 1136, 296, 20, -32766, 576, -32766, -32766, -32766, 742, 341, 342, 413, 429, 1064, 337, 512, 418, 202, 819, 629, -4, 1034, 464, 817, 54, 49, 805, 337, 762, 40, 21, 419, 51, 466, 1034, 467, 475, 468, 340, 748, 420, 120, -205, -205, -205, 31, 32, 421, 422, 1062, -32766, 33, 469, -32766, -32766, -32766, 744, 351, 352, 470, 471, 429, 1098, 337, 429, 472, 337, 1034, 788, 835, 423, 424, 415, 1098, -32766, 802, -32766, -32766, 102, 103, 104, 1137, 303, 202, 130, 1066, 1065, 1067, 337, 123, 239, 240, 241, 748, 105, 418, 1205, 819, 629, -205, 440, 464, -32766, -32766, -32766, 805, 242, 243, 40, 21, 419, 121, 466, 126, 467, 429, 468, 337, 122, 420, 1052, -204, -204, -204, 31, 32, 421, 422, 1034, 745, 33, 469, 220, 759, 817, 54, 351, 352, 470, 471, 218, 219, 220, 119, 472, 244, 127, 788, 835, 423, 424, 202, -32766, -32766, -32766, 30, 293, 803, 79, 80, 81, 202, 798, 210, 632, 99, 100, 101, 236, 237, 238, 817, 54, -32766, 211, 800, 819, 629, -204, 34, 1034, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 286, 303, 418, 1034, 817, 54, -32766, -32766, 464, 218, 219, 220, 805, 105, 914, 40, 21, 419, 78, 466, 212, 467, 337, 468, 133, 247, 420, 295, 567, 248, 202, 31, 32, 421, 633, 242, 243, 33, 469, 418, 249, 817, 54, 351, 352, 464, 760, -84, 761, 805, 310, 472, 40, 21, 419, -32766, 466, 640, 467, 643, 468, 447, 22, 420, 815, 452, 584, 132, 31, 32, 421, 637, 134, 364, 33, 469, 418, 303, 817, 54, 351, 352, 464, 819, 629, 828, 805, 43, 472, 40, 21, 419, 44, 466, 45, 467, 46, 468, 591, 592, 420, 753, 635, 930, 649, 31, 32, 421, 641, 918, 657, 33, 469, 418, 105, 817, 54, 351, 352, 464, 819, 629, 47, 805, 50, 472, 40, 21, 419, 53, 466, 131, 467, 298, 468, 599, 742, 420, -32766, -274, 516, 570, 31, 32, 421, 646, 748, 946, 33, 469, 418, 589, 436, -32766, 351, 352, 464, 819, 629, 623, 805, 836, 472, 40, 21, 419, 611, 466, -82, 467, 603, 468, 11, 573, 420, 439, 456, 281, 318, 31, 32, 421, 588, 432, 321, 33, 469, 418, -414, 458, 322, 351, 352, 464, 851, 629, 837, 805, -505, 472, 40, 21, 419, 654, 466, 38, 467, 24, 468, 0, 0, 420, 319, 0, -405, 0, 31, 32, 421, 245, 312, 314, 33, 469, -506, 0, 0, 1097, 351, 352, 1143, 819, 629, 0, 0, 527, 472, 213, 214, 6, 7, 12, 14, 215, 363, 216, -415, 558, 789, -221, 830, 0, 0, 747, 0, 0, 0, 207, 39, 652, 653, 758, 806, 814, 793, 1086, 1087, 808, 819, 629, 213, 214, 867, 1088, 858, 859, 215, 791, 216, 852, 849, 847, 925, 926, 923, 813, 797, 799, 801, 804, 207, 922, 756, 757, 924, 287, 78, 331, 1086, 1087, 353, 630, 634, 636, 638, 639, 1088, 642, 644, 645, 647, 648, 631, 1142, 1211, 1213, 755, 834, 754, 833, 1212, 554, 832, 1092, 1093, 1094, 1095, 1089, 1090, 388, 1048, 824, 1036, 831, 1037, 1096, 1091, 822, 931, 856, 857, 451, 1210, 1179, 0, 217, 1177, 1162, 1175, 1077, 906, 1183, 1173, 0, 554, 26, 1092, 1093, 1094, 1095, 1089, 1090, 388, 29, 37, 42, 76, 77, 1096, 1091, 208, 284, 288, 289, 304, 305, 306, 307, 217, 335, 406, 408, 0, -220, 16, 17, 18, 383, 448, 455, 457, 462, 548, 620, 1039, 1042, 896, 1102, 1038, 1014, 559, 1013, 1079, 0, 0, -424, 1032, 0, 1043, 1045, 1044, 1047, 1046, 1061, 1176, 1161, 1157, 1174, 1076, 1208, 1103, 1156, 595); protected $actionCheck = array(2, 3, 4, 5, 6, 7, 14, 9, 10, 11, 12, 13, 33, 34, 35, 36, 37, 38, 39, 40, 41, 0, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 9, 10, 11, 33, 34, 35, 36, 37, 38, 39, 40, 41, 8, 68, 69, 33, 34, 35, 36, 37, 56, 30, 8, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 70, 71, 72, 73, 74, 75, 76, 13, 1, 79, 115, 116, 117, 118, 119, 120, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 31, 132, 133, 134, 135, 136, 137, 138, 139, 140, 3, 4, 5, 6, 7, 146, 147, 148, 8, 12, 13, 158, 15, 33, 34, 35, 36, 37, 38, 39, 40, 41, 14, 43, 44, 45, 46, 13, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 33, 34, 35, 36, 49, 50, 13, 8, 8, 37, 55, 81, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 156, 69, 70, 71, 72, 58, 59, 37, 37, 77, 78, 79, 154, 81, 9, 10, 11, 85, 9, 10, 11, 79, 31, 1, 2, 154, 107, 9, 10, 11, 105, 112, 107, 126, 8, 30, 31, 105, 8, 30, 121, 32, 33, 34, 35, 36, 37, 115, 30, 155, 32, 33, 34, 35, 36, 123, 124, 115, 116, 117, 118, 119, 120, 115, 132, 133, 159, 135, 136, 137, 138, 139, 140, 141, 79, 156, 151, 82, 131, 147, 148, 133, 134, 151, 152, 153, 9, 10, 11, 157, 8, 159, 160, 158, 162, 73, 74, 75, 76, 150, 69, 79, 0, 1, 2, 83, 158, 30, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 8, 97, 150, 150, 81, 81, 102, 103, 104, 105, 13, 158, 108, 109, 9, 10, 11, 158, 114, 115, 116, 117, 9, 10, 11, 8, 122, 154, 8, 125, 126, 127, 128, 43, 44, 45, 46, 47, 48, 49, 50, 51, 79, 30, 131, 32, 33, 34, 35, 8, 1, 81, 9, 10, 11, 132, 81, 73, 154, 155, 156, 37, 154, 79, 1, 2, 115, 83, 155, 81, 86, 87, 88, 30, 90, 69, 92, 80, 94, 155, 157, 97, 159, 159, 133, 134, 102, 103, 104, 105, 8, 107, 108, 109, 9, 10, 112, 70, 114, 115, 116, 117, 9, 10, 11, 81, 122, 8, 81, 125, 126, 127, 128, 8, 151, 152, 153, 10, 11, 156, 161, 8, 158, 30, 84, 32, 33, 34, 79, 159, 146, 8, 157, 79, 159, 84, 73, 30, 154, 155, 156, 13, 79, 1, 2, 69, 83, 159, 156, 86, 87, 88, 69, 90, 13, 92, 132, 94, 69, 81, 97, 155, 99, 100, 101, 102, 103, 104, 105, 115, 9, 108, 109, 9, 10, 11, 79, 114, 115, 116, 117, 157, 142, 159, 157, 122, 159, 13, 125, 126, 127, 128, 8, 142, 30, 154, 32, 33, 52, 53, 54, 158, 56, 30, 155, 151, 152, 153, 159, 14, 52, 53, 54, 81, 68, 73, 84, 154, 155, 156, 131, 79, 33, 34, 35, 83, 68, 69, 86, 87, 88, 155, 90, 155, 92, 157, 94, 159, 155, 97, 158, 99, 100, 101, 102, 103, 104, 105, 13, 152, 108, 109, 11, 154, 1, 2, 114, 115, 116, 117, 9, 10, 11, 16, 122, 14, 31, 125, 126, 127, 128, 30, 9, 10, 11, 143, 144, 154, 9, 10, 11, 30, 154, 16, 31, 49, 50, 51, 49, 50, 51, 1, 2, 30, 16, 154, 154, 155, 156, 30, 13, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 37, 56, 73, 13, 1, 2, 33, 34, 79, 9, 10, 11, 83, 68, 154, 86, 87, 88, 155, 90, 16, 92, 159, 94, 155, 16, 97, 37, 159, 16, 30, 102, 103, 104, 31, 68, 69, 108, 109, 73, 16, 1, 2, 114, 115, 79, 105, 31, 107, 83, 31, 122, 86, 87, 88, 33, 90, 31, 92, 31, 94, 74, 75, 97, 31, 74, 75, 31, 102, 103, 104, 31, 100, 101, 108, 109, 73, 56, 1, 2, 114, 115, 79, 154, 155, 37, 83, 69, 122, 86, 87, 88, 69, 90, 69, 92, 69, 94, 110, 111, 97, 154, 155, 154, 155, 102, 103, 104, 31, 154, 155, 108, 109, 73, 68, 1, 2, 114, 115, 79, 154, 155, 69, 83, 69, 122, 86, 87, 88, 69, 90, 69, 92, 70, 94, 76, 79, 97, 84, 81, 84, 89, 102, 103, 104, 31, 81, 81, 108, 109, 73, 112, 88, 115, 114, 115, 79, 154, 155, 91, 83, 126, 122, 86, 87, 88, 93, 90, 96, 92, 95, 94, 96, 99, 97, 96, 96, 96, 129, 102, 103, 104, 99, 105, 113, 108, 109, 73, 145, 105, 129, 114, 115, 79, 154, 155, 126, 83, 131, 122, 86, 87, 88, 156, 90, 154, 92, 157, 94, -1, -1, 97, 130, -1, 145, -1, 102, 103, 104, 31, 131, 131, 108, 109, 131, -1, -1, 142, 114, 115, 142, 154, 155, -1, -1, 149, 122, 49, 50, 145, 145, 145, 145, 55, 145, 57, 145, 149, 156, 158, 150, -1, -1, 151, -1, -1, -1, 69, 154, 154, 154, 154, 154, 154, 154, 77, 78, 154, 154, 155, 49, 50, 154, 85, 154, 154, 55, 154, 57, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 69, 154, 154, 154, 154, 159, 155, 155, 77, 78, 155, 155, 155, 155, 155, 155, 85, 155, 155, 155, 155, 155, 155, 162, 156, 156, 156, 156, 156, 156, 156, 133, 156, 135, 136, 137, 138, 139, 140, 141, 156, 156, 156, 156, 156, 147, 148, 156, 156, 156, 156, 156, 156, 156, -1, 157, 156, 156, 156, 156, 156, 156, 156, -1, 133, 157, 135, 136, 137, 138, 139, 140, 141, 157, 157, 157, 157, 157, 147, 148, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, -1, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -1, -1, 160, 160, -1, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161); protected $actionBase = array(0, 226, 306, 385, 464, 285, 246, 246, 786, -2, -2, 146, -2, -2, -2, 649, 723, 760, 723, 575, 686, 612, 612, 612, 175, 153, 153, 153, 174, 890, 319, 62, 450, 463, 557, 609, 636, 496, 496, 496, 496, 136, 136, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 195, 75, 777, 517, 147, 778, 779, 780, 886, 727, 887, 832, 833, 682, 836, 837, 838, 839, 840, 831, 841, 907, 842, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 483, 573, 365, 209, 281, 407, 646, 646, 646, 646, 646, 646, 646, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 429, 834, 585, 585, 585, 563, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 495, 486, -21, -21, 415, 668, 335, 619, 222, 511, 213, 25, 25, 25, 25, 25, 148, 16, 4, 4, 4, 4, 151, 312, 312, 312, 312, 119, 119, 119, 119, 346, 346, 123, 245, 245, 349, 400, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 111, 558, 558, 561, 561, 310, 152, 152, 152, 152, 704, 273, 273, 129, 371, 371, 371, 373, 734, 797, 376, 376, 376, 376, 376, 376, 468, 468, 468, 480, 480, 480, 702, 587, 454, 587, 454, 684, 748, 509, 748, 700, 199, 515, 803, 398, 720, 829, 729, 830, 601, 747, 235, 782, 724, 419, 782, 633, 637, 634, 419, 419, 715, 98, 863, 292, 195, 595, 405, 667, 781, 421, 732, 784, 363, 445, 411, 593, 328, 286, 744, 785, 888, 889, 181, 739, 667, 667, 667, 139, 362, 328, -8, 613, 613, 613, 613, 48, 613, 613, 613, 613, 314, 230, 506, 404, 783, 703, 703, 712, 694, 852, 696, 696, 703, 711, 703, 712, 694, 854, 854, 854, 854, 703, 694, 703, 703, 703, 696, 696, 694, 709, 696, 38, 694, 695, 707, 707, 854, 751, 752, 703, 703, 728, 696, 696, 696, 728, 694, 854, 685, 746, 234, 696, 854, 665, 711, 665, 703, 685, 694, 665, 711, 711, 665, 21, 662, 664, 853, 855, 869, 792, 681, 716, 861, 862, 856, 860, 844, 679, 753, 754, 569, 669, 671, 673, 699, 740, 701, 735, 724, 692, 692, 692, 713, 741, 713, 692, 692, 692, 692, 692, 692, 692, 692, 893, 689, 745, 736, 710, 755, 589, 600, 793, 731, 738, 882, 875, 891, 892, 863, 880, 713, 894, 697, 180, 650, 864, 693, 788, 713, 865, 713, 794, 713, 883, 804, 708, 805, 806, 692, 884, 895, 896, 897, 898, 899, 900, 901, 902, 706, 903, 756, 698, 876, 339, 859, 715, 742, 725, 791, 759, 807, 342, 904, 808, 713, 713, 795, 787, 713, 796, 764, 750, 872, 766, 877, 905, 731, 726, 878, 713, 730, 809, 906, 342, 672, 705, 737, 721, 767, 870, 885, 868, 798, 655, 659, 810, 812, 820, 674, 769, 873, 874, 871, 771, 799, 670, 800, 719, 821, 801, 866, 772, 822, 823, 881, 718, 743, 717, 722, 714, 802, 824, 879, 773, 774, 775, 827, 776, 828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 136, 136, 136, -2, -2, -2, -2, 0, 0, -2, 0, 0, 0, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 0, 0, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 591, -21, -21, -21, -21, 591, -21, -21, -21, -21, -21, -21, -21, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, -21, 376, 591, 591, 591, -21, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, -21, 591, 0, 0, 591, -21, 591, -21, 591, -21, 591, 591, 591, 591, 591, 591, -21, -21, -21, -21, -21, -21, 0, 468, 468, 468, 468, -21, -21, -21, -21, 376, 376, -37, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 468, 468, 480, 480, 376, 376, 376, 376, 376, -37, 376, 376, 419, 711, 711, 711, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 419, 0, 419, 0, 376, 419, 711, 419, 454, 711, 711, 419, 696, 618, 618, 618, 618, 342, 328, 0, 711, 711, 0, 711, 0, 0, 0, 0, 0, 696, 0, 703, 0, 0, 0, 0, 692, 180, 0, 725, 427, 0, 0, 0, 0, 0, 0, 725, 427, 435, 435, 0, 706, 692, 692, 692, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 342); protected $actionDefault = array(3, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 534, 534, 489, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 293, 293, 293, 32767, 32767, 32767, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 32767, 32767, 32767, 32767, 32767, 32767, 376, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 382, 539, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 357, 358, 360, 361, 292, 542, 523, 241, 383, 538, 291, 243, 321, 493, 32767, 32767, 32767, 323, 120, 252, 197, 492, 123, 290, 228, 375, 377, 322, 297, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 296, 449, 32767, 354, 353, 352, 451, 486, 486, 489, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 450, 319, 477, 476, 320, 447, 324, 448, 326, 452, 325, 342, 343, 340, 341, 344, 454, 453, 470, 471, 468, 469, 295, 345, 346, 347, 348, 472, 473, 474, 475, 32767, 32767, 276, 533, 533, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 333, 334, 461, 462, 32767, 232, 232, 232, 232, 277, 232, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 328, 329, 327, 456, 457, 455, 423, 32767, 32767, 32767, 425, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 494, 32767, 32767, 32767, 32767, 32767, 507, 412, 32767, 404, 32767, 32767, 216, 218, 165, 32767, 32767, 480, 32767, 32767, 32767, 32767, 32767, 512, 338, 32767, 32767, 114, 32767, 32767, 32767, 549, 32767, 507, 32767, 114, 32767, 32767, 32767, 32767, 351, 330, 331, 332, 32767, 32767, 511, 505, 464, 465, 466, 467, 32767, 458, 459, 460, 463, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 169, 420, 426, 426, 32767, 32767, 32767, 32767, 169, 32767, 32767, 32767, 32767, 32767, 169, 32767, 32767, 32767, 510, 509, 169, 32767, 405, 488, 169, 182, 180, 180, 32767, 202, 202, 32767, 32767, 184, 481, 500, 32767, 184, 169, 32767, 393, 171, 488, 32767, 32767, 234, 32767, 234, 32767, 393, 169, 234, 32767, 32767, 234, 32767, 406, 430, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 372, 373, 483, 496, 32767, 497, 32767, 404, 336, 337, 339, 316, 32767, 318, 362, 363, 364, 365, 366, 367, 368, 370, 32767, 410, 32767, 413, 32767, 32767, 32767, 251, 32767, 547, 32767, 32767, 300, 547, 32767, 32767, 32767, 541, 32767, 32767, 294, 32767, 32767, 32767, 32767, 247, 32767, 167, 32767, 531, 32767, 548, 32767, 505, 32767, 335, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 506, 32767, 32767, 32767, 32767, 223, 32767, 443, 32767, 114, 32767, 32767, 32767, 183, 32767, 32767, 298, 242, 32767, 32767, 540, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 112, 32767, 168, 32767, 32767, 32767, 185, 32767, 32767, 505, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 289, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 505, 32767, 32767, 227, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 406, 32767, 270, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 125, 125, 3, 125, 125, 254, 3, 254, 125, 254, 254, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 210, 213, 202, 202, 162, 125, 125, 262); protected $goto = array(165, 139, 139, 139, 165, 143, 146, 140, 141, 142, 148, 186, 167, 162, 162, 162, 162, 143, 143, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 137, 158, 159, 160, 161, 183, 138, 184, 489, 490, 367, 491, 495, 496, 497, 498, 499, 500, 501, 502, 959, 163, 144, 145, 147, 170, 175, 185, 203, 251, 254, 256, 258, 260, 261, 262, 263, 264, 265, 273, 274, 275, 276, 299, 300, 324, 325, 326, 384, 385, 386, 538, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 149, 150, 151, 166, 152, 168, 153, 204, 169, 154, 155, 156, 205, 157, 135, 616, 556, 574, 578, 622, 624, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 1099, 515, 345, 571, 600, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 504, 1202, 1202, 1075, 1074, 504, 540, 541, 542, 543, 544, 545, 546, 547, 549, 582, 3, 4, 173, 1202, 844, 844, 844, 844, 839, 845, 176, 177, 178, 391, 392, 393, 394, 172, 201, 206, 250, 255, 257, 259, 266, 267, 268, 269, 270, 271, 277, 278, 279, 280, 301, 302, 327, 328, 329, 396, 397, 398, 399, 174, 179, 252, 253, 180, 181, 182, 493, 493, 750, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 505, 929, 442, 444, 627, 505, 751, 779, 1100, 610, 927, 880, 880, 765, 1190, 1190, 1168, 555, 775, 764, 743, 1168, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, 390, 602, 746, 532, 532, 564, 528, 530, 530, 492, 494, 520, 536, 565, 568, 579, 586, 810, 606, 506, 346, 347, 609, 850, 506, 365, 537, 746, 533, 746, 563, 430, 430, 375, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 1063, 581, 957, 596, 597, 1063, 887, 887, 887, 887, 1160, 887, 887, 1182, 1182, 1182, 376, 376, 376, 749, 1063, 1063, 1063, 1063, 1063, 1063, 334, 1056, 317, 374, 374, 374, 866, 848, 846, 848, 650, 461, 507, 875, 870, 376, 1194, 368, 374, 389, 374, 898, 374, 1080, 583, 348, 404, 374, 1216, 590, 601, 1017, 19, 15, 361, 1148, 1187, 525, 936, 904, 510, 526, 904, 651, 551, 381, 1201, 1201, 587, 1007, 550, 877, 607, 608, 873, 612, 613, 619, 621, 626, 628, 23, 884, 937, 1201, 336, 598, 1059, 1060, 1204, 378, 1056, 557, 539, 893, 768, 766, 379, 514, 902, 509, 524, 655, 1057, 1159, 1057, 776, 509, 1167, 524, 514, 514, 1058, 1167, 1049, 907, 508, 1054, 511, 433, 434, 510, 1184, 1184, 1184, 854, 445, 945, 569, 1145, 459, 362, 0, 0, 773, 1209, 0, 518, 0, 519, 0, 529, 0, 0, 0, 0, 0, 1166, 0, 0, 0, 771, 0, 0, 0, 449, 0, 0, 0, 0, 0, 0, 605, 0, 0, 0, 0, 13, 1055, 614); protected $gotoCheck = array(42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 56, 66, 59, 59, 59, 8, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 124, 99, 69, 39, 39, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 66, 140, 140, 122, 122, 66, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 29, 29, 26, 140, 66, 66, 66, 66, 66, 66, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 115, 115, 14, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 7, 7, 7, 7, 115, 15, 28, 7, 7, 7, 74, 74, 22, 74, 74, 116, 56, 22, 22, 5, 116, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 50, 50, 10, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 60, 120, 69, 69, 60, 32, 120, 60, 2, 10, 107, 10, 2, 56, 56, 10, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 64, 99, 64, 64, 56, 56, 56, 56, 56, 79, 56, 56, 8, 8, 8, 121, 121, 121, 13, 56, 56, 56, 56, 56, 56, 123, 79, 123, 12, 12, 12, 13, 13, 13, 13, 13, 56, 13, 13, 13, 121, 138, 45, 12, 121, 12, 81, 12, 33, 67, 67, 67, 12, 12, 125, 48, 33, 33, 33, 33, 129, 136, 8, 95, 12, 12, 31, 12, 31, 31, 47, 139, 139, 31, 100, 33, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 33, 76, 95, 139, 17, 33, 79, 79, 139, 11, 79, 11, 46, 78, 24, 23, 16, 46, 82, 8, 8, 71, 79, 79, 79, 25, 8, 117, 8, 46, 46, 79, 117, 111, 83, 8, 113, 8, 8, 8, 12, 117, 117, 117, 68, 62, 97, 63, 128, 106, 57, -1, -1, 8, 8, -1, 57, -1, 99, -1, 57, -1, -1, -1, -1, -1, 117, -1, -1, -1, 8, -1, -1, -1, 57, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, 57, 12, 12); protected $gotoBase = array(0, 0, -249, 0, 0, 300, 0, 287, 105, 0, 47, 164, 118, 421, 274, 295, 171, 184, 0, 0, 0, 0, -49, 168, 172, 104, 24, 0, 288, -431, 0, -159, 359, 44, 0, 0, 0, 0, 0, 125, 0, 0, -24, 0, 0, 407, 479, 186, 178, 355, 75, 0, 0, 0, 0, 0, 106, 119, 0, -192, -81, 0, 101, 93, -231, 0, -90, 135, 121, -276, 0, 148, 0, 0, 21, 0, 183, 0, 194, 71, 0, 423, 155, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 0, 122, 0, 120, 176, 0, 0, 0, 0, 0, 83, 358, 170, 0, 0, 113, 0, 111, 0, -7, 9, 220, 0, 0, 77, 108, -102, 100, -42, 251, 0, 0, 89, 256, 0, 0, 0, 0, 0, 0, 181, 0, 419, 160, -107, 0, 0); protected $gotoDefault = array(-32768, 463, 659, 2, 660, 733, 741, 593, 477, 625, 577, 370, 1178, 785, 786, 787, 371, 358, 478, 369, 400, 395, 774, 767, 769, 777, 171, 401, 780, 1, 782, 513, 818, 1008, 355, 790, 356, 585, 792, 522, 794, 795, 136, 372, 373, 523, 479, 380, 572, 809, 272, 377, 811, 357, 812, 821, 360, 460, 454, 552, 604, 425, 441, 566, 560, 531, 1072, 561, 853, 344, 861, 656, 869, 872, 480, 553, 883, 446, 891, 1085, 387, 897, 903, 908, 283, 911, 407, 402, 580, 916, 917, 5, 921, 617, 618, 8, 308, 944, 594, 958, 411, 1027, 1029, 481, 482, 517, 453, 503, 521, 483, 1050, 435, 403, 1053, 484, 485, 426, 427, 1069, 350, 1153, 349, 443, 316, 1140, 575, 1104, 450, 1193, 1149, 343, 486, 487, 366, 1172, 382, 1188, 431, 1195, 1203, 339, 535, 562); protected $ruleToNonTerminal = array(0, 1, 3, 3, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 10, 11, 11, 12, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 17, 17, 18, 18, 20, 20, 16, 16, 21, 21, 22, 22, 23, 23, 24, 24, 19, 19, 25, 27, 27, 28, 29, 29, 31, 30, 30, 30, 30, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 13, 13, 53, 53, 55, 54, 54, 47, 47, 57, 57, 58, 58, 14, 15, 15, 15, 61, 61, 61, 62, 62, 65, 65, 63, 63, 67, 67, 40, 40, 49, 49, 52, 52, 52, 51, 51, 68, 41, 41, 41, 41, 69, 69, 70, 70, 71, 71, 38, 38, 34, 34, 72, 36, 36, 73, 35, 35, 37, 37, 48, 48, 48, 59, 59, 75, 75, 76, 76, 78, 78, 78, 77, 77, 60, 60, 79, 79, 79, 80, 80, 81, 81, 81, 43, 43, 82, 82, 82, 44, 44, 83, 83, 84, 84, 64, 85, 85, 85, 85, 90, 90, 91, 91, 92, 92, 92, 92, 92, 93, 94, 94, 89, 89, 86, 86, 88, 88, 96, 96, 95, 95, 95, 95, 95, 95, 87, 87, 98, 97, 97, 45, 45, 39, 39, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 33, 33, 46, 46, 103, 103, 104, 104, 104, 104, 110, 99, 99, 106, 106, 112, 112, 113, 114, 114, 114, 114, 114, 114, 66, 66, 56, 56, 56, 56, 100, 100, 118, 118, 115, 115, 119, 119, 119, 119, 101, 101, 101, 105, 105, 105, 111, 111, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 26, 26, 26, 26, 26, 26, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 109, 109, 102, 102, 102, 102, 125, 125, 128, 128, 127, 127, 129, 129, 50, 50, 50, 50, 131, 131, 130, 130, 130, 130, 130, 132, 132, 117, 117, 120, 120, 116, 116, 134, 133, 133, 133, 133, 121, 121, 121, 121, 108, 108, 122, 122, 122, 122, 74, 135, 135, 136, 136, 136, 107, 107, 137, 137, 138, 138, 138, 138, 138, 123, 123, 123, 123, 140, 141, 139, 139, 139, 139, 139, 139, 139, 142, 142, 142); protected $ruleToLength = array(1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 4, 3, 4, 2, 3, 1, 1, 7, 6, 3, 1, 3, 1, 3, 1, 1, 3, 1, 3, 1, 2, 3, 1, 3, 3, 1, 3, 2, 0, 1, 1, 1, 1, 1, 3, 5, 8, 3, 5, 9, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 1, 2, 2, 5, 7, 9, 5, 6, 3, 3, 2, 2, 1, 1, 1, 0, 2, 8, 0, 4, 1, 3, 0, 1, 0, 1, 10, 7, 6, 5, 1, 2, 2, 0, 2, 0, 2, 0, 2, 1, 3, 1, 4, 1, 4, 1, 1, 4, 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, 1, 1, 4, 0, 2, 3, 0, 2, 4, 0, 2, 0, 3, 1, 2, 1, 1, 0, 1, 3, 4, 6, 1, 1, 1, 0, 1, 0, 2, 2, 3, 3, 1, 3, 1, 2, 2, 3, 1, 1, 2, 4, 3, 1, 1, 3, 2, 0, 1, 3, 3, 9, 3, 1, 3, 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, 1, 3, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 3, 1, 0, 1, 1, 3, 3, 4, 4, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 5, 4, 3, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 2, 1, 2, 10, 11, 3, 3, 2, 4, 4, 3, 4, 4, 4, 4, 7, 3, 2, 0, 4, 1, 3, 2, 2, 4, 6, 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 4, 4, 0, 2, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 3, 1, 4, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 1, 3, 1, 1, 3, 3, 0, 2, 0, 1, 3, 1, 3, 1, 1, 1, 1, 1, 6, 4, 3, 4, 2, 4, 4, 1, 3, 1, 2, 1, 1, 4, 1, 1, 3, 6, 4, 4, 4, 4, 1, 4, 0, 1, 1, 3, 1, 1, 4, 3, 1, 1, 1, 0, 0, 2, 3, 1, 3, 1, 4, 2, 2, 2, 2, 1, 2, 1, 1, 1, 4, 3, 3, 3, 6, 3, 1, 1, 1); protected function initReduceCallbacks() { $this->reduceCallbacks = [0 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 1 => function ($stackPos) { $this->semValue = $this->handleNamespaces($this->semStack[$stackPos - (1 - 1)]); }, 2 => function ($stackPos) { if (\is_array($this->semStack[$stackPos - (2 - 2)])) { $this->semValue = \array_merge($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]); } else { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; } }, 3 => function ($stackPos) { $this->semValue = array(); }, 4 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; } if ($nop !== null) { $this->semStack[$stackPos - (1 - 1)][] = $nop; } $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 5 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 6 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 7 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 8 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 9 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 10 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 11 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 12 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 13 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 14 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 15 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 16 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 17 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 18 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 19 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 20 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 21 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 22 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 23 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 24 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 25 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 26 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 27 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 28 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 29 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 30 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 31 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 32 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 33 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 34 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 35 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 36 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 37 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 38 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 39 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 40 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 41 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 42 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 43 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 44 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 45 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 46 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 47 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 48 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 49 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 50 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 51 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 52 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 53 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 54 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 55 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 56 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 57 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 58 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 59 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 60 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 61 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 62 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 63 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 64 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 65 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 66 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 67 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 68 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 69 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 70 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 71 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 72 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 73 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 74 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 75 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 76 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 77 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 78 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 79 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 80 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 81 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 82 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 83 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 84 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 85 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 86 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 87 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 88 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 89 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name(\substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 90 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable(\substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 91 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 92 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 93 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 94 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 95 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_($this->semStack[$stackPos - (3 - 2)], null, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); $this->semValue->setAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_::KIND_SEMICOLON); $this->checkNamespace($this->semValue); }, 96 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_($this->semStack[$stackPos - (5 - 2)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); $this->semValue->setAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($this->semValue); }, 97 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_(null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); $this->semValue->setAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($this->semValue); }, 98 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_($this->semStack[$stackPos - (3 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 99 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_($this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 100 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 101 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 102 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION; }, 103 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT; }, 104 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 6)], $this->semStack[$stackPos - (7 - 2)], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); }, 105 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 5)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 106 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 107 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 108 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 109 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 110 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 111 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 112 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse($this->semStack[$stackPos - (1 - 1)], null, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos - (1 - 1)); }, 113 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos - (3 - 3)); }, 114 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse($this->semStack[$stackPos - (1 - 1)], null, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos - (1 - 1)); }, 115 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos - (3 - 3)); }, 116 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; $this->semValue->type = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL; }, 117 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; $this->semValue->type = $this->semStack[$stackPos - (2 - 1)]; }, 118 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 119 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 120 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Const_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 121 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 122 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 123 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Const_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 124 => function ($stackPos) { if (\is_array($this->semStack[$stackPos - (2 - 2)])) { $this->semValue = \array_merge($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]); } else { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; } }, 125 => function ($stackPos) { $this->semValue = array(); }, 126 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; } if ($nop !== null) { $this->semStack[$stackPos - (1 - 1)][] = $nop; } $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 127 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 128 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 129 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 130 => function ($stackPos) { throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 131 => function ($stackPos) { if ($this->semStack[$stackPos - (3 - 2)]) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; $attrs = $this->startAttributeStack[$stackPos - (3 - 1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) { $stmts[0]->setAttribute('comments', \array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); } } else { $startAttributes = $this->startAttributeStack[$stackPos - (3 - 1)]; if (isset($startAttributes['comments'])) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; } if (null === $this->semValue) { $this->semValue = array(); } } }, 132 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_($this->semStack[$stackPos - (5 - 2)], ['stmts' => \is_array($this->semStack[$stackPos - (5 - 3)]) ? $this->semStack[$stackPos - (5 - 3)] : array($this->semStack[$stackPos - (5 - 3)]), 'elseifs' => $this->semStack[$stackPos - (5 - 4)], 'else' => $this->semStack[$stackPos - (5 - 5)]], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 133 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_($this->semStack[$stackPos - (8 - 2)], ['stmts' => $this->semStack[$stackPos - (8 - 4)], 'elseifs' => $this->semStack[$stackPos - (8 - 5)], 'else' => $this->semStack[$stackPos - (8 - 6)]], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes); }, 134 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\While_($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 135 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Do_($this->semStack[$stackPos - (5 - 4)], \is_array($this->semStack[$stackPos - (5 - 2)]) ? $this->semStack[$stackPos - (5 - 2)] : array($this->semStack[$stackPos - (5 - 2)]), $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 136 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\For_(['init' => $this->semStack[$stackPos - (9 - 3)], 'cond' => $this->semStack[$stackPos - (9 - 5)], 'loop' => $this->semStack[$stackPos - (9 - 7)], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); }, 137 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Switch_($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 138 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Break_(null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 139 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Break_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 140 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Continue_(null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 141 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Continue_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 142 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_(null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 143 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 144 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Global_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 145 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Static_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 146 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Echo_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 147 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\InlineHTML($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 148 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 149 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 150 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Unset_($this->semStack[$stackPos - (5 - 3)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 151 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos - (7 - 5)][1], 'stmts' => $this->semStack[$stackPos - (7 - 7)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); }, 152 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_($this->semStack[$stackPos - (9 - 3)], $this->semStack[$stackPos - (9 - 7)][0], ['keyVar' => $this->semStack[$stackPos - (9 - 5)], 'byRef' => $this->semStack[$stackPos - (9 - 7)][1], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); }, 153 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Declare_($this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 154 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TryCatch($this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 5)], $this->semStack[$stackPos - (6 - 6)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); }, 155 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Throw_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 156 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Goto_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 157 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Label($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 158 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 159 => function ($stackPos) { $this->semValue = array(); /* means: no statement */ }, 160 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 161 => function ($stackPos) { $startAttributes = $this->startAttributeStack[$stackPos - (1 - 1)]; if (isset($startAttributes['comments'])) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; } if ($this->semValue === null) { $this->semValue = array(); } /* means: no statement */ }, 162 => function ($stackPos) { $this->semValue = array(); }, 163 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 164 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Catch_(array($this->semStack[$stackPos - (8 - 3)]), $this->semStack[$stackPos - (8 - 4)], $this->semStack[$stackPos - (8 - 7)], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes); }, 165 => function ($stackPos) { $this->semValue = null; }, 166 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Finally_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 167 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 168 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 169 => function ($stackPos) { $this->semValue = \false; }, 170 => function ($stackPos) { $this->semValue = \true; }, 171 => function ($stackPos) { $this->semValue = \false; }, 172 => function ($stackPos) { $this->semValue = \true; }, 173 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_($this->semStack[$stackPos - (10 - 3)], ['byRef' => $this->semStack[$stackPos - (10 - 2)], 'params' => $this->semStack[$stackPos - (10 - 5)], 'returnType' => $this->semStack[$stackPos - (10 - 7)], 'stmts' => $this->semStack[$stackPos - (10 - 9)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes); }, 174 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_($this->semStack[$stackPos - (7 - 2)], ['type' => $this->semStack[$stackPos - (7 - 1)], 'extends' => $this->semStack[$stackPos - (7 - 3)], 'implements' => $this->semStack[$stackPos - (7 - 4)], 'stmts' => $this->semStack[$stackPos - (7 - 6)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); $this->checkClass($this->semValue, $stackPos - (7 - 2)); }, 175 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_($this->semStack[$stackPos - (6 - 2)], ['extends' => $this->semStack[$stackPos - (6 - 3)], 'stmts' => $this->semStack[$stackPos - (6 - 5)]], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); $this->checkInterface($this->semValue, $stackPos - (6 - 2)); }, 176 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_($this->semStack[$stackPos - (5 - 2)], ['stmts' => $this->semStack[$stackPos - (5 - 4)]], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 177 => function ($stackPos) { $this->semValue = 0; }, 178 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT; }, 179 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL; }, 180 => function ($stackPos) { $this->semValue = null; }, 181 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; }, 182 => function ($stackPos) { $this->semValue = array(); }, 183 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; }, 184 => function ($stackPos) { $this->semValue = array(); }, 185 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; }, 186 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 187 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 188 => function ($stackPos) { $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]); }, 189 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 190 => function ($stackPos) { $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]); }, 191 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 192 => function ($stackPos) { $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]); }, 193 => function ($stackPos) { $this->semValue = null; }, 194 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 195 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 196 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 197 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\DeclareDeclare($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 198 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 199 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 3)]; }, 200 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 201 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (5 - 3)]; }, 202 => function ($stackPos) { $this->semValue = array(); }, 203 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 204 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Case_($this->semStack[$stackPos - (4 - 2)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 205 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Case_(null, $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 206 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 207 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 208 => function ($stackPos) { $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]); }, 209 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 210 => function ($stackPos) { $this->semValue = array(); }, 211 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 212 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ElseIf_($this->semStack[$stackPos - (3 - 2)], \is_array($this->semStack[$stackPos - (3 - 3)]) ? $this->semStack[$stackPos - (3 - 3)] : array($this->semStack[$stackPos - (3 - 3)]), $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 213 => function ($stackPos) { $this->semValue = array(); }, 214 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 215 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ElseIf_($this->semStack[$stackPos - (4 - 2)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 216 => function ($stackPos) { $this->semValue = null; }, 217 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Else_(\is_array($this->semStack[$stackPos - (2 - 2)]) ? $this->semStack[$stackPos - (2 - 2)] : array($this->semStack[$stackPos - (2 - 2)]), $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 218 => function ($stackPos) { $this->semValue = null; }, 219 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Else_($this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 220 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false); }, 221 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (2 - 2)], \true); }, 222 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false); }, 223 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 224 => function ($stackPos) { $this->semValue = array(); }, 225 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 226 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 227 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Param($this->semStack[$stackPos - (4 - 4)], null, $this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 2)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); $this->checkParam($this->semValue); }, 228 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Param($this->semStack[$stackPos - (6 - 4)], $this->semStack[$stackPos - (6 - 6)], $this->semStack[$stackPos - (6 - 1)], $this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 3)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); $this->checkParam($this->semValue); }, 229 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 230 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('array', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 231 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('callable', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 232 => function ($stackPos) { $this->semValue = null; }, 233 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 234 => function ($stackPos) { $this->semValue = null; }, 235 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; }, 236 => function ($stackPos) { $this->semValue = array(); }, 237 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 238 => function ($stackPos) { $this->semValue = array(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($this->semStack[$stackPos - (3 - 2)], \false, \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes)); }, 239 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 240 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 241 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($this->semStack[$stackPos - (1 - 1)], \false, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 242 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($this->semStack[$stackPos - (2 - 2)], \true, \false, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 243 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($this->semStack[$stackPos - (2 - 2)], \false, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 244 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 245 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 246 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 247 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 248 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 249 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 250 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 251 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\StaticVar($this->semStack[$stackPos - (1 - 1)], null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 252 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\StaticVar($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 253 => function ($stackPos) { if ($this->semStack[$stackPos - (2 - 2)] !== null) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; } }, 254 => function ($stackPos) { $this->semValue = array(); }, 255 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; } if ($nop !== null) { $this->semStack[$stackPos - (1 - 1)][] = $nop; } $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 256 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); $this->checkProperty($this->semValue, $stackPos - (3 - 1)); }, 257 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst($this->semStack[$stackPos - (3 - 2)], 0, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 258 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod($this->semStack[$stackPos - (9 - 4)], ['type' => $this->semStack[$stackPos - (9 - 1)], 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 6)], 'returnType' => $this->semStack[$stackPos - (9 - 8)], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); $this->checkClassMethod($this->semValue, $stackPos - (9 - 1)); }, 259 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 260 => function ($stackPos) { $this->semValue = array(); }, 261 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 262 => function ($stackPos) { $this->semValue = array(); }, 263 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 264 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 265 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (5 - 1)][0], $this->semStack[$stackPos - (5 - 1)][1], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 266 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], $this->semStack[$stackPos - (4 - 3)], null, $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 267 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 268 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 269 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]); }, 270 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 271 => function ($stackPos) { $this->semValue = array(null, $this->semStack[$stackPos - (1 - 1)]); }, 272 => function ($stackPos) { $this->semValue = null; }, 273 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 274 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 275 => function ($stackPos) { $this->semValue = 0; }, 276 => function ($stackPos) { $this->semValue = 0; }, 277 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 278 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 279 => function ($stackPos) { $this->checkModifier($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $stackPos - (2 - 2)); $this->semValue = $this->semStack[$stackPos - (2 - 1)] | $this->semStack[$stackPos - (2 - 2)]; }, 280 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC; }, 281 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED; }, 282 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE; }, 283 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC; }, 284 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT; }, 285 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL; }, 286 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 287 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 288 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier(\substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 289 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\PropertyProperty($this->semStack[$stackPos - (1 - 1)], null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 290 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\PropertyProperty($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 291 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 292 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 293 => function ($stackPos) { $this->semValue = array(); }, 294 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 295 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 296 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 297 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 298 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 299 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 300 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 301 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Clone_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 302 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 303 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 304 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 305 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 306 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 307 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 308 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 309 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 310 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 311 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 312 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 313 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 314 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Coalesce($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 315 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 316 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 317 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 318 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 319 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 320 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 321 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 322 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 323 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 324 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 325 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 326 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 327 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 328 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 329 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 330 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 331 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 332 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 333 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 334 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 335 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 336 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 337 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 338 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 339 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BitwiseNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 340 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 341 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 342 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 343 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 344 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Spaceship($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 345 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 346 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 347 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 348 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 349 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 350 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 351 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 352 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary($this->semStack[$stackPos - (5 - 1)], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 353 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary($this->semStack[$stackPos - (4 - 1)], null, $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 354 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 355 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Isset_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 356 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Empty_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 357 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_($this->semStack[$stackPos - (2 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 358 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_($this->semStack[$stackPos - (2 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 359 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Eval_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 360 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_($this->semStack[$stackPos - (2 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 361 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_($this->semStack[$stackPos - (2 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 362 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Int_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 363 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes; $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos - (2 - 1)]); $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double($this->semStack[$stackPos - (2 - 2)], $attrs); }, 364 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\String_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 365 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Array_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 366 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Object_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 367 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Bool_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 368 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Unset_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 369 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes; $attrs['kind'] = \strtolower($this->semStack[$stackPos - (2 - 1)]) === 'exit' ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_::KIND_EXIT : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_::KIND_DIE; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_($this->semStack[$stackPos - (2 - 2)], $attrs); }, 370 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ErrorSuppress($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 371 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 372 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 373 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 374 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ShellExec($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 375 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Print_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 376 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_(null, null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 377 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 378 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure(['static' => \false, 'byRef' => $this->semStack[$stackPos - (10 - 2)], 'params' => $this->semStack[$stackPos - (10 - 4)], 'uses' => $this->semStack[$stackPos - (10 - 6)], 'returnType' => $this->semStack[$stackPos - (10 - 7)], 'stmts' => $this->semStack[$stackPos - (10 - 9)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes); }, 379 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure(['static' => \true, 'byRef' => $this->semStack[$stackPos - (11 - 3)], 'params' => $this->semStack[$stackPos - (11 - 5)], 'uses' => $this->semStack[$stackPos - (11 - 7)], 'returnType' => $this->semStack[$stackPos - (11 - 8)], 'stmts' => $this->semStack[$stackPos - (11 - 10)]], $this->startAttributeStack[$stackPos - (11 - 1)] + $this->endAttributes); }, 380 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 381 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 382 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_($this->semStack[$stackPos - (2 - 2)], null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 383 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_($this->semStack[$stackPos - (4 - 4)], $this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 384 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes; $attrs['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_::KIND_LONG; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($this->semStack[$stackPos - (4 - 3)], $attrs); }, 385 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes; $attrs['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_::KIND_SHORT; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($this->semStack[$stackPos - (3 - 2)], $attrs); }, 386 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 387 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes; $attrs['kind'] = $this->semStack[$stackPos - (4 - 1)][0] === "'" || $this->semStack[$stackPos - (4 - 1)][1] === "'" && ($this->semStack[$stackPos - (4 - 1)][0] === 'b' || $this->semStack[$stackPos - (4 - 1)][0] === 'B') ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_SINGLE_QUOTED : \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_DOUBLE_QUOTED; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parse($this->semStack[$stackPos - (4 - 1)]), $attrs), $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 388 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 389 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 390 => function ($stackPos) { $this->semValue = array(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos - (7 - 3)], 'implements' => $this->semStack[$stackPos - (7 - 4)], 'stmts' => $this->semStack[$stackPos - (7 - 6)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes), $this->semStack[$stackPos - (7 - 2)]); $this->checkClass($this->semValue[0], -1); }, 391 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 392 => function ($stackPos) { list($class, $ctorArgs) = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 393 => function ($stackPos) { $this->semValue = array(); }, 394 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 3)]; }, 395 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 396 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 397 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClosureUse($this->semStack[$stackPos - (2 - 2)], $this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 398 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 399 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 400 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall($this->semStack[$stackPos - (6 - 1)], $this->semStack[$stackPos - (6 - 4)], $this->semStack[$stackPos - (6 - 6)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 401 => function ($stackPos) { $this->semValue = $this->fixupPhp5StaticPropCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 402 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 403 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 404 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 405 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 406 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 407 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 408 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified(\substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 409 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\Relative(\substr($this->semStack[$stackPos - (1 - 1)], 10), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 410 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 411 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 412 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 413 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 414 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 415 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 416 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 417 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 418 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 419 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 420 => function ($stackPos) { $this->semValue = null; }, 421 => function ($stackPos) { $this->semValue = null; }, 422 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 423 => function ($stackPos) { $this->semValue = array(); }, 424 => function ($stackPos) { $this->semValue = array(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parseEscapeSequences($this->semStack[$stackPos - (1 - 1)], '`', \false), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes)); }, 425 => function ($stackPos) { foreach ($this->semStack[$stackPos - (1 - 1)] as $s) { if ($s instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart) { $s->value = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parseEscapeSequences($s->value, '`', \false); } } $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 426 => function ($stackPos) { $this->semValue = array(); }, 427 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 428 => function ($stackPos) { $this->semValue = $this->parseLNumber($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes, \true); }, 429 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber::parse($this->semStack[$stackPos - (1 - 1)]), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 430 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes; $attrs['kind'] = $this->semStack[$stackPos - (1 - 1)][0] === "'" || $this->semStack[$stackPos - (1 - 1)][1] === "'" && ($this->semStack[$stackPos - (1 - 1)][0] === 'b' || $this->semStack[$stackPos - (1 - 1)][0] === 'B') ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_SINGLE_QUOTED : \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_DOUBLE_QUOTED; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parse($this->semStack[$stackPos - (1 - 1)], \false), $attrs); }, 431 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Line($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 432 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\File($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 433 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 434 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 435 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 436 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Method($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 437 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 438 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 439 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)], \false); }, 440 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos - (2 - 1)], '', $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (2 - 2)] + $this->endAttributeStack[$stackPos - (2 - 2)], \false); }, 441 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 442 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 443 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 444 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 445 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 446 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 447 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 448 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 449 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 450 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 451 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 452 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 453 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 454 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 455 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 456 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 457 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 458 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 459 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 460 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 461 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 462 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 463 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 464 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 465 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 466 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 467 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BitwiseNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 468 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 469 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 470 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 471 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 472 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 473 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 474 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 475 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 476 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary($this->semStack[$stackPos - (5 - 1)], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 477 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary($this->semStack[$stackPos - (4 - 1)], null, $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 478 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 479 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 480 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 481 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 482 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 483 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 484 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes; $attrs['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_DOUBLE_QUOTED; foreach ($this->semStack[$stackPos - (3 - 2)] as $s) { if ($s instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart) { $s->value = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parseEscapeSequences($s->value, '"', \true); } } $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\Encapsed($this->semStack[$stackPos - (3 - 2)], $attrs); }, 485 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)], \true); }, 486 => function ($stackPos) { $this->semValue = array(); }, 487 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 488 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 489 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 490 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 491 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 492 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (3 - 3)], $this->semStack[$stackPos - (3 - 1)], \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 493 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 494 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 495 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 496 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 497 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 498 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 5)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 499 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 500 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 501 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 502 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 503 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 504 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 505 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 506 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 507 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 508 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 509 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 510 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 511 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 512 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 513 => function ($stackPos) { $var = \substr($this->semStack[$stackPos - (1 - 1)], 1); $this->semValue = \is_string($var) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes) : $var; }, 514 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 515 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch($this->semStack[$stackPos - (6 - 1)], $this->semStack[$stackPos - (6 - 5)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 516 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 517 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 518 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 519 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 520 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 521 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 522 => function ($stackPos) { $this->semValue = null; }, 523 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 524 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 525 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 526 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 527 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); $this->errorState = 2; }, 528 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\List_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 529 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 530 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 531 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 532 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 533 => function ($stackPos) { $this->semValue = null; }, 534 => function ($stackPos) { $this->semValue = array(); }, 535 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 536 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 537 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 538 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (3 - 3)], $this->semStack[$stackPos - (3 - 1)], \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 539 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 540 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (4 - 4)], $this->semStack[$stackPos - (4 - 1)], \true, $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 541 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (2 - 2)], null, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 542 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (2 - 2)], null, \false, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 543 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 544 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 545 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 546 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]); }, 547 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 548 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 549 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 550 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 551 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 552 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 553 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 554 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 4)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 555 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 556 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 557 => function ($stackPos) { $this->semValue = $this->parseNumString($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 558 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }]; } } '", "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "'+'", "'-'", "'.'", "'*'", "'/'", "'%'", "'!'", "T_INSTANCEOF", "'~'", "T_INC", "T_DEC", "T_INT_CAST", "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", "T_BOOL_CAST", "T_UNSET_CAST", "'@'", "T_POW", "'['", "T_NEW", "T_CLONE", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_MATCH", "T_ENDSWITCH", "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_GOTO", "T_FUNCTION", "T_FN", "T_CONST", "T_RETURN", "T_TRY", "T_CATCH", "T_FINALLY", "T_USE", "T_INSTEADOF", "T_GLOBAL", "T_STATIC", "T_ABSTRACT", "T_FINAL", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", "T_VAR", "T_UNSET", "T_ISSET", "T_EMPTY", "T_HALT_COMPILER", "T_CLASS", "T_TRAIT", "T_INTERFACE", "T_EXTENDS", "T_IMPLEMENTS", "T_OBJECT_OPERATOR", "T_NULLSAFE_OBJECT_OPERATOR", "T_LIST", "T_ARRAY", "T_CALLABLE", "T_CLASS_C", "T_TRAIT_C", "T_METHOD_C", "T_FUNC_C", "T_LINE", "T_FILE", "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", "T_ELLIPSIS", "T_NAME_FULLY_QUALIFIED", "T_NAME_QUALIFIED", "T_NAME_RELATIVE", "T_ATTRIBUTE", "';'", "']'", "'{'", "'}'", "'('", "')'", "'`'", "'\"'", "'\$'"); protected $tokenToSymbol = array(0, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 55, 163, 165, 164, 54, 37, 165, 160, 161, 52, 49, 8, 50, 51, 53, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 31, 156, 43, 16, 45, 30, 67, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 69, 165, 157, 36, 165, 162, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 158, 35, 159, 57, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 38, 39, 40, 41, 42, 44, 46, 47, 48, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155); protected $action = array(130, 131, 132, 555, 133, 134, -32766, 704, 705, 706, 135, 36, -543, -552, 455, -32766, -543, -32766, -32766, -32766, -552, 1152, 778, 927, -549, 969, 970, 0, -32766, -32766, -32766, -549, -32766, 1219, -32766, 245, -32766, 962, -32766, -32766, -32766, -32766, -32766, 461, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, 124, -331, 707, -331, -32766, 388, 1031, 1032, 1033, 1030, 1029, 1028, -32766, 435, 430, 2, 261, 136, 371, 711, 712, 713, 714, 391, 789, 397, 1031, 1032, 1033, 1030, 1029, 1028, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 745, 556, 746, 747, 748, 749, 737, 738, 372, 373, 740, 741, 726, 727, 728, 730, 731, 732, 332, 771, 772, 773, 774, 775, 733, 734, 557, 558, 766, 757, 755, 756, 752, 753, -294, -189, 559, 560, 751, 561, 562, 563, 564, 565, 566, 1235, 456, 783, -503, 889, 754, 567, 568, 928, 137, -32766, -32766, -32766, 130, 131, 132, 555, 133, 134, 983, 704, 705, 706, 135, 36, -32766, -32766, -32766, -32766, -552, -32766, -32766, -32766, -552, 1152, 547, 101, 102, 103, 583, -549, -32766, -32766, -32766, -549, -32766, -32766, -32766, 245, -32766, 80, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, 959, 958, 957, -32766, -32766, -503, -503, 707, 1264, -32766, 388, 1265, -32766, -32766, -32766, 235, 784, -32766, 778, 19, -503, 261, 136, 371, 711, 712, 713, 714, -32766, -32766, 397, 788, -503, -32766, -509, -32766, -32766, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 745, 556, 746, 747, 748, 749, 737, 738, 372, 373, 740, 741, 726, 727, 728, 730, 731, 732, 332, 771, 772, 773, 774, 775, 733, 734, 557, 558, 766, 757, 755, 756, 752, 753, -294, -189, 559, 560, 751, 561, 562, 563, 564, 565, 566, 309, 81, 82, 83, 139, 754, 567, 568, 681, 137, 729, 699, 700, 701, 702, 703, 1239, 704, 705, 706, 742, 743, 33, 1238, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 31, 263, -32766, -32766, -32766, 104, 105, 106, 577, 263, 1216, 126, -188, 107, 142, 440, 441, 707, -32766, -32766, -32766, 107, -254, -32766, 247, -32766, -32766, -32766, -32766, -32766, -32766, 708, 709, 710, 711, 712, 713, 714, 293, -32766, 776, -32766, -32766, -32766, -32766, -32766, 295, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 745, 768, 746, 747, 748, 749, 737, 738, 739, 767, 740, 741, 726, 727, 728, 730, 731, 732, 770, 771, 772, 773, 774, 775, 733, 734, 735, 736, 766, 757, 755, 756, 752, 753, 529, 311, 744, 750, 751, 758, 759, 761, 760, 762, 763, 234, -32766, -32766, -32766, 307, 754, 765, 764, 48, 49, 50, 486, 51, 52, 481, 397, 18, 321, 53, 54, 345, 55, -32766, 982, -32766, -32766, -32766, -32766, -32766, -32766, -32767, -32767, -32767, -32767, -32767, 349, -32767, -32767, -32767, -32767, 99, 100, 101, 102, 103, 814, 354, 815, 1191, 356, 1152, 871, 271, 408, 871, 56, 57, 409, 814, 410, 815, 58, -188, 59, 240, 241, 60, 61, 62, 63, 64, 65, 66, 67, -32766, 26, 262, 68, 412, 487, 411, 672, 967, 1185, 1186, 488, 1150, 1216, 1154, 1153, 1155, 1183, 40, 23, 489, 1009, 490, -82, 491, 147, 492, 969, 970, 493, 494, 786, 429, 430, 42, 43, 413, 418, 415, 871, 44, 495, 391, 496, 497, 248, 344, 320, 1159, 1154, 1153, 1155, 793, 896, 498, 499, 500, 148, 1008, 861, 692, 787, 861, 967, 1254, 501, 502, 150, 1173, 1174, 1175, 1176, 1170, 1171, 281, 624, 24, 26, -14, 151, 1177, 1172, 969, 970, 1154, 1153, 1155, 282, -82, 1216, -502, 152, 69, 1183, 305, 306, 311, 34, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 154, -149, -149, -149, 639, 640, 146, 376, 1159, 1159, 861, 615, 616, 32, 243, 35, -149, 1216, -149, 121, -149, 873, -149, 667, 873, 122, 667, 242, 1067, 1069, 501, 502, 414, 1173, 1174, 1175, 1176, 1170, 1171, -501, 127, -502, -502, 496, 497, 1177, 1172, -504, 128, 871, 424, 425, 847, 896, -107, -107, -502, 71, 442, 443, 306, 311, -107, -32766, 432, 433, -49, 141, -502, 1152, -508, 155, 156, 780, 157, -84, -32766, -32766, -32766, 673, -32766, -76, -32766, 873, -32766, 667, -149, -32766, 1216, 1216, 1179, 282, -32766, -32766, -32766, -73, 73, -71, -32766, -32766, 311, -501, -501, 129, -32766, 388, -70, -69, -32766, -504, -504, -68, -32766, -67, 1152, -66, -501, -65, 871, -64, 275, -32766, -32766, -32766, -504, -32766, -45, -32766, -501, -32766, -16, 861, -32766, 145, -107, 264, -504, -32766, -32766, -32766, 682, 72, 244, -32766, -32766, -32766, 685, 782, 674, -32766, 388, 1152, 669, 871, -501, 870, 144, -32766, -32766, -32766, -32766, 272, -32766, 282, -32766, 273, -32766, 73, 73, -32766, 1216, 311, 311, 276, -32766, -32766, -32766, 885, -32766, 246, -32766, -32766, 277, 677, 1152, 314, -32766, 388, -4, 871, 263, -32766, -32766, -32766, -32766, -32766, 107, -32766, 143, -32766, 861, 778, -32766, 871, 873, -32766, 667, -32766, -32766, -32766, 625, 647, 871, -32766, -32766, -32766, -501, -501, 787, -32766, 388, 1152, 1037, -32766, 969, 970, 1266, -32766, -32766, -32766, -32766, -501, -32766, 531, -32766, 861, -32766, 660, 871, -32766, 630, 535, 683, -501, -32766, -32766, -32766, 138, -32766, 642, -32766, -32766, 1023, 311, 1152, 20, -32766, 388, 437, 466, 631, -32766, -32766, -32766, -32766, -32766, 643, -32766, 286, -32766, -506, 861, -32766, 913, 407, 667, 613, -32766, -32766, -32766, -32766, 284, -467, -32766, -32766, 861, 46, 283, 282, -32766, 388, 686, 897, 414, 861, 402, 898, -32766, 294, 38, 280, -232, -232, -232, 496, 497, 1007, 414, 873, 26, 667, 1190, 786, 806, 896, -107, -107, 1192, 496, 497, 861, 1216, 47, -457, 8, 1183, 22, 847, 896, -107, -107, 347, -506, -506, 541, 9, -231, -231, -231, 581, 1180, 887, 414, 39, 873, 848, 667, -4, 289, 290, 689, 690, 852, 496, 497, 937, 914, 1261, 873, -506, 667, -232, 847, 896, -107, -107, 921, 873, 911, 667, 922, 850, 909, -537, 502, 123, 1173, 1174, 1175, 1176, 1170, 1171, 1012, 1015, 291, 292, 1016, 1013, 1177, 1172, 1014, 1020, 1263, 873, 30, 667, -231, 304, 798, 348, 71, 1205, 1223, 306, 311, 1257, 618, -535, 346, 668, -107, 125, -107, 671, 675, 676, 678, 285, 679, 680, -107, -107, -107, -107, -107, -107, -107, 684, 670, -257, 809, 808, 817, 895, 929, 816, 1262, 894, 892, 893, 1138, 880, 888, 878, 919, 920, 1260, 1217, 1206, 1224, 1230, 1233, 0, -509, -508, -507, 1, 27, 28, 37, 41, 45, 70, 74, -308, -255, 75, 76, 77, 78, 79, 140, 149, 153, 239, 310, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 403, 404, 0, -254, 12, 13, 14, 15, 17, 375, 457, 458, 465, 468, 469, 470, 471, 475, 476, 477, 484, 654, 1163, 1106, 1181, 984, 1142, -259, -99, 11, 16, 25, 279, 374, 574, 578, 605, 659, 1110, 1158, 1107, 1236, 0, -471, 1123, 0, 1184); protected $actionCheck = array(2, 3, 4, 5, 6, 7, 115, 9, 10, 11, 12, 13, 157, 1, 31, 73, 161, 9, 10, 11, 8, 79, 79, 31, 1, 134, 135, 0, 86, 87, 88, 8, 90, 1, 92, 37, 94, 1, 30, 97, 32, 33, 34, 101, 102, 103, 104, 9, 10, 11, 108, 109, 14, 105, 56, 107, 114, 115, 115, 116, 117, 118, 119, 120, 122, 105, 106, 8, 70, 71, 72, 73, 74, 75, 76, 115, 1, 79, 115, 116, 117, 118, 119, 120, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 8, 8, 133, 134, 135, 136, 137, 138, 139, 140, 141, 1, 158, 79, 69, 1, 147, 148, 149, 156, 151, 9, 10, 11, 2, 3, 4, 5, 6, 7, 161, 9, 10, 11, 12, 13, 9, 10, 11, 73, 157, 9, 10, 11, 161, 79, 80, 49, 50, 51, 50, 157, 86, 87, 88, 161, 90, 30, 92, 37, 94, 158, 30, 97, 32, 33, 34, 35, 102, 103, 104, 118, 119, 120, 108, 109, 131, 132, 56, 79, 114, 115, 82, 9, 10, 11, 14, 153, 122, 79, 8, 146, 70, 71, 72, 73, 74, 75, 76, 9, 10, 79, 156, 158, 30, 160, 32, 33, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 161, 161, 133, 134, 135, 136, 137, 138, 139, 140, 141, 69, 9, 10, 11, 158, 147, 148, 149, 158, 151, 2, 3, 4, 5, 6, 7, 1, 9, 10, 11, 12, 13, 30, 8, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 8, 56, 9, 10, 11, 52, 53, 54, 1, 56, 81, 8, 8, 68, 8, 131, 132, 56, 9, 10, 11, 68, 161, 30, 8, 32, 33, 34, 35, 36, 37, 70, 71, 72, 73, 74, 75, 76, 8, 30, 79, 32, 33, 34, 35, 36, 8, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 84, 164, 133, 134, 135, 136, 137, 138, 139, 140, 141, 96, 9, 10, 11, 8, 147, 148, 149, 2, 3, 4, 5, 6, 7, 105, 79, 107, 8, 12, 13, 8, 15, 30, 1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 8, 43, 44, 45, 46, 47, 48, 49, 50, 51, 105, 8, 107, 143, 8, 79, 1, 30, 8, 1, 49, 50, 8, 105, 8, 107, 55, 161, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 9, 69, 70, 71, 72, 73, 8, 31, 115, 77, 78, 79, 115, 81, 152, 153, 154, 85, 86, 87, 88, 159, 90, 31, 92, 14, 94, 134, 135, 97, 98, 152, 105, 106, 102, 103, 104, 105, 106, 1, 108, 109, 115, 116, 117, 37, 114, 115, 1, 152, 153, 154, 8, 126, 122, 123, 124, 14, 156, 83, 158, 81, 83, 115, 84, 133, 134, 14, 136, 137, 138, 139, 140, 141, 142, 74, 75, 69, 31, 14, 148, 149, 134, 135, 152, 153, 154, 155, 96, 81, 69, 14, 160, 85, 162, 163, 164, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 14, 74, 75, 76, 74, 75, 100, 101, 1, 1, 83, 110, 111, 144, 145, 14, 89, 81, 91, 16, 93, 156, 95, 158, 156, 16, 158, 37, 58, 59, 133, 134, 105, 136, 137, 138, 139, 140, 141, 69, 16, 131, 132, 116, 117, 148, 149, 69, 16, 1, 105, 106, 125, 126, 127, 128, 146, 160, 105, 106, 163, 164, 126, 73, 127, 128, 31, 16, 158, 79, 160, 16, 16, 79, 16, 31, 86, 87, 88, 31, 90, 31, 92, 156, 94, 158, 159, 97, 81, 81, 1, 155, 102, 103, 104, 31, 160, 31, 108, 109, 164, 131, 132, 31, 114, 115, 31, 31, 73, 131, 132, 31, 122, 31, 79, 31, 146, 31, 1, 31, 30, 86, 87, 88, 146, 90, 31, 92, 158, 94, 31, 83, 97, 31, 126, 31, 158, 102, 103, 104, 31, 151, 37, 108, 109, 73, 31, 153, 31, 114, 115, 79, 158, 1, 69, 31, 31, 122, 86, 87, 88, 35, 90, 155, 92, 35, 94, 160, 160, 97, 81, 164, 164, 35, 102, 103, 104, 37, 73, 37, 108, 109, 35, 31, 79, 35, 114, 115, 0, 1, 56, 86, 87, 88, 122, 90, 68, 92, 69, 94, 83, 79, 97, 1, 156, 115, 158, 102, 103, 104, 89, 76, 1, 108, 109, 73, 131, 132, 81, 114, 115, 79, 81, 84, 134, 135, 82, 122, 86, 87, 88, 146, 90, 84, 92, 83, 94, 91, 1, 97, 95, 88, 31, 158, 102, 103, 104, 158, 73, 93, 108, 109, 121, 164, 79, 96, 114, 115, 96, 96, 99, 86, 87, 88, 122, 90, 99, 92, 113, 94, 69, 83, 97, 156, 126, 158, 112, 102, 103, 104, 115, 130, 146, 108, 109, 83, 69, 129, 155, 114, 115, 159, 126, 105, 83, 107, 126, 122, 129, 156, 112, 99, 100, 101, 116, 117, 1, 105, 156, 69, 158, 143, 152, 125, 126, 127, 128, 143, 116, 117, 83, 81, 69, 146, 146, 85, 146, 125, 126, 127, 128, 146, 131, 132, 150, 147, 99, 100, 101, 150, 157, 151, 105, 156, 156, 159, 158, 159, 131, 132, 156, 156, 156, 116, 117, 156, 156, 159, 156, 158, 158, 159, 125, 126, 127, 128, 156, 156, 156, 158, 156, 156, 156, 160, 134, 158, 136, 137, 138, 139, 140, 141, 156, 156, 131, 132, 156, 156, 148, 149, 156, 156, 159, 156, 158, 158, 159, 158, 157, 146, 160, 157, 157, 163, 164, 157, 157, 160, 158, 158, 105, 158, 107, 158, 158, 158, 158, 112, 158, 158, 115, 116, 117, 118, 119, 120, 121, 158, 158, 161, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, -1, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 159, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, -1, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, -1, 162, 162, -1, 163); protected $actionBase = array(0, -2, 151, 555, 816, 830, 865, 379, 717, 622, 862, 676, 780, 780, 839, 780, 493, 745, 301, 301, -57, 301, 301, 496, 496, 496, 618, 618, 618, 618, -58, -58, 95, 700, 733, 770, 663, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 75, -8, 347, 629, 986, 992, 988, 993, 984, 983, 987, 989, 994, 915, 916, 753, 917, 918, 919, 920, 990, 877, 985, 991, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 508, 38, 219, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 156, 156, 156, 203, 525, 525, 8, 598, 161, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 349, 333, 435, 435, 435, 435, 435, 436, 436, 436, 436, 933, 564, 636, 635, 465, -52, 127, 127, 718, 718, 759, 410, 410, 410, 444, -109, -109, -109, 74, 538, 396, 348, 414, 414, 414, 414, 414, 802, 998, 139, 139, 139, 139, 414, 414, 414, 606, 713, 713, 881, 293, 293, 293, 713, 383, 777, 497, 383, 497, 129, 793, 32, -40, -145, 793, 829, 845, 23, 12, 788, 573, 788, 767, 863, 898, 995, 82, 789, 913, 795, 914, 224, 678, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 269, 982, 63, 269, 269, 269, 529, 63, 518, 558, 63, 778, 982, 75, 805, 75, 75, 75, 75, 944, 75, 75, 75, 75, 75, 75, 949, 727, 723, 692, -17, 75, -8, 143, 143, 419, 36, 143, 143, 143, 143, 75, 75, 565, 573, 762, 812, 581, 817, 344, 762, 762, 762, 509, 121, 201, 122, 352, 750, 750, 768, 769, 924, 924, 750, 765, 750, 769, 929, 750, 768, 768, 750, 924, 768, 761, 343, 488, 452, 470, 768, 768, 492, 924, 370, 768, 768, 750, 750, 750, 797, 768, 494, 750, 356, 346, 750, 750, 768, 768, 797, 786, 59, 779, 924, 924, 924, 797, 455, 779, 779, 822, 823, 792, 732, 439, 378, 561, 332, 768, 732, 732, 750, 481, 792, 732, 792, 732, 818, 732, 732, 732, 792, 732, 765, 484, 732, 768, 515, 211, 732, 27, 930, 931, 672, 934, 927, 935, 955, 936, 937, 879, 794, 798, 942, 928, 938, 926, 925, 752, 631, 637, 806, 764, 923, 756, 756, 756, 921, 756, 756, 756, 756, 756, 756, 756, 756, 631, 811, 813, 776, 781, 945, 652, 660, 796, 814, 996, 997, 944, 976, 939, 771, 679, 962, 946, 760, 867, 947, 948, 963, 977, 978, 826, 757, 861, 899, 869, 950, 883, 756, 930, 937, 928, 938, 926, 925, 716, 714, 710, 712, 708, 704, 694, 703, 730, 875, 841, 872, 949, 922, 631, 873, 958, 864, 964, 965, 878, 790, 772, 876, 900, 951, 952, 953, 884, 979, 885, 815, 959, 896, 966, 791, 901, 967, 968, 969, 970, 886, 902, 888, 824, 749, 932, 773, 903, 528, 766, 775, 956, 560, 943, 889, 904, 905, 971, 972, 973, 906, 907, 940, 827, 960, 784, 961, 957, 828, 838, 570, 754, 758, 582, 594, 908, 909, 941, 737, 763, 840, 842, 980, 910, 614, 843, 683, 911, 975, 684, 686, 774, 897, 808, 783, 787, 954, 743, 844, 912, 854, 855, 858, 974, 859, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 449, 449, 449, 449, 449, 449, 301, 301, 301, 301, 449, 449, 449, 449, 449, 449, 449, 0, 0, 301, 0, 0, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 285, 414, 414, 285, 0, 285, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 285, 285, 285, 285, 285, 285, 285, 293, 293, 293, 293, 761, 414, 414, 414, 414, -37, 293, 293, 414, 414, -37, 414, 414, 414, 761, 414, 414, 414, 0, 0, 63, 497, 0, 0, 0, 0, 0, 497, 497, 269, 269, 269, 269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 497, 0, 63, 0, 765, 414, 269, 761, 308, 414, 0, 0, 0, 0, 63, 765, 63, 497, 143, 75, 308, 0, 534, 534, 534, 534, 0, 573, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 0, 761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 765, 768, 0, 924, 0, 0, 0, 0, 750, 0, 0, 0, 0, 0, 0, 750, 929, 768, 768, 0, 0, 0, 0, 0, 0, 765, 0, 0, 0, 0, 0, 0, 0, 0, 756, 790, 0, 790, 0, 756, 756, 756); protected $actionDefault = array(3, 32767, 99, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 97, 32767, 32767, 32767, 32767, 32767, 32767, 555, 555, 555, 555, 236, 99, 32767, 32767, 32767, 32767, 431, 350, 350, 350, 32767, 32767, 499, 499, 499, 499, 499, 499, 32767, 32767, 32767, 32767, 32767, 32767, 431, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 97, 32767, 32767, 32767, 35, 5, 6, 8, 9, 48, 15, 32767, 32767, 32767, 32767, 32767, 99, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 548, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 435, 414, 415, 417, 418, 349, 500, 554, 293, 551, 348, 142, 305, 295, 224, 296, 240, 241, 267, 345, 146, 379, 432, 381, 430, 434, 380, 355, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 353, 354, 433, 436, 437, 440, 441, 411, 410, 409, 377, 32767, 32767, 378, 352, 382, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 99, 32767, 384, 383, 400, 401, 398, 399, 402, 403, 404, 405, 406, 32767, 32767, 32767, 32767, 32767, 328, 391, 392, 284, 284, 330, 32767, 32767, 32767, 108, 32767, 32767, 32767, 493, 408, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 99, 32767, 97, 495, 374, 376, 463, 386, 387, 385, 356, 32767, 470, 32767, 99, 472, 32767, 32767, 32767, 32767, 32767, 32767, 494, 32767, 501, 501, 32767, 456, 97, 32767, 32767, 32767, 32767, 262, 32767, 32767, 32767, 32767, 562, 456, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 32767, 107, 32767, 32767, 32767, 97, 185, 32767, 250, 252, 99, 516, 190, 32767, 475, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 468, 190, 190, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 456, 396, 135, 32767, 135, 501, 388, 389, 390, 458, 501, 501, 501, 32767, 32767, 32767, 190, 32767, 473, 473, 97, 97, 97, 97, 468, 32767, 190, 190, 32767, 32767, 190, 108, 96, 96, 96, 96, 190, 190, 96, 100, 98, 190, 190, 32767, 32767, 32767, 205, 190, 96, 32767, 98, 98, 32767, 32767, 190, 190, 205, 207, 98, 209, 32767, 520, 521, 205, 98, 209, 209, 229, 229, 447, 286, 98, 96, 98, 98, 190, 286, 286, 32767, 98, 447, 286, 447, 286, 192, 286, 286, 286, 447, 286, 32767, 98, 286, 190, 96, 96, 286, 32767, 32767, 32767, 458, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 488, 32767, 505, 518, 394, 395, 397, 503, 419, 420, 421, 422, 423, 424, 425, 427, 550, 32767, 462, 32767, 32767, 32767, 32767, 304, 560, 32767, 560, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 561, 32767, 501, 32767, 32767, 32767, 32767, 393, 7, 74, 41, 42, 50, 56, 479, 480, 481, 482, 476, 477, 483, 478, 32767, 484, 526, 32767, 32767, 502, 553, 32767, 32767, 32767, 32767, 32767, 32767, 135, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 488, 32767, 133, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 501, 32767, 32767, 32767, 281, 283, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 501, 32767, 32767, 32767, 269, 271, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 266, 32767, 32767, 344, 32767, 32767, 32767, 32767, 324, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 148, 148, 3, 3, 307, 148, 148, 148, 307, 307, 148, 307, 307, 148, 148, 148, 148, 148, 148, 180, 244, 247, 229, 229, 148, 316, 148); protected $goto = array(190, 190, 655, 781, 663, 399, 629, 964, 971, 972, 393, 297, 298, 317, 549, 303, 398, 318, 400, 607, 361, 365, 534, 572, 576, 161, 161, 161, 161, 187, 187, 171, 173, 209, 191, 204, 187, 187, 187, 187, 187, 188, 188, 188, 188, 188, 188, 182, 183, 184, 185, 186, 206, 204, 207, 509, 510, 389, 511, 513, 514, 515, 516, 517, 518, 519, 520, 1053, 162, 163, 164, 189, 165, 166, 167, 160, 168, 169, 170, 172, 203, 205, 208, 230, 233, 236, 238, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 266, 267, 300, 301, 302, 394, 395, 396, 554, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 174, 225, 175, 192, 193, 194, 231, 182, 183, 184, 185, 186, 206, 1053, 195, 176, 177, 178, 196, 192, 179, 232, 197, 159, 198, 226, 180, 199, 227, 228, 181, 229, 200, 201, 202, 807, 611, 611, 804, 274, 274, 274, 274, 976, 973, 974, 592, 626, 1147, 594, 594, 571, 533, 526, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1250, 1250, 986, 328, 812, 1027, 860, 855, 856, 869, 1026, 813, 857, 810, 858, 859, 811, 803, 1251, 1251, 805, 1250, 863, 912, 936, 910, 910, 908, 910, 687, 363, 526, 1003, 1004, 533, 1253, 525, 945, 940, 1251, 542, 543, 820, 1148, 838, 370, 552, 832, 308, 288, 819, 573, 864, 795, 865, 1200, 1200, 785, 587, 588, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1151, 1151, 1151, 968, 1149, 1208, 1209, 968, 968, 472, 968, 968, 968, 779, 968, 968, 968, 1232, 1232, 1232, 1232, 1151, 1151, 1151, 1151, 1151, 785, 21, 785, 546, 1198, 1198, 1151, 1151, 1151, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 523, 523, 523, 325, 876, 512, 512, 392, 877, 582, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 1240, 427, 906, 906, 906, 906, 387, 387, 387, 387, 602, 604, 427, 900, 907, 540, 904, 379, 662, 688, 606, 608, 933, 5, 627, 6, 539, 645, 649, 947, 653, 661, 943, 586, 377, 378, 800, 1019, 570, 635, 666, 636, 359, 381, 382, 383, 453, 646, 652, 652, 384, 658, 1017, 454, 323, 580, 595, 598, 599, 600, 601, 619, 620, 621, 665, 527, 537, 1267, 450, 1225, 1226, 527, 545, 537, 800, 628, 362, 1101, 528, 434, 521, 521, 521, 521, 1227, 1228, 1132, 890, 405, 575, 1133, 1136, 891, 1137, 444, 553, 445, 419, 419, 419, 830, 329, 330, 1258, 1259, 1222, 1222, 1222, 622, 623, 431, 637, 638, 1211, 439, 439, 550, 585, 881, 1041, 797, 319, 833, 821, 991, 439, 590, 995, 825, 828, 369, 822, 952, 1234, 1234, 1234, 1234, 915, 648, 824, 955, 632, 931, 473, 691, 474, 992, 818, 1144, 451, 996, 480, 0, 834, 1036, 1218, 917, 0, 0, 1143, 0, 905, 0, 0, 0, 0, 0, 528, 0, 0, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 800, 419, 1034, 837, 0, 0, 0, 994, 0, 0, 1220, 1220, 994, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, 524, 524, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 950, 950); protected $gotoCheck = array(41, 41, 71, 6, 8, 64, 64, 105, 105, 105, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 57, 57, 57, 57, 57, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 14, 107, 107, 25, 22, 22, 22, 22, 107, 107, 107, 54, 54, 19, 99, 99, 114, 74, 74, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 164, 164, 111, 88, 14, 128, 14, 14, 14, 14, 128, 14, 14, 14, 14, 14, 14, 24, 165, 165, 26, 164, 14, 48, 24, 24, 24, 24, 24, 24, 74, 74, 14, 14, 74, 164, 24, 24, 24, 165, 74, 74, 34, 19, 44, 74, 74, 34, 151, 151, 34, 74, 63, 19, 63, 152, 152, 11, 74, 74, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 71, 71, 71, 71, 19, 19, 19, 71, 71, 74, 71, 71, 71, 5, 71, 71, 71, 8, 8, 8, 8, 71, 71, 71, 71, 71, 11, 74, 11, 154, 153, 153, 71, 71, 71, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 18, 18, 18, 161, 71, 155, 155, 12, 71, 12, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 163, 18, 18, 18, 18, 18, 23, 23, 23, 23, 81, 81, 18, 18, 18, 47, 84, 84, 84, 47, 47, 47, 94, 45, 47, 45, 8, 47, 47, 47, 47, 47, 47, 8, 78, 78, 21, 7, 7, 78, 7, 78, 60, 78, 78, 78, 80, 78, 7, 7, 78, 7, 7, 80, 78, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 8, 8, 13, 158, 158, 158, 8, 95, 8, 21, 62, 8, 135, 13, 8, 98, 98, 98, 98, 160, 160, 76, 76, 103, 98, 76, 76, 76, 76, 8, 8, 8, 22, 22, 22, 8, 88, 88, 8, 8, 114, 114, 114, 82, 82, 79, 82, 82, 13, 133, 133, 2, 2, 16, 16, 17, 28, 15, 15, 15, 133, 16, 15, 38, 8, 27, 36, 16, 114, 114, 114, 114, 15, 13, 16, 101, 16, 16, 139, 90, 139, 113, 16, 144, 141, 116, 139, -1, 40, 131, 114, 87, -1, -1, 16, -1, 15, -1, -1, -1, -1, -1, 13, -1, -1, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 21, 22, 15, 15, -1, -1, -1, 114, -1, -1, 114, 114, 114, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, 23, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 98, 98); protected $gotoBase = array(0, 0, -232, 0, 0, 249, -6, 351, -16, 0, 0, -37, -11, 79, -167, 22, 1, 148, 40, -188, 0, 83, 158, 324, 199, 156, 202, 132, 162, 0, 0, 0, 0, 0, -118, 0, 131, 0, 142, 0, 66, -1, 0, 0, 211, -347, 0, -332, 192, 0, 0, 0, 0, 0, 130, 0, 0, -23, 0, 0, 323, 0, 161, 225, -229, 0, 0, 0, 0, 0, 0, -5, 0, 0, -198, 0, 30, 42, -109, 157, -77, -122, -246, 0, 53, 0, 0, 67, -267, 0, 89, 0, 0, 0, 312, 352, 0, 0, 375, -63, 0, 116, 0, 140, 0, -264, 0, -110, 0, 0, 0, 186, 0, 118, 165, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -74, 0, 0, 64, 0, 405, 0, 135, 0, 0, 0, -4, 0, 63, 0, 0, 65, 0, 0, 0, 0, 0, 0, -71, 7, 52, 258, 72, 0, 0, 99, 0, 58, 276, 0, 292, -101, -83, 0, 0); protected $gotoDefault = array(-32768, 485, 695, 4, 696, 769, 777, 569, 503, 664, 324, 596, 390, 331, 862, 1040, 551, 796, 1160, 1168, 428, 799, 312, 326, 844, 845, 846, 366, 351, 357, 364, 617, 597, 467, 831, 422, 823, 459, 826, 421, 835, 158, 386, 483, 839, 3, 841, 530, 872, 352, 849, 353, 641, 851, 536, 853, 854, 360, 367, 368, 1045, 544, 593, 866, 237, 538, 867, 350, 868, 875, 355, 358, 650, 438, 478, 380, 1021, 579, 614, 416, 447, 591, 603, 589, 902, 460, 436, 916, 327, 924, 693, 1052, 609, 462, 932, 610, 939, 942, 504, 505, 452, 954, 268, 463, 981, 633, 634, 966, 612, 979, 446, 985, 423, 993, 1204, 426, 997, 260, 1000, 269, 385, 401, 1005, 1006, 7, 1011, 656, 657, 10, 265, 482, 1035, 651, 420, 1051, 406, 1120, 1122, 532, 464, 1140, 1139, 644, 479, 1145, 1207, 417, 506, 448, 299, 507, 287, 315, 296, 522, 278, 316, 508, 449, 1213, 1221, 313, 29, 1241, 1252, 322, 548, 584); protected $ruleToNonTerminal = array(0, 1, 3, 3, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 10, 10, 11, 11, 12, 12, 13, 14, 14, 15, 15, 16, 16, 17, 17, 20, 20, 21, 22, 22, 23, 23, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 28, 28, 29, 29, 31, 33, 33, 27, 35, 35, 32, 37, 37, 34, 34, 36, 36, 38, 38, 30, 39, 39, 40, 42, 43, 43, 44, 45, 45, 47, 46, 46, 46, 46, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 24, 24, 67, 67, 70, 70, 69, 68, 68, 61, 73, 73, 74, 74, 75, 75, 76, 76, 25, 25, 26, 26, 26, 26, 79, 79, 79, 80, 80, 83, 83, 81, 81, 84, 85, 85, 55, 55, 63, 63, 66, 66, 66, 65, 86, 86, 87, 56, 56, 56, 56, 88, 88, 89, 89, 90, 90, 91, 92, 92, 93, 93, 94, 94, 53, 53, 49, 49, 96, 51, 51, 97, 50, 50, 52, 52, 62, 62, 62, 62, 77, 77, 100, 100, 102, 102, 102, 102, 101, 101, 101, 104, 104, 104, 105, 105, 107, 107, 107, 106, 106, 108, 108, 109, 109, 109, 103, 103, 78, 78, 78, 19, 19, 110, 110, 111, 111, 111, 111, 58, 112, 112, 113, 59, 115, 115, 116, 116, 117, 117, 82, 118, 118, 118, 118, 118, 123, 123, 124, 124, 125, 125, 125, 125, 125, 126, 127, 127, 122, 122, 119, 119, 121, 121, 129, 129, 128, 128, 128, 128, 128, 128, 120, 130, 130, 132, 131, 131, 60, 95, 133, 133, 54, 54, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 140, 134, 134, 139, 139, 142, 143, 143, 144, 145, 145, 145, 18, 18, 71, 71, 71, 71, 135, 135, 135, 135, 147, 147, 136, 136, 138, 138, 138, 141, 141, 152, 152, 152, 152, 152, 152, 152, 152, 152, 153, 153, 99, 155, 155, 155, 155, 137, 137, 137, 137, 137, 137, 137, 137, 57, 57, 150, 150, 150, 150, 156, 156, 146, 146, 146, 157, 157, 157, 157, 157, 157, 72, 72, 64, 64, 64, 64, 114, 114, 114, 114, 160, 159, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 158, 158, 158, 158, 98, 154, 162, 162, 161, 161, 163, 163, 163, 163, 163, 163, 163, 163, 151, 151, 151, 151, 165, 166, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167); protected $ruleToLength = array(1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 2, 1, 3, 4, 1, 2, 0, 1, 1, 1, 1, 1, 3, 5, 4, 3, 4, 2, 3, 1, 1, 7, 6, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 3, 1, 3, 1, 2, 2, 3, 1, 3, 2, 3, 1, 3, 2, 0, 1, 1, 1, 1, 1, 3, 7, 10, 5, 7, 9, 5, 3, 3, 3, 3, 3, 3, 1, 2, 5, 7, 9, 6, 5, 6, 3, 2, 1, 1, 1, 0, 2, 1, 3, 8, 0, 4, 2, 1, 3, 0, 1, 0, 1, 3, 1, 8, 9, 7, 8, 7, 6, 1, 2, 2, 0, 2, 0, 2, 0, 2, 2, 1, 3, 1, 4, 1, 4, 1, 1, 4, 2, 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, 1, 7, 0, 2, 1, 3, 3, 4, 1, 4, 0, 2, 5, 0, 2, 6, 0, 2, 0, 3, 1, 2, 1, 1, 2, 0, 1, 3, 0, 1, 1, 1, 6, 8, 6, 1, 2, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 2, 1, 0, 1, 0, 2, 2, 2, 4, 1, 3, 1, 2, 2, 3, 2, 3, 1, 1, 2, 3, 1, 1, 3, 2, 0, 1, 5, 5, 10, 3, 1, 1, 3, 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, 1, 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 3, 1, 1, 3, 2, 2, 3, 1, 0, 1, 1, 3, 3, 3, 4, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 2, 1, 2, 4, 2, 2, 8, 9, 8, 9, 9, 10, 9, 10, 8, 3, 2, 0, 4, 2, 1, 3, 2, 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 0, 3, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 4, 1, 1, 3, 1, 1, 1, 1, 1, 3, 2, 3, 0, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 4, 4, 1, 4, 4, 0, 1, 1, 1, 3, 3, 1, 4, 2, 2, 1, 3, 1, 4, 4, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, 1, 4, 1, 1, 1, 3, 1, 1, 2, 1, 3, 4, 3, 2, 0, 2, 2, 1, 2, 1, 1, 1, 4, 3, 3, 3, 3, 6, 3, 1, 1, 2, 1); protected function initReduceCallbacks() { $this->reduceCallbacks = [0 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 1 => function ($stackPos) { $this->semValue = $this->handleNamespaces($this->semStack[$stackPos - (1 - 1)]); }, 2 => function ($stackPos) { if (\is_array($this->semStack[$stackPos - (2 - 2)])) { $this->semValue = \array_merge($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]); } else { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; } }, 3 => function ($stackPos) { $this->semValue = array(); }, 4 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; } if ($nop !== null) { $this->semStack[$stackPos - (1 - 1)][] = $nop; } $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 5 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 6 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 7 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 8 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 9 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 10 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 11 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 12 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 13 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 14 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 15 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 16 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 17 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 18 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 19 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 20 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 21 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 22 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 23 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 24 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 25 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 26 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 27 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 28 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 29 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 30 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 31 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 32 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 33 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 34 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 35 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 36 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 37 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 38 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 39 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 40 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 41 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 42 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 43 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 44 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 45 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 46 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 47 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 48 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 49 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 50 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 51 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 52 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 53 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 54 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 55 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 56 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 57 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 58 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 59 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 60 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 61 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 62 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 63 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 64 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 65 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 66 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 67 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 68 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 69 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 70 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 71 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 72 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 73 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 74 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 75 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 76 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 77 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 78 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 79 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 80 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 81 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 82 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 83 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 84 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 85 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 86 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 87 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 88 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 89 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 90 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 91 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 92 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name(\substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 93 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable(\substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 94 => function ($stackPos) { /* nothing */ }, 95 => function ($stackPos) { /* nothing */ }, 96 => function ($stackPos) { /* nothing */ }, 97 => function ($stackPos) { $this->emitError(new \_HumbugBoxd02f763d3c56\PhpParser\Error('A trailing comma is not allowed here', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes)); }, 98 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 99 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 100 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Attribute($this->semStack[$stackPos - (1 - 1)], [], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 101 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Attribute($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 102 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 103 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 104 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\AttributeGroup($this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 105 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 106 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 107 => function ($stackPos) { $this->semValue = []; }, 108 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 109 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 110 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 111 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 112 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 113 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_($this->semStack[$stackPos - (3 - 2)], null, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); $this->semValue->setAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_::KIND_SEMICOLON); $this->checkNamespace($this->semValue); }, 114 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_($this->semStack[$stackPos - (5 - 2)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); $this->semValue->setAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($this->semValue); }, 115 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_(null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); $this->semValue->setAttribute('kind', \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($this->semValue); }, 116 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_($this->semStack[$stackPos - (3 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 117 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_($this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 118 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 119 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 120 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION; }, 121 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT; }, 122 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 6)], $this->semStack[$stackPos - (7 - 2)], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); }, 123 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 5)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 124 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 125 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 126 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 127 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 128 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 129 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 130 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 131 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 132 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 133 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse($this->semStack[$stackPos - (1 - 1)], null, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos - (1 - 1)); }, 134 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos - (3 - 3)); }, 135 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse($this->semStack[$stackPos - (1 - 1)], null, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos - (1 - 1)); }, 136 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos - (3 - 3)); }, 137 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; $this->semValue->type = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL; }, 138 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; $this->semValue->type = $this->semStack[$stackPos - (2 - 1)]; }, 139 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 140 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 141 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 142 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Const_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 143 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 144 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 145 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 146 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Const_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 147 => function ($stackPos) { if (\is_array($this->semStack[$stackPos - (2 - 2)])) { $this->semValue = \array_merge($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]); } else { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; } }, 148 => function ($stackPos) { $this->semValue = array(); }, 149 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; } if ($nop !== null) { $this->semStack[$stackPos - (1 - 1)][] = $nop; } $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 150 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 151 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 152 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 153 => function ($stackPos) { throw new \_HumbugBoxd02f763d3c56\PhpParser\Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 154 => function ($stackPos) { if ($this->semStack[$stackPos - (3 - 2)]) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; $attrs = $this->startAttributeStack[$stackPos - (3 - 1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) { $stmts[0]->setAttribute('comments', \array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); } } else { $startAttributes = $this->startAttributeStack[$stackPos - (3 - 1)]; if (isset($startAttributes['comments'])) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; } if (null === $this->semValue) { $this->semValue = array(); } } }, 155 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_($this->semStack[$stackPos - (7 - 3)], ['stmts' => \is_array($this->semStack[$stackPos - (7 - 5)]) ? $this->semStack[$stackPos - (7 - 5)] : array($this->semStack[$stackPos - (7 - 5)]), 'elseifs' => $this->semStack[$stackPos - (7 - 6)], 'else' => $this->semStack[$stackPos - (7 - 7)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); }, 156 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_($this->semStack[$stackPos - (10 - 3)], ['stmts' => $this->semStack[$stackPos - (10 - 6)], 'elseifs' => $this->semStack[$stackPos - (10 - 7)], 'else' => $this->semStack[$stackPos - (10 - 8)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes); }, 157 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\While_($this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 158 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Do_($this->semStack[$stackPos - (7 - 5)], \is_array($this->semStack[$stackPos - (7 - 2)]) ? $this->semStack[$stackPos - (7 - 2)] : array($this->semStack[$stackPos - (7 - 2)]), $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); }, 159 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\For_(['init' => $this->semStack[$stackPos - (9 - 3)], 'cond' => $this->semStack[$stackPos - (9 - 5)], 'loop' => $this->semStack[$stackPos - (9 - 7)], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); }, 160 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Switch_($this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 161 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Break_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 162 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Continue_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 163 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 164 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Global_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 165 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Static_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 166 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Echo_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 167 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\InlineHTML($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 168 => function ($stackPos) { $e = $this->semStack[$stackPos - (2 - 1)]; if ($e instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Throw_) { // For backwards-compatibility reasons, convert throw in statement position into // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_). $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Throw_($e->expr, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); } else { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression($e, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); } }, 169 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Unset_($this->semStack[$stackPos - (5 - 3)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 170 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos - (7 - 5)][1], 'stmts' => $this->semStack[$stackPos - (7 - 7)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); }, 171 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_($this->semStack[$stackPos - (9 - 3)], $this->semStack[$stackPos - (9 - 7)][0], ['keyVar' => $this->semStack[$stackPos - (9 - 5)], 'byRef' => $this->semStack[$stackPos - (9 - 7)][1], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); }, 172 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_($this->semStack[$stackPos - (6 - 3)], new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error($this->startAttributeStack[$stackPos - (6 - 4)] + $this->endAttributeStack[$stackPos - (6 - 4)]), ['stmts' => $this->semStack[$stackPos - (6 - 6)]], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 173 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Declare_($this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 174 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TryCatch($this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 5)], $this->semStack[$stackPos - (6 - 6)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); }, 175 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Goto_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 176 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Label($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 177 => function ($stackPos) { $this->semValue = array(); /* means: no statement */ }, 178 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 179 => function ($stackPos) { $startAttributes = $this->startAttributeStack[$stackPos - (1 - 1)]; if (isset($startAttributes['comments'])) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; } if ($this->semValue === null) { $this->semValue = array(); } /* means: no statement */ }, 180 => function ($stackPos) { $this->semValue = array(); }, 181 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 182 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 183 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 184 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Catch_($this->semStack[$stackPos - (8 - 3)], $this->semStack[$stackPos - (8 - 4)], $this->semStack[$stackPos - (8 - 7)], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes); }, 185 => function ($stackPos) { $this->semValue = null; }, 186 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Finally_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 187 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 188 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 189 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 190 => function ($stackPos) { $this->semValue = \false; }, 191 => function ($stackPos) { $this->semValue = \true; }, 192 => function ($stackPos) { $this->semValue = \false; }, 193 => function ($stackPos) { $this->semValue = \true; }, 194 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 195 => function ($stackPos) { $this->semValue = []; }, 196 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_($this->semStack[$stackPos - (8 - 3)], ['byRef' => $this->semStack[$stackPos - (8 - 2)], 'params' => $this->semStack[$stackPos - (8 - 5)], 'returnType' => $this->semStack[$stackPos - (8 - 7)], 'stmts' => $this->semStack[$stackPos - (8 - 8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes); }, 197 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_($this->semStack[$stackPos - (9 - 4)], ['byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 6)], 'returnType' => $this->semStack[$stackPos - (9 - 8)], 'stmts' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => $this->semStack[$stackPos - (9 - 1)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); }, 198 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_($this->semStack[$stackPos - (7 - 2)], ['type' => $this->semStack[$stackPos - (7 - 1)], 'extends' => $this->semStack[$stackPos - (7 - 3)], 'implements' => $this->semStack[$stackPos - (7 - 4)], 'stmts' => $this->semStack[$stackPos - (7 - 6)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); $this->checkClass($this->semValue, $stackPos - (7 - 2)); }, 199 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_($this->semStack[$stackPos - (8 - 3)], ['type' => $this->semStack[$stackPos - (8 - 2)], 'extends' => $this->semStack[$stackPos - (8 - 4)], 'implements' => $this->semStack[$stackPos - (8 - 5)], 'stmts' => $this->semStack[$stackPos - (8 - 7)], 'attrGroups' => $this->semStack[$stackPos - (8 - 1)]], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes); $this->checkClass($this->semValue, $stackPos - (8 - 3)); }, 200 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_($this->semStack[$stackPos - (7 - 3)], ['extends' => $this->semStack[$stackPos - (7 - 4)], 'stmts' => $this->semStack[$stackPos - (7 - 6)], 'attrGroups' => $this->semStack[$stackPos - (7 - 1)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); $this->checkInterface($this->semValue, $stackPos - (7 - 3)); }, 201 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_($this->semStack[$stackPos - (6 - 3)], ['stmts' => $this->semStack[$stackPos - (6 - 5)], 'attrGroups' => $this->semStack[$stackPos - (6 - 1)]], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 202 => function ($stackPos) { $this->semValue = 0; }, 203 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT; }, 204 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL; }, 205 => function ($stackPos) { $this->semValue = null; }, 206 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; }, 207 => function ($stackPos) { $this->semValue = array(); }, 208 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; }, 209 => function ($stackPos) { $this->semValue = array(); }, 210 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; }, 211 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 212 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 213 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 214 => function ($stackPos) { $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]); }, 215 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 216 => function ($stackPos) { $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]); }, 217 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 218 => function ($stackPos) { $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]); }, 219 => function ($stackPos) { $this->semValue = null; }, 220 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 221 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 222 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 223 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 224 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\DeclareDeclare($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 225 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 226 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 3)]; }, 227 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 228 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (5 - 3)]; }, 229 => function ($stackPos) { $this->semValue = array(); }, 230 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 231 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Case_($this->semStack[$stackPos - (4 - 2)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 232 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Case_(null, $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 233 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 234 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 235 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Match_($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 6)], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes); }, 236 => function ($stackPos) { $this->semValue = []; }, 237 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 238 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 239 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 240 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\MatchArm($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 241 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\MatchArm(null, $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 242 => function ($stackPos) { $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]); }, 243 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 244 => function ($stackPos) { $this->semValue = array(); }, 245 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 246 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ElseIf_($this->semStack[$stackPos - (5 - 3)], \is_array($this->semStack[$stackPos - (5 - 5)]) ? $this->semStack[$stackPos - (5 - 5)] : array($this->semStack[$stackPos - (5 - 5)]), $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 247 => function ($stackPos) { $this->semValue = array(); }, 248 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 249 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ElseIf_($this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 6)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 250 => function ($stackPos) { $this->semValue = null; }, 251 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Else_(\is_array($this->semStack[$stackPos - (2 - 2)]) ? $this->semStack[$stackPos - (2 - 2)] : array($this->semStack[$stackPos - (2 - 2)]), $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 252 => function ($stackPos) { $this->semValue = null; }, 253 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Else_($this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 254 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false); }, 255 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (2 - 2)], \true); }, 256 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false); }, 257 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false); }, 258 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 259 => function ($stackPos) { $this->semValue = array(); }, 260 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 261 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 262 => function ($stackPos) { $this->semValue = 0; }, 263 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC; }, 264 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED; }, 265 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE; }, 266 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Param($this->semStack[$stackPos - (6 - 6)], null, $this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 4)], $this->semStack[$stackPos - (6 - 5)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 1)]); $this->checkParam($this->semValue); }, 267 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Param($this->semStack[$stackPos - (8 - 6)], $this->semStack[$stackPos - (8 - 8)], $this->semStack[$stackPos - (8 - 3)], $this->semStack[$stackPos - (8 - 4)], $this->semStack[$stackPos - (8 - 5)], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (8 - 2)], $this->semStack[$stackPos - (8 - 1)]); $this->checkParam($this->semValue); }, 268 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Param(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error($this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes), null, $this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 4)], $this->semStack[$stackPos - (6 - 5)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 1)]); }, 269 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 270 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 271 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\UnionType($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 272 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 273 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('static', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 274 => function ($stackPos) { $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos - (1 - 1)]); }, 275 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('array', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 276 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('callable', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 277 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]); }, 278 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 279 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]); }, 280 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 281 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 282 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 283 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\UnionType($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 284 => function ($stackPos) { $this->semValue = null; }, 285 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 286 => function ($stackPos) { $this->semValue = null; }, 287 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 2)]; }, 288 => function ($stackPos) { $this->semValue = null; }, 289 => function ($stackPos) { $this->semValue = array(); }, 290 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 2)]; }, 291 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 292 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 293 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($this->semStack[$stackPos - (1 - 1)], \false, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 294 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($this->semStack[$stackPos - (2 - 2)], \true, \false, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 295 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($this->semStack[$stackPos - (2 - 2)], \false, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 296 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($this->semStack[$stackPos - (3 - 3)], \false, \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (3 - 1)]); }, 297 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 298 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 299 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 300 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 301 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 302 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 303 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 304 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\StaticVar($this->semStack[$stackPos - (1 - 1)], null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 305 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\StaticVar($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 306 => function ($stackPos) { if ($this->semStack[$stackPos - (2 - 2)] !== null) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; } }, 307 => function ($stackPos) { $this->semValue = array(); }, 308 => function ($stackPos) { $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; } if ($nop !== null) { $this->semStack[$stackPos - (1 - 1)][] = $nop; } $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 309 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property($this->semStack[$stackPos - (5 - 2)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 1)]); $this->checkProperty($this->semValue, $stackPos - (5 - 2)); }, 310 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst($this->semStack[$stackPos - (5 - 4)], $this->semStack[$stackPos - (5 - 2)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (5 - 1)]); $this->checkClassConst($this->semValue, $stackPos - (5 - 2)); }, 311 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod($this->semStack[$stackPos - (10 - 5)], ['type' => $this->semStack[$stackPos - (10 - 2)], 'byRef' => $this->semStack[$stackPos - (10 - 4)], 'params' => $this->semStack[$stackPos - (10 - 7)], 'returnType' => $this->semStack[$stackPos - (10 - 9)], 'stmts' => $this->semStack[$stackPos - (10 - 10)], 'attrGroups' => $this->semStack[$stackPos - (10 - 1)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes); $this->checkClassMethod($this->semValue, $stackPos - (10 - 2)); }, 312 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 313 => function ($stackPos) { $this->semValue = null; /* will be skipped */ }, 314 => function ($stackPos) { $this->semValue = array(); }, 315 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 316 => function ($stackPos) { $this->semValue = array(); }, 317 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 318 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 319 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (5 - 1)][0], $this->semStack[$stackPos - (5 - 1)][1], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 320 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], $this->semStack[$stackPos - (4 - 3)], null, $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 321 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 322 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 323 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]); }, 324 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 325 => function ($stackPos) { $this->semValue = array(null, $this->semStack[$stackPos - (1 - 1)]); }, 326 => function ($stackPos) { $this->semValue = null; }, 327 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 328 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 329 => function ($stackPos) { $this->semValue = 0; }, 330 => function ($stackPos) { $this->semValue = 0; }, 331 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 332 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 333 => function ($stackPos) { $this->checkModifier($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $stackPos - (2 - 2)); $this->semValue = $this->semStack[$stackPos - (2 - 1)] | $this->semStack[$stackPos - (2 - 2)]; }, 334 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC; }, 335 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED; }, 336 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE; }, 337 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC; }, 338 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT; }, 339 => function ($stackPos) { $this->semValue = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_FINAL; }, 340 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 341 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 342 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 343 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier(\substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 344 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\PropertyProperty($this->semStack[$stackPos - (1 - 1)], null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 345 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\PropertyProperty($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 346 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 347 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 348 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 349 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 350 => function ($stackPos) { $this->semValue = array(); }, 351 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 352 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 353 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 354 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 355 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 356 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 357 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 358 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 359 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Clone_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 360 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 361 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 362 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 363 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 364 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 365 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 366 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 367 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 368 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 369 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 370 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 371 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 372 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Coalesce($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 373 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 374 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 375 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 376 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 377 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 378 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 379 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 380 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 381 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 382 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 383 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 384 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 385 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 386 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 387 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 388 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 389 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 390 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 391 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 392 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 393 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 394 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 395 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 396 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 397 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BitwiseNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 398 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 399 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 400 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 401 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 402 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Spaceship($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 403 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 404 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 405 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 406 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 407 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 408 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 409 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary($this->semStack[$stackPos - (5 - 1)], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes); }, 410 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary($this->semStack[$stackPos - (4 - 1)], null, $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 411 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 412 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Isset_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 413 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Empty_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 414 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_($this->semStack[$stackPos - (2 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 415 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_($this->semStack[$stackPos - (2 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 416 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Eval_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 417 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_($this->semStack[$stackPos - (2 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 418 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_($this->semStack[$stackPos - (2 - 2)], \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 419 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Int_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 420 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes; $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos - (2 - 1)]); $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double($this->semStack[$stackPos - (2 - 2)], $attrs); }, 421 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\String_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 422 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Array_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 423 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Object_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 424 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Bool_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 425 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Unset_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 426 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes; $attrs['kind'] = \strtolower($this->semStack[$stackPos - (2 - 1)]) === 'exit' ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_::KIND_EXIT : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_::KIND_DIE; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_($this->semStack[$stackPos - (2 - 2)], $attrs); }, 427 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ErrorSuppress($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 428 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 429 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ShellExec($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 430 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Print_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 431 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_(null, null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 432 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_($this->semStack[$stackPos - (2 - 2)], null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 433 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_($this->semStack[$stackPos - (4 - 4)], $this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 434 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 435 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Throw_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 436 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction(['static' => \false, 'byRef' => $this->semStack[$stackPos - (8 - 2)], 'params' => $this->semStack[$stackPos - (8 - 4)], 'returnType' => $this->semStack[$stackPos - (8 - 6)], 'expr' => $this->semStack[$stackPos - (8 - 8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes); }, 437 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction(['static' => \true, 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 5)], 'returnType' => $this->semStack[$stackPos - (9 - 7)], 'expr' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); }, 438 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure(['static' => \false, 'byRef' => $this->semStack[$stackPos - (8 - 2)], 'params' => $this->semStack[$stackPos - (8 - 4)], 'uses' => $this->semStack[$stackPos - (8 - 6)], 'returnType' => $this->semStack[$stackPos - (8 - 7)], 'stmts' => $this->semStack[$stackPos - (8 - 8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes); }, 439 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure(['static' => \true, 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 5)], 'uses' => $this->semStack[$stackPos - (9 - 7)], 'returnType' => $this->semStack[$stackPos - (9 - 8)], 'stmts' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); }, 440 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction(['static' => \false, 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 5)], 'returnType' => $this->semStack[$stackPos - (9 - 7)], 'expr' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => $this->semStack[$stackPos - (9 - 1)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); }, 441 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction(['static' => \true, 'byRef' => $this->semStack[$stackPos - (10 - 4)], 'params' => $this->semStack[$stackPos - (10 - 6)], 'returnType' => $this->semStack[$stackPos - (10 - 8)], 'expr' => $this->semStack[$stackPos - (10 - 10)], 'attrGroups' => $this->semStack[$stackPos - (10 - 1)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes); }, 442 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure(['static' => \false, 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 5)], 'uses' => $this->semStack[$stackPos - (9 - 7)], 'returnType' => $this->semStack[$stackPos - (9 - 8)], 'stmts' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => $this->semStack[$stackPos - (9 - 1)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes); }, 443 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure(['static' => \true, 'byRef' => $this->semStack[$stackPos - (10 - 4)], 'params' => $this->semStack[$stackPos - (10 - 6)], 'uses' => $this->semStack[$stackPos - (10 - 8)], 'returnType' => $this->semStack[$stackPos - (10 - 9)], 'stmts' => $this->semStack[$stackPos - (10 - 10)], 'attrGroups' => $this->semStack[$stackPos - (10 - 1)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes); }, 444 => function ($stackPos) { $this->semValue = array(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos - (8 - 4)], 'implements' => $this->semStack[$stackPos - (8 - 5)], 'stmts' => $this->semStack[$stackPos - (8 - 7)], 'attrGroups' => $this->semStack[$stackPos - (8 - 1)]], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes), $this->semStack[$stackPos - (8 - 3)]); $this->checkClass($this->semValue[0], -1); }, 445 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 446 => function ($stackPos) { list($class, $ctorArgs) = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 447 => function ($stackPos) { $this->semValue = array(); }, 448 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 3)]; }, 449 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 450 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 451 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 452 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClosureUse($this->semStack[$stackPos - (2 - 2)], $this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 453 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 454 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 455 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 456 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 457 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 458 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 459 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 460 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified(\substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 461 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\Relative(\substr($this->semStack[$stackPos - (1 - 1)], 10), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 462 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 463 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 464 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 465 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); $this->errorState = 2; }, 466 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 467 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 468 => function ($stackPos) { $this->semValue = null; }, 469 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 470 => function ($stackPos) { $this->semValue = array(); }, 471 => function ($stackPos) { $this->semValue = array(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parseEscapeSequences($this->semStack[$stackPos - (1 - 1)], '`'), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes)); }, 472 => function ($stackPos) { foreach ($this->semStack[$stackPos - (1 - 1)] as $s) { if ($s instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart) { $s->value = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parseEscapeSequences($s->value, '`', \true); } } $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 473 => function ($stackPos) { $this->semValue = array(); }, 474 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 475 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 476 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Line($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 477 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\File($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 478 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 479 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 480 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 481 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Method($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 482 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 483 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 484 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 485 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch($this->semStack[$stackPos - (3 - 1)], new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error($this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)]), $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); $this->errorState = 2; }, 486 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes; $attrs['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_::KIND_SHORT; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($this->semStack[$stackPos - (3 - 2)], $attrs); }, 487 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes; $attrs['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_::KIND_LONG; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($this->semStack[$stackPos - (4 - 3)], $attrs); }, 488 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 489 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes; $attrs['kind'] = $this->semStack[$stackPos - (1 - 1)][0] === "'" || $this->semStack[$stackPos - (1 - 1)][1] === "'" && ($this->semStack[$stackPos - (1 - 1)][0] === 'b' || $this->semStack[$stackPos - (1 - 1)][0] === 'B') ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_SINGLE_QUOTED : \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_DOUBLE_QUOTED; $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parse($this->semStack[$stackPos - (1 - 1)]), $attrs); }, 490 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes; $attrs['kind'] = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::KIND_DOUBLE_QUOTED; foreach ($this->semStack[$stackPos - (3 - 2)] as $s) { if ($s instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart) { $s->value = \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_::parseEscapeSequences($s->value, '"', \true); } } $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\Encapsed($this->semStack[$stackPos - (3 - 2)], $attrs); }, 491 => function ($stackPos) { $this->semValue = $this->parseLNumber($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 492 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber(\_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber::parse($this->semStack[$stackPos - (1 - 1)]), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 493 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 494 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 495 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 496 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)], \true); }, 497 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos - (2 - 1)], '', $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (2 - 2)] + $this->endAttributeStack[$stackPos - (2 - 2)], \true); }, 498 => function ($stackPos) { $this->semValue = $this->parseDocString($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)], \true); }, 499 => function ($stackPos) { $this->semValue = null; }, 500 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 501 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 502 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 503 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 504 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 505 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 506 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 507 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 508 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 509 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 510 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 511 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 512 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 513 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 514 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 515 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafeMethodCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 516 => function ($stackPos) { $this->semValue = null; }, 517 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 518 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 519 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 520 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 521 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafePropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 522 => function ($stackPos) { $this->semValue = \substr($this->semStack[$stackPos - (1 - 1)], 1); }, 523 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (4 - 3)]; }, 524 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 525 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error($this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); $this->errorState = 2; }, 526 => function ($stackPos) { $var = $this->semStack[$stackPos - (1 - 1)]; $this->semValue = \is_string($var) ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes) : $var; }, 527 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 528 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 529 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 530 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 531 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 532 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafePropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 533 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 534 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 535 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 536 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 537 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 538 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 539 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 540 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 541 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); $this->errorState = 2; }, 542 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\List_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 543 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; $end = \count($this->semValue) - 1; if ($this->semValue[$end] === null) { \array_pop($this->semValue); } }, 544 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, 545 => function ($stackPos) { /* do nothing -- prevent default action of $$=$this->semStack[$1]. See $551. */ }, 546 => function ($stackPos) { $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)]; $this->semValue = $this->semStack[$stackPos - (3 - 1)]; }, 547 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 548 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 549 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (2 - 2)], null, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 550 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 551 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (3 - 3)], $this->semStack[$stackPos - (3 - 1)], \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 552 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (4 - 4)], $this->semStack[$stackPos - (4 - 1)], \true, $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 553 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (3 - 3)], $this->semStack[$stackPos - (3 - 1)], \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 554 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($this->semStack[$stackPos - (2 - 2)], null, \false, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 555 => function ($stackPos) { $this->semValue = null; }, 556 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 557 => function ($stackPos) { $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)]; $this->semValue = $this->semStack[$stackPos - (2 - 1)]; }, 558 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (1 - 1)]); }, 559 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]); }, 560 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 561 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 562 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }, 563 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes); }, 564 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 565 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafePropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 566 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 567 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes); }, 568 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 4)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes); }, 569 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (3 - 2)]; }, 570 => function ($stackPos) { $this->semValue = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 571 => function ($stackPos) { $this->semValue = $this->parseNumString($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes); }, 572 => function ($stackPos) { $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes); }, 573 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos - (1 - 1)]; }]; } } #!/usr/bin/env php ['startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments']]); $parser = (new \_HumbugBoxd02f763d3c56\PhpParser\ParserFactory())->create(\_HumbugBoxd02f763d3c56\PhpParser\ParserFactory::PREFER_PHP7, $lexer); $dumper = new \_HumbugBoxd02f763d3c56\PhpParser\NodeDumper(['dumpComments' => \true, 'dumpPositions' => $attributes['with-positions']]); $prettyPrinter = new \_HumbugBoxd02f763d3c56\PhpParser\PrettyPrinter\Standard(); $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $traverser->addVisitor(new \_HumbugBoxd02f763d3c56\PhpParser\NodeVisitor\NameResolver()); foreach ($files as $file) { if (\strpos($file, ' Code {$code}\n"); } else { if (!\file_exists($file)) { \fwrite(\STDERR, "File {$file} does not exist.\n"); exit(1); } $code = \file_get_contents($file); \fwrite(\STDERR, "====> File {$file}:\n"); } if ($attributes['with-recovery']) { $errorHandler = new \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler\Collecting(); $stmts = $parser->parse($code, $errorHandler); foreach ($errorHandler->getErrors() as $error) { $message = \_HumbugBoxd02f763d3c56\formatErrorMessage($error, $code, $attributes['with-column-info']); \fwrite(\STDERR, $message . "\n"); } if (null === $stmts) { continue; } } else { try { $stmts = $parser->parse($code); } catch (\_HumbugBoxd02f763d3c56\PhpParser\Error $error) { $message = \_HumbugBoxd02f763d3c56\formatErrorMessage($error, $code, $attributes['with-column-info']); \fwrite(\STDERR, $message . "\n"); exit(1); } } foreach ($operations as $operation) { if ('dump' === $operation) { \fwrite(\STDERR, "==> Node dump:\n"); echo $dumper->dump($stmts, $code), "\n"; } elseif ('pretty-print' === $operation) { \fwrite(\STDERR, "==> Pretty print:\n"); echo $prettyPrinter->prettyPrintFile($stmts), "\n"; } elseif ('json-dump' === $operation) { \fwrite(\STDERR, "==> JSON dump:\n"); echo \json_encode($stmts, \JSON_PRETTY_PRINT), "\n"; } elseif ('var-dump' === $operation) { \fwrite(\STDERR, "==> var_dump():\n"); \var_dump($stmts); } elseif ('resolve-names' === $operation) { \fwrite(\STDERR, "==> Resolved names.\n"); $stmts = $traverser->traverse($stmts); } } } function formatErrorMessage(\_HumbugBoxd02f763d3c56\PhpParser\Error $e, $code, $withColumnInfo) { if ($withColumnInfo && $e->hasColumnInfo()) { return $e->getMessageWithColumnInfo($code); } else { return $e->getMessage(); } } function showHelp($error = '') { if ($error) { \fwrite(\STDERR, $error . "\n\n"); } \fwrite($error ? \STDERR : \STDOUT, << \false, 'with-positions' => \false, 'with-recovery' => \false]; \array_shift($args); $parseOptions = \true; foreach ($args as $arg) { if (!$parseOptions) { $files[] = $arg; continue; } switch ($arg) { case '--dump': case '-d': $operations[] = 'dump'; break; case '--pretty-print': case '-p': $operations[] = 'pretty-print'; break; case '--json-dump': case '-j': $operations[] = 'json-dump'; break; case '--var-dump': $operations[] = 'var-dump'; break; case '--resolve-names': case '-N': $operations[] = 'resolve-names'; break; case '--with-column-info': case '-c': $attributes['with-column-info'] = \true; break; case '--with-positions': case '-P': $attributes['with-positions'] = \true; break; case '--with-recovery': case '-r': $attributes['with-recovery'] = \true; break; case '--help': case '-h': \_HumbugBoxd02f763d3c56\showHelp(); break; case '--': $parseOptions = \false; break; default: if ($arg[0] === '-') { \_HumbugBoxd02f763d3c56\showHelp("Invalid operation {$arg}."); } else { $files[] = $arg; } } } return [$operations, $files, $attributes]; } /* We currently rely on the token ID mapping to be the same between PHP 5 and PHP 7 - so the same lexer can be used for * both. This is enforced by sharing this token file. */ %right T_THROW %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left ',' %left T_LOGICAL_OR %left T_LOGICAL_XOR %left T_LOGICAL_AND %right T_PRINT %right T_YIELD %right T_DOUBLE_ARROW %right T_YIELD_FROM %left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL T_COALESCE_EQUAL %left '?' ':' %right T_COALESCE %left T_BOOLEAN_OR %left T_BOOLEAN_AND %left '|' %left '^' %left '&' %nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP %nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL %left T_SL T_SR %left '+' '-' '.' %left '*' '/' '%' %right '!' %nonassoc T_INSTANCEOF %right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' %right T_POW %right '[' %nonassoc T_NEW T_CLONE %token T_EXIT %token T_IF %left T_ELSEIF %left T_ELSE %left T_ENDIF %token T_LNUMBER %token T_DNUMBER %token T_STRING %token T_STRING_VARNAME %token T_VARIABLE %token T_NUM_STRING %token T_INLINE_HTML %token T_ENCAPSED_AND_WHITESPACE %token T_CONSTANT_ENCAPSED_STRING %token T_ECHO %token T_DO %token T_WHILE %token T_ENDWHILE %token T_FOR %token T_ENDFOR %token T_FOREACH %token T_ENDFOREACH %token T_DECLARE %token T_ENDDECLARE %token T_AS %token T_SWITCH %token T_MATCH %token T_ENDSWITCH %token T_CASE %token T_DEFAULT %token T_BREAK %token T_CONTINUE %token T_GOTO %token T_FUNCTION %token T_FN %token T_CONST %token T_RETURN %token T_TRY %token T_CATCH %token T_FINALLY %token T_THROW %token T_USE %token T_INSTEADOF %token T_GLOBAL %right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC %token T_VAR %token T_UNSET %token T_ISSET %token T_EMPTY %token T_HALT_COMPILER %token T_CLASS %token T_TRAIT %token T_INTERFACE %token T_EXTENDS %token T_IMPLEMENTS %token T_OBJECT_OPERATOR %token T_NULLSAFE_OBJECT_OPERATOR %token T_DOUBLE_ARROW %token T_LIST %token T_ARRAY %token T_CALLABLE %token T_CLASS_C %token T_TRAIT_C %token T_METHOD_C %token T_FUNC_C %token T_LINE %token T_FILE %token T_START_HEREDOC %token T_END_HEREDOC %token T_DOLLAR_OPEN_CURLY_BRACES %token T_CURLY_OPEN %token T_PAAMAYIM_NEKUDOTAYIM %token T_NAMESPACE %token T_NS_C %token T_DIR %token T_NS_SEPARATOR %token T_ELLIPSIS %token T_NAME_FULLY_QUALIFIED %token T_NAME_QUALIFIED %token T_NAME_RELATIVE %token T_ATTRIBUTE%pure_parser %expect 2 %tokens %% start: top_statement_list { $$ = $this->handleNamespaces($1); } ; top_statement_list_ex: top_statement_list_ex top_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; top_statement_list: top_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; reserved_non_modifiers: T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN | T_MATCH ; semi_reserved: reserved_non_modifiers | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC ; identifier_ex: T_STRING { $$ = Node\Identifier[$1]; } | semi_reserved { $$ = Node\Identifier[$1]; } ; identifier: T_STRING { $$ = Node\Identifier[$1]; } ; reserved_non_modifiers_identifier: reserved_non_modifiers { $$ = Node\Identifier[$1]; } ; namespace_declaration_name: T_STRING { $$ = Name[$1]; } | semi_reserved { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } ; namespace_name: T_STRING { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } ; legacy_namespace_name: namespace_name { $$ = $1; } | T_NAME_FULLY_QUALIFIED { $$ = Name[substr($1, 1)]; } ; plain_variable: T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } ; semi: ';' { /* nothing */ } | error { /* nothing */ } ; no_comma: /* empty */ { /* nothing */ } | ',' { $this->emitError(new Error('A trailing comma is not allowed here', attributes())); } ; optional_comma: /* empty */ | ',' ; attribute_decl: class_name { $$ = Node\Attribute[$1, []]; } | class_name argument_list { $$ = Node\Attribute[$1, $2]; } ; attribute_group: attribute_decl { init($1); } | attribute_group ',' attribute_decl { push($1, $3); } ; attribute: T_ATTRIBUTE attribute_group optional_comma ']' { $$ = Node\AttributeGroup[$2]; } ; attributes: attribute { init($1); } | attributes attribute { push($1, $2); } ; optional_attributes: /* empty */ { $$ = []; } | attributes { $$ = $1; } ; top_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } | T_NAMESPACE namespace_declaration_name semi { $$ = Stmt\Namespace_[$2, null]; $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); $this->checkNamespace($$); } | T_NAMESPACE namespace_declaration_name '{' top_statement_list '}' { $$ = Stmt\Namespace_[$2, $4]; $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($$); } | T_NAMESPACE '{' top_statement_list '}' { $$ = Stmt\Namespace_[null, $3]; $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($$); } | T_USE use_declarations semi { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } | T_USE use_type use_declarations semi { $$ = Stmt\Use_[$3, $2]; } | group_use_declaration semi { $$ = $1; } | T_CONST constant_declaration_list semi { $$ = Stmt\Const_[$2]; } ; use_type: T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } ; group_use_declaration: T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}' { $$ = Stmt\GroupUse[$3, $6, $2]; } | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}' { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; } ; unprefixed_use_declarations: non_empty_unprefixed_use_declarations optional_comma { $$ = $1; } ; non_empty_unprefixed_use_declarations: non_empty_unprefixed_use_declarations ',' unprefixed_use_declaration { push($1, $3); } | unprefixed_use_declaration { init($1); } ; use_declarations: non_empty_use_declarations no_comma { $$ = $1; } ; non_empty_use_declarations: non_empty_use_declarations ',' use_declaration { push($1, $3); } | use_declaration { init($1); } ; inline_use_declarations: non_empty_inline_use_declarations optional_comma { $$ = $1; } ; non_empty_inline_use_declarations: non_empty_inline_use_declarations ',' inline_use_declaration { push($1, $3); } | inline_use_declaration { init($1); } ; unprefixed_use_declaration: namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } | namespace_name T_AS identifier { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } ; use_declaration: legacy_namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } | legacy_namespace_name T_AS identifier { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } ; inline_use_declaration: unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } ; constant_declaration_list: non_empty_constant_declaration_list no_comma { $$ = $1; } ; non_empty_constant_declaration_list: non_empty_constant_declaration_list ',' constant_declaration { push($1, $3); } | constant_declaration { init($1); } ; constant_declaration: identifier '=' expr { $$ = Node\Const_[$1, $3]; } ; class_const_list: non_empty_class_const_list no_comma { $$ = $1; } ; non_empty_class_const_list: non_empty_class_const_list ',' class_const { push($1, $3); } | class_const { init($1); } ; class_const: identifier_ex '=' expr { $$ = Node\Const_[$1, $3]; } ; inner_statement_list_ex: inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; inner_statement_list: inner_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; inner_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } ; non_empty_statement: '{' inner_statement_list '}' { if ($2) { $$ = $2; prependLeadingComments($$); } else { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); if (null === $$) { $$ = array(); } } } | T_IF '(' expr ')' statement elseif_list else_single { $$ = Stmt\If_[$3, ['stmts' => toArray($5), 'elseifs' => $6, 'else' => $7]]; } | T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' { $$ = Stmt\If_[$3, ['stmts' => $6, 'elseifs' => $7, 'else' => $8]]; } | T_WHILE '(' expr ')' while_statement { $$ = Stmt\While_[$3, $5]; } | T_DO statement T_WHILE '(' expr ')' ';' { $$ = Stmt\Do_ [$5, toArray($2)]; } | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } | T_SWITCH '(' expr ')' switch_case_list { $$ = Stmt\Switch_[$3, $5]; } | T_BREAK optional_expr semi { $$ = Stmt\Break_[$2]; } | T_CONTINUE optional_expr semi { $$ = Stmt\Continue_[$2]; } | T_RETURN optional_expr semi { $$ = Stmt\Return_[$2]; } | T_GLOBAL global_var_list semi { $$ = Stmt\Global_[$2]; } | T_STATIC static_var_list semi { $$ = Stmt\Static_[$2]; } | T_ECHO expr_list_forbid_comma semi { $$ = Stmt\Echo_[$2]; } | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } | expr semi { $e = $1; if ($e instanceof Expr\Throw_) { // For backwards-compatibility reasons, convert throw in statement position into // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_). $$ = Stmt\Throw_[$e->expr]; } else { $$ = Stmt\Expression[$e]; } } | T_UNSET '(' variables_list ')' semi { $$ = Stmt\Unset_[$3]; } | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } | T_FOREACH '(' expr error ')' foreach_statement { $$ = Stmt\Foreach_[$3, new Expr\Error(stackAttributes(#4)), ['stmts' => $6]]; } | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } | T_TRY '{' inner_statement_list '}' catches optional_finally { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } | T_GOTO identifier semi { $$ = Stmt\Goto_[$2]; } | identifier ':' { $$ = Stmt\Label[$1]; } | error { $$ = array(); /* means: no statement */ } ; statement: non_empty_statement { $$ = $1; } | ';' { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); if ($$ === null) $$ = array(); /* means: no statement */ } ; catches: /* empty */ { init(); } | catches catch { push($1, $2); } ; name_union: name { init($1); } | name_union '|' name { push($1, $3); } ; catch: T_CATCH '(' name_union optional_plain_variable ')' '{' inner_statement_list '}' { $$ = Stmt\Catch_[$3, $4, $7]; } ; optional_finally: /* empty */ { $$ = null; } | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } ; variables_list: non_empty_variables_list optional_comma { $$ = $1; } ; non_empty_variables_list: variable { init($1); } | non_empty_variables_list ',' variable { push($1, $3); } ; optional_ref: /* empty */ { $$ = false; } | '&' { $$ = true; } ; optional_ellipsis: /* empty */ { $$ = false; } | T_ELLIPSIS { $$ = true; } ; block_or_error: '{' inner_statement_list '}' { $$ = $2; } | error { $$ = []; } ; function_declaration_statement: T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type block_or_error { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; } | attributes T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type block_or_error { $$ = Stmt\Function_[$4, ['byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; } ; class_declaration_statement: class_entry_type identifier extends_from implements_list '{' class_statement_list '}' { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6, 'attrGroups' => []]]; $this->checkClass($$, #2); } | attributes class_entry_type identifier extends_from implements_list '{' class_statement_list '}' { $$ = Stmt\Class_[$3, ['type' => $2, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]]; $this->checkClass($$, #3); } | optional_attributes T_INTERFACE identifier interface_extends_list '{' class_statement_list '}' { $$ = Stmt\Interface_[$3, ['extends' => $4, 'stmts' => $6, 'attrGroups' => $1]]; $this->checkInterface($$, #3); } | optional_attributes T_TRAIT identifier '{' class_statement_list '}' { $$ = Stmt\Trait_[$3, ['stmts' => $5, 'attrGroups' => $1]]; } ; class_entry_type: T_CLASS { $$ = 0; } | T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; } ; extends_from: /* empty */ { $$ = null; } | T_EXTENDS class_name { $$ = $2; } ; interface_extends_list: /* empty */ { $$ = array(); } | T_EXTENDS class_name_list { $$ = $2; } ; implements_list: /* empty */ { $$ = array(); } | T_IMPLEMENTS class_name_list { $$ = $2; } ; class_name_list: non_empty_class_name_list no_comma { $$ = $1; } ; non_empty_class_name_list: class_name { init($1); } | non_empty_class_name_list ',' class_name { push($1, $3); } ; for_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } ; foreach_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } ; declare_statement: non_empty_statement { $$ = toArray($1); } | ';' { $$ = null; } | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } ; declare_list: non_empty_declare_list no_comma { $$ = $1; } ; non_empty_declare_list: declare_list_element { init($1); } | non_empty_declare_list ',' declare_list_element { push($1, $3); } ; declare_list_element: identifier '=' expr { $$ = Stmt\DeclareDeclare[$1, $3]; } ; switch_case_list: '{' case_list '}' { $$ = $2; } | '{' ';' case_list '}' { $$ = $3; } | ':' case_list T_ENDSWITCH ';' { $$ = $2; } | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } ; case_list: /* empty */ { init(); } | case_list case { push($1, $2); } ; case: T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } ; case_separator: ':' | ';' ; match: T_MATCH '(' expr ')' '{' match_arm_list '}' { $$ = Expr\Match_[$3, $6]; } ; match_arm_list: /* empty */ { $$ = []; } | non_empty_match_arm_list optional_comma { $$ = $1; } ; non_empty_match_arm_list: match_arm { init($1); } | non_empty_match_arm_list ',' match_arm { push($1, $3); } ; match_arm: expr_list_allow_comma T_DOUBLE_ARROW expr { $$ = Node\MatchArm[$1, $3]; } | T_DEFAULT optional_comma T_DOUBLE_ARROW expr { $$ = Node\MatchArm[null, $4]; } ; while_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } ; elseif_list: /* empty */ { init(); } | elseif_list elseif { push($1, $2); } ; elseif: T_ELSEIF '(' expr ')' statement { $$ = Stmt\ElseIf_[$3, toArray($5)]; } ; new_elseif_list: /* empty */ { init(); } | new_elseif_list new_elseif { push($1, $2); } ; new_elseif: T_ELSEIF '(' expr ')' ':' inner_statement_list { $$ = Stmt\ElseIf_[$3, $6]; } ; else_single: /* empty */ { $$ = null; } | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } ; new_else_single: /* empty */ { $$ = null; } | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } ; foreach_variable: variable { $$ = array($1, false); } | '&' variable { $$ = array($2, true); } | list_expr { $$ = array($1, false); } | array_short_syntax { $$ = array($1, false); } ; parameter_list: non_empty_parameter_list optional_comma { $$ = $1; } | /* empty */ { $$ = array(); } ; non_empty_parameter_list: parameter { init($1); } | non_empty_parameter_list ',' parameter { push($1, $3); } ; optional_visibility_modifier: /* empty */ { $$ = 0; } | T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } ; parameter: optional_attributes optional_visibility_modifier optional_type_without_static optional_ref optional_ellipsis plain_variable { $$ = new Node\Param($6, null, $3, $4, $5, attributes(), $2, $1); $this->checkParam($$); } | optional_attributes optional_visibility_modifier optional_type_without_static optional_ref optional_ellipsis plain_variable '=' expr { $$ = new Node\Param($6, $8, $3, $4, $5, attributes(), $2, $1); $this->checkParam($$); } | optional_attributes optional_visibility_modifier optional_type_without_static optional_ref optional_ellipsis error { $$ = new Node\Param(Expr\Error[], null, $3, $4, $5, attributes(), $2, $1); } ; type_expr: type { $$ = $1; } | '?' type { $$ = Node\NullableType[$2]; } | union_type { $$ = Node\UnionType[$1]; } ; type: type_without_static { $$ = $1; } | T_STATIC { $$ = Node\Name['static']; } ; type_without_static: name { $$ = $this->handleBuiltinTypes($1); } | T_ARRAY { $$ = Node\Identifier['array']; } | T_CALLABLE { $$ = Node\Identifier['callable']; } ; union_type: type '|' type { init($1, $3); } | union_type '|' type { push($1, $3); } ; union_type_without_static: type_without_static '|' type_without_static { init($1, $3); } | union_type_without_static '|' type_without_static { push($1, $3); } ; type_expr_without_static: type_without_static { $$ = $1; } | '?' type_without_static { $$ = Node\NullableType[$2]; } | union_type_without_static { $$ = Node\UnionType[$1]; } ; optional_type_without_static: /* empty */ { $$ = null; } | type_expr_without_static { $$ = $1; } ; optional_return_type: /* empty */ { $$ = null; } | ':' type_expr { $$ = $2; } | ':' error { $$ = null; } ; argument_list: '(' ')' { $$ = array(); } | '(' non_empty_argument_list optional_comma ')' { $$ = $2; } ; non_empty_argument_list: argument { init($1); } | non_empty_argument_list ',' argument { push($1, $3); } ; argument: expr { $$ = Node\Arg[$1, false, false]; } | '&' variable { $$ = Node\Arg[$2, true, false]; } | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } | identifier_ex ':' expr { $$ = new Node\Arg($3, false, false, attributes(), $1); } ; global_var_list: non_empty_global_var_list no_comma { $$ = $1; } ; non_empty_global_var_list: non_empty_global_var_list ',' global_var { push($1, $3); } | global_var { init($1); } ; global_var: simple_variable { $$ = Expr\Variable[$1]; } ; static_var_list: non_empty_static_var_list no_comma { $$ = $1; } ; non_empty_static_var_list: non_empty_static_var_list ',' static_var { push($1, $3); } | static_var { init($1); } ; static_var: plain_variable { $$ = Stmt\StaticVar[$1, null]; } | plain_variable '=' expr { $$ = Stmt\StaticVar[$1, $3]; } ; class_statement_list_ex: class_statement_list_ex class_statement { if ($2 !== null) { push($1, $2); } } | /* empty */ { init(); } ; class_statement_list: class_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; class_statement: optional_attributes variable_modifiers optional_type_without_static property_declaration_list semi { $$ = new Stmt\Property($2, $4, attributes(), $3, $1); $this->checkProperty($$, #2); } | optional_attributes method_modifiers T_CONST class_const_list semi { $$ = new Stmt\ClassConst($4, $2, attributes(), $1); $this->checkClassConst($$, #2); } | optional_attributes method_modifiers T_FUNCTION optional_ref identifier_ex '(' parameter_list ')' optional_return_type method_body { $$ = Stmt\ClassMethod[$5, ['type' => $2, 'byRef' => $4, 'params' => $7, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; $this->checkClassMethod($$, #2); } | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } | error { $$ = null; /* will be skipped */ } ; trait_adaptations: ';' { $$ = array(); } | '{' trait_adaptation_list '}' { $$ = $2; } ; trait_adaptation_list: /* empty */ { init(); } | trait_adaptation_list trait_adaptation { push($1, $2); } ; trait_adaptation: trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } | trait_method_reference T_AS member_modifier identifier_ex ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } | trait_method_reference T_AS member_modifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } | trait_method_reference T_AS identifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } | trait_method_reference T_AS reserved_non_modifiers_identifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } ; trait_method_reference_fully_qualified: name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = array($1, $3); } ; trait_method_reference: trait_method_reference_fully_qualified { $$ = $1; } | identifier_ex { $$ = array(null, $1); } ; method_body: ';' /* abstract method */ { $$ = null; } | block_or_error { $$ = $1; } ; variable_modifiers: non_empty_member_modifiers { $$ = $1; } | T_VAR { $$ = 0; } ; method_modifiers: /* empty */ { $$ = 0; } | non_empty_member_modifiers { $$ = $1; } ; non_empty_member_modifiers: member_modifier { $$ = $1; } | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } ; member_modifier: T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } ; property_declaration_list: non_empty_property_declaration_list no_comma { $$ = $1; } ; non_empty_property_declaration_list: property_declaration { init($1); } | non_empty_property_declaration_list ',' property_declaration { push($1, $3); } ; property_decl_name: T_VARIABLE { $$ = Node\VarLikeIdentifier[parseVar($1)]; } ; property_declaration: property_decl_name { $$ = Stmt\PropertyProperty[$1, null]; } | property_decl_name '=' expr { $$ = Stmt\PropertyProperty[$1, $3]; } ; expr_list_forbid_comma: non_empty_expr_list no_comma { $$ = $1; } ; expr_list_allow_comma: non_empty_expr_list optional_comma { $$ = $1; } ; non_empty_expr_list: non_empty_expr_list ',' expr { push($1, $3); } | expr { init($1); } ; for_expr: /* empty */ { $$ = array(); } | expr_list_forbid_comma { $$ = $1; } ; expr: variable { $$ = $1; } | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } | array_short_syntax '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' '&' variable { $$ = Expr\AssignRef[$1, $4]; } | new_expr { $$ = $1; } | match { $$ = $1; } | T_CLONE expr { $$ = Expr\Clone_[$2]; } | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } | variable T_COALESCE_EQUAL expr { $$ = Expr\AssignOp\Coalesce [$1, $3]; } | variable T_INC { $$ = Expr\PostInc[$1]; } | T_INC variable { $$ = Expr\PreInc [$2]; } | variable T_DEC { $$ = Expr\PostDec[$1]; } | T_DEC variable { $$ = Expr\PreDec [$2]; } | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } | expr '&' expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } | '!' expr { $$ = Expr\BooleanNot[$2]; } | '~' expr { $$ = Expr\BitwiseNot[$2]; } | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } | '(' expr ')' { $$ = $2; } | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } | T_ISSET '(' expr_list_allow_comma ')' { $$ = Expr\Isset_[$3]; } | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } | T_EVAL '(' expr ')' { $$ = Expr\Eval_[$3]; } | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } | T_DOUBLE_CAST expr { $attrs = attributes(); $attrs['kind'] = $this->getFloatCastKind($1); $$ = new Expr\Cast\Double($2, $attrs); } | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } | T_EXIT exit_expr { $attrs = attributes(); $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; $$ = new Expr\Exit_($2, $attrs); } | '@' expr { $$ = Expr\ErrorSuppress[$2]; } | scalar { $$ = $1; } | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } | T_PRINT expr { $$ = Expr\Print_[$2]; } | T_YIELD { $$ = Expr\Yield_[null, null]; } | T_YIELD expr { $$ = Expr\Yield_[$2, null]; } | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } | T_THROW expr { $$ = Expr\Throw_[$2]; } | T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $2, 'params' => $4, 'returnType' => $6, 'expr' => $8, 'attrGroups' => []]]; } | T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => []]]; } | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; } | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => []]]; } | attributes T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => $1]]; } | attributes T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $4, 'params' => $6, 'returnType' => $8, 'expr' => $10, 'attrGroups' => $1]]; } | attributes T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error { $$ = Expr\Closure[['static' => false, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; } | attributes T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error { $$ = Expr\Closure[['static' => true, 'byRef' => $4, 'params' => $6, 'uses' => $8, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; } ; anonymous_class: optional_attributes T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]], $3); $this->checkClass($$[0], -1); } ; new_expr: T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } | T_NEW anonymous_class { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } ; lexical_vars: /* empty */ { $$ = array(); } | T_USE '(' lexical_var_list ')' { $$ = $3; } ; lexical_var_list: non_empty_lexical_var_list optional_comma { $$ = $1; } ; non_empty_lexical_var_list: lexical_var { init($1); } | non_empty_lexical_var_list ',' lexical_var { push($1, $3); } ; lexical_var: optional_ref plain_variable { $$ = Expr\ClosureUse[$2, $1]; } ; function_call: name argument_list { $$ = Expr\FuncCall[$1, $2]; } | callable_expr argument_list { $$ = Expr\FuncCall[$1, $2]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM member_name argument_list { $$ = Expr\StaticCall[$1, $3, $4]; } ; class_name: T_STATIC { $$ = Name[$1]; } | name { $$ = $1; } ; name: T_STRING { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } | T_NAME_FULLY_QUALIFIED { $$ = Name\FullyQualified[substr($1, 1)]; } | T_NAME_RELATIVE { $$ = Name\Relative[substr($1, 10)]; } ; class_name_reference: class_name { $$ = $1; } | new_variable { $$ = $1; } | '(' expr ')' { $$ = $2; } | error { $$ = Expr\Error[]; $this->errorState = 2; } ; class_name_or_var: class_name { $$ = $1; } | fully_dereferencable { $$ = $1; } ; exit_expr: /* empty */ { $$ = null; } | '(' optional_expr ')' { $$ = $2; } ; backticks_expr: /* empty */ { $$ = array(); } | T_ENCAPSED_AND_WHITESPACE { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`')]); } | encaps_list { parseEncapsed($1, '`', true); $$ = $1; } ; ctor_arguments: /* empty */ { $$ = array(); } | argument_list { $$ = $1; } ; constant: name { $$ = Expr\ConstFetch[$1]; } | T_LINE { $$ = Scalar\MagicConst\Line[]; } | T_FILE { $$ = Scalar\MagicConst\File[]; } | T_DIR { $$ = Scalar\MagicConst\Dir[]; } | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } ; class_constant: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = Expr\ClassConstFetch[$1, $3]; } /* We interpret an isolated FOO:: as an unfinished class constant fetch. It could also be an unfinished static property fetch or unfinished scoped call. */ | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error { $$ = Expr\ClassConstFetch[$1, new Expr\Error(stackAttributes(#3))]; $this->errorState = 2; } ; array_short_syntax: '[' array_pair_list ']' { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; $$ = new Expr\Array_($2, $attrs); } ; dereferencable_scalar: T_ARRAY '(' array_pair_list ')' { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; $$ = new Expr\Array_($3, $attrs); } | array_short_syntax { $$ = $1; } | T_CONSTANT_ENCAPSED_STRING { $attrs = attributes(); $attrs['kind'] = strKind($1); $$ = new Scalar\String_(Scalar\String_::parse($1), $attrs); } | '"' encaps_list '"' { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } ; scalar: T_LNUMBER { $$ = $this->parseLNumber($1, attributes()); } | T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; } | dereferencable_scalar { $$ = $1; } | constant { $$ = $1; } | class_constant { $$ = $1; } | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } | T_START_HEREDOC T_END_HEREDOC { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), true); } | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } ; optional_expr: /* empty */ { $$ = null; } | expr { $$ = $1; } ; fully_dereferencable: variable { $$ = $1; } | '(' expr ')' { $$ = $2; } | dereferencable_scalar { $$ = $1; } | class_constant { $$ = $1; } ; array_object_dereferencable: fully_dereferencable { $$ = $1; } | constant { $$ = $1; } ; callable_expr: callable_variable { $$ = $1; } | '(' expr ')' { $$ = $2; } | dereferencable_scalar { $$ = $1; } ; callable_variable: simple_variable { $$ = Expr\Variable[$1]; } | array_object_dereferencable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | array_object_dereferencable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } | function_call { $$ = $1; } | array_object_dereferencable T_OBJECT_OPERATOR property_name argument_list { $$ = Expr\MethodCall[$1, $3, $4]; } | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list { $$ = Expr\NullsafeMethodCall[$1, $3, $4]; } ; optional_plain_variable: /* empty */ { $$ = null; } | plain_variable { $$ = $1; } ; variable: callable_variable { $$ = $1; } | static_member { $$ = $1; } | array_object_dereferencable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; } | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name { $$ = Expr\NullsafePropertyFetch[$1, $3]; } ; simple_variable: T_VARIABLE { $$ = parseVar($1); } | '$' '{' expr '}' { $$ = $3; } | '$' simple_variable { $$ = Expr\Variable[$2]; } | '$' error { $$ = Expr\Error[]; $this->errorState = 2; } ; static_member_prop_name: simple_variable { $var = $1; $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; } ; static_member: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name { $$ = Expr\StaticPropertyFetch[$1, $3]; } ; new_variable: simple_variable { $$ = Expr\Variable[$1]; } | new_variable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | new_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } | new_variable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; } | new_variable T_NULLSAFE_OBJECT_OPERATOR property_name { $$ = Expr\NullsafePropertyFetch[$1, $3]; } | class_name T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name { $$ = Expr\StaticPropertyFetch[$1, $3]; } | new_variable T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name { $$ = Expr\StaticPropertyFetch[$1, $3]; } ; member_name: identifier_ex { $$ = $1; } | '{' expr '}' { $$ = $2; } | simple_variable { $$ = Expr\Variable[$1]; } ; property_name: identifier { $$ = $1; } | '{' expr '}' { $$ = $2; } | simple_variable { $$ = Expr\Variable[$1]; } | error { $$ = Expr\Error[]; $this->errorState = 2; } ; list_expr: T_LIST '(' inner_array_pair_list ')' { $$ = Expr\List_[$3]; } ; array_pair_list: inner_array_pair_list { $$ = $1; $end = count($$)-1; if ($$[$end] === null) array_pop($$); } ; comma_or_error: ',' | error { /* do nothing -- prevent default action of $$=$1. See #551. */ } ; inner_array_pair_list: inner_array_pair_list comma_or_error array_pair { push($1, $3); } | array_pair { init($1); } ; array_pair: expr { $$ = Expr\ArrayItem[$1, null, false]; } | '&' variable { $$ = Expr\ArrayItem[$2, null, true]; } | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } | expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } | expr T_DOUBLE_ARROW '&' 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]; } | /* empty */ { $$ = null; } ; encaps_list: encaps_list encaps_var { push($1, $2); } | encaps_list encaps_string_part { push($1, $2); } | encaps_var { init($1); } | encaps_string_part encaps_var { init($1, $2); } ; encaps_string_part: T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } ; encaps_str_varname: T_STRING_VARNAME { $$ = Expr\Variable[$1]; } ; encaps_var: plain_variable { $$ = $1; } | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | plain_variable T_OBJECT_OPERATOR identifier { $$ = Expr\PropertyFetch[$1, $3]; } | plain_variable T_NULLSAFE_OBJECT_OPERATOR identifier { $$ = Expr\NullsafePropertyFetch[$1, $3]; } | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}' { $$ = Expr\ArrayDimFetch[$2, $4]; } | T_CURLY_OPEN variable '}' { $$ = $2; } ; encaps_var_offset: T_STRING { $$ = Scalar\String_[$1]; } | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } | '-' T_NUM_STRING { $$ = $this->parseNumString('-' . $2, attributes()); } | plain_variable { $$ = $1; } ; %% %pure_parser %expect 6 %tokens %% start: top_statement_list { $$ = $this->handleNamespaces($1); } ; top_statement_list_ex: top_statement_list_ex top_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; top_statement_list: top_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; reserved_non_modifiers: T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN | T_MATCH ; semi_reserved: reserved_non_modifiers | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC ; identifier_ex: T_STRING { $$ = Node\Identifier[$1]; } | semi_reserved { $$ = Node\Identifier[$1]; } ; identifier: T_STRING { $$ = Node\Identifier[$1]; } ; reserved_non_modifiers_identifier: reserved_non_modifiers { $$ = Node\Identifier[$1]; } ; namespace_name: T_STRING { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } ; legacy_namespace_name: namespace_name { $$ = $1; } | T_NAME_FULLY_QUALIFIED { $$ = Name[substr($1, 1)]; } ; plain_variable: T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } ; top_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } | T_NAMESPACE namespace_name ';' { $$ = Stmt\Namespace_[$2, null]; $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); $this->checkNamespace($$); } | T_NAMESPACE namespace_name '{' top_statement_list '}' { $$ = Stmt\Namespace_[$2, $4]; $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($$); } | T_NAMESPACE '{' top_statement_list '}' { $$ = Stmt\Namespace_[null, $3]; $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $this->checkNamespace($$); } | T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } | T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; } | group_use_declaration ';' { $$ = $1; } | T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; } ; use_type: T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } ; group_use_declaration: T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}' { $$ = Stmt\GroupUse[$3, $6, $2]; } | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}' { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; } ; unprefixed_use_declarations: unprefixed_use_declarations ',' unprefixed_use_declaration { push($1, $3); } | unprefixed_use_declaration { init($1); } ; use_declarations: use_declarations ',' use_declaration { push($1, $3); } | use_declaration { init($1); } ; inline_use_declarations: inline_use_declarations ',' inline_use_declaration { push($1, $3); } | inline_use_declaration { init($1); } ; unprefixed_use_declaration: namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } | namespace_name T_AS identifier { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } ; use_declaration: legacy_namespace_name { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } | legacy_namespace_name T_AS identifier { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } ; inline_use_declaration: unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } ; constant_declaration_list: constant_declaration_list ',' constant_declaration { push($1, $3); } | constant_declaration { init($1); } ; constant_declaration: identifier '=' static_scalar { $$ = Node\Const_[$1, $3]; } ; class_const_list: class_const_list ',' class_const { push($1, $3); } | class_const { init($1); } ; class_const: identifier_ex '=' static_scalar { $$ = Node\Const_[$1, $3]; } ; inner_statement_list_ex: inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; inner_statement_list: inner_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; inner_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } ; non_empty_statement: '{' inner_statement_list '}' { if ($2) { $$ = $2; prependLeadingComments($$); } else { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); if (null === $$) { $$ = array(); } } } | T_IF parentheses_expr statement elseif_list else_single { $$ = Stmt\If_[$2, ['stmts' => toArray($3), 'elseifs' => $4, 'else' => $5]]; } | T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' { $$ = Stmt\If_[$2, ['stmts' => $4, 'elseifs' => $5, 'else' => $6]]; } | T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; } | T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, toArray($2)]; } | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } | T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; } | T_BREAK ';' { $$ = Stmt\Break_[null]; } | T_BREAK expr ';' { $$ = Stmt\Break_[$2]; } | T_CONTINUE ';' { $$ = Stmt\Continue_[null]; } | T_CONTINUE expr ';' { $$ = Stmt\Continue_[$2]; } | T_RETURN ';' { $$ = Stmt\Return_[null]; } | T_RETURN expr ';' { $$ = Stmt\Return_[$2]; } | T_GLOBAL global_var_list ';' { $$ = Stmt\Global_[$2]; } | T_STATIC static_var_list ';' { $$ = Stmt\Static_[$2]; } | T_ECHO expr_list ';' { $$ = Stmt\Echo_[$2]; } | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } | yield_expr ';' { $$ = Stmt\Expression[$1]; } | expr ';' { $$ = Stmt\Expression[$1]; } | T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; } | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } | T_TRY '{' inner_statement_list '}' catches optional_finally { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } | T_THROW expr ';' { $$ = Stmt\Throw_[$2]; } | T_GOTO identifier ';' { $$ = Stmt\Goto_[$2]; } | identifier ':' { $$ = Stmt\Label[$1]; } | expr error { $$ = Stmt\Expression[$1]; } | error { $$ = array(); /* means: no statement */ } ; statement: non_empty_statement { $$ = $1; } | ';' { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes); if ($$ === null) $$ = array(); /* means: no statement */ } ; catches: /* empty */ { init(); } | catches catch { push($1, $2); } ; catch: T_CATCH '(' name plain_variable ')' '{' inner_statement_list '}' { $$ = Stmt\Catch_[array($3), $4, $7]; } ; optional_finally: /* empty */ { $$ = null; } | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } ; variables_list: variable { init($1); } | variables_list ',' variable { push($1, $3); } ; optional_ref: /* empty */ { $$ = false; } | '&' { $$ = true; } ; optional_ellipsis: /* empty */ { $$ = false; } | T_ELLIPSIS { $$ = true; } ; function_declaration_statement: T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type '{' inner_statement_list '}' { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; } ; class_declaration_statement: class_entry_type identifier extends_from implements_list '{' class_statement_list '}' { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]]; $this->checkClass($$, #2); } | T_INTERFACE identifier interface_extends_list '{' class_statement_list '}' { $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]]; $this->checkInterface($$, #2); } | T_TRAIT identifier '{' class_statement_list '}' { $$ = Stmt\Trait_[$2, ['stmts' => $4]]; } ; class_entry_type: T_CLASS { $$ = 0; } | T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; } ; extends_from: /* empty */ { $$ = null; } | T_EXTENDS class_name { $$ = $2; } ; interface_extends_list: /* empty */ { $$ = array(); } | T_EXTENDS class_name_list { $$ = $2; } ; implements_list: /* empty */ { $$ = array(); } | T_IMPLEMENTS class_name_list { $$ = $2; } ; class_name_list: class_name { init($1); } | class_name_list ',' class_name { push($1, $3); } ; for_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } ; foreach_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } ; declare_statement: non_empty_statement { $$ = toArray($1); } | ';' { $$ = null; } | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } ; declare_list: declare_list_element { init($1); } | declare_list ',' declare_list_element { push($1, $3); } ; declare_list_element: identifier '=' static_scalar { $$ = Stmt\DeclareDeclare[$1, $3]; } ; switch_case_list: '{' case_list '}' { $$ = $2; } | '{' ';' case_list '}' { $$ = $3; } | ':' case_list T_ENDSWITCH ';' { $$ = $2; } | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } ; case_list: /* empty */ { init(); } | case_list case { push($1, $2); } ; case: T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } ; case_separator: ':' | ';' ; while_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } ; elseif_list: /* empty */ { init(); } | elseif_list elseif { push($1, $2); } ; elseif: T_ELSEIF parentheses_expr statement { $$ = Stmt\ElseIf_[$2, toArray($3)]; } ; new_elseif_list: /* empty */ { init(); } | new_elseif_list new_elseif { push($1, $2); } ; new_elseif: T_ELSEIF parentheses_expr ':' inner_statement_list { $$ = Stmt\ElseIf_[$2, $4]; } ; else_single: /* empty */ { $$ = null; } | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } ; new_else_single: /* empty */ { $$ = null; } | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } ; foreach_variable: variable { $$ = array($1, false); } | '&' variable { $$ = array($2, true); } | list_expr { $$ = array($1, false); } ; parameter_list: non_empty_parameter_list { $$ = $1; } | /* empty */ { $$ = array(); } ; non_empty_parameter_list: parameter { init($1); } | non_empty_parameter_list ',' parameter { push($1, $3); } ; parameter: optional_param_type optional_ref optional_ellipsis plain_variable { $$ = Node\Param[$4, null, $1, $2, $3]; $this->checkParam($$); } | optional_param_type optional_ref optional_ellipsis plain_variable '=' static_scalar { $$ = Node\Param[$4, $6, $1, $2, $3]; $this->checkParam($$); } ; type: name { $$ = $1; } | T_ARRAY { $$ = Node\Identifier['array']; } | T_CALLABLE { $$ = Node\Identifier['callable']; } ; optional_param_type: /* empty */ { $$ = null; } | type { $$ = $1; } ; optional_return_type: /* empty */ { $$ = null; } | ':' type { $$ = $2; } ; argument_list: '(' ')' { $$ = array(); } | '(' non_empty_argument_list ')' { $$ = $2; } | '(' yield_expr ')' { $$ = array(Node\Arg[$2, false, false]); } ; non_empty_argument_list: argument { init($1); } | non_empty_argument_list ',' argument { push($1, $3); } ; argument: expr { $$ = Node\Arg[$1, false, false]; } | '&' variable { $$ = Node\Arg[$2, true, false]; } | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } ; global_var_list: global_var_list ',' global_var { push($1, $3); } | global_var { init($1); } ; global_var: plain_variable { $$ = $1; } | '$' variable { $$ = Expr\Variable[$2]; } | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } ; static_var_list: static_var_list ',' static_var { push($1, $3); } | static_var { init($1); } ; static_var: plain_variable { $$ = Stmt\StaticVar[$1, null]; } | plain_variable '=' static_scalar { $$ = Stmt\StaticVar[$1, $3]; } ; class_statement_list_ex: class_statement_list_ex class_statement { if ($2 !== null) { push($1, $2); } } | /* empty */ { init(); } ; class_statement_list: class_statement_list_ex { makeZeroLengthNop($nop, $this->lookaheadStartAttributes); if ($nop !== null) { $1[] = $nop; } $$ = $1; } ; class_statement: variable_modifiers property_declaration_list ';' { $$ = Stmt\Property[$1, $2]; $this->checkProperty($$, #1); } | T_CONST class_const_list ';' { $$ = Stmt\ClassConst[$2, 0]; } | method_modifiers T_FUNCTION optional_ref identifier_ex '(' parameter_list ')' optional_return_type method_body { $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]]; $this->checkClassMethod($$, #1); } | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } ; trait_adaptations: ';' { $$ = array(); } | '{' trait_adaptation_list '}' { $$ = $2; } ; trait_adaptation_list: /* empty */ { init(); } | trait_adaptation_list trait_adaptation { push($1, $2); } ; trait_adaptation: trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } | trait_method_reference T_AS member_modifier identifier_ex ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } | trait_method_reference T_AS member_modifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } | trait_method_reference T_AS identifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } | trait_method_reference T_AS reserved_non_modifiers_identifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } ; trait_method_reference_fully_qualified: name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = array($1, $3); } ; trait_method_reference: trait_method_reference_fully_qualified { $$ = $1; } | identifier_ex { $$ = array(null, $1); } ; method_body: ';' /* abstract method */ { $$ = null; } | '{' inner_statement_list '}' { $$ = $2; } ; variable_modifiers: non_empty_member_modifiers { $$ = $1; } | T_VAR { $$ = 0; } ; method_modifiers: /* empty */ { $$ = 0; } | non_empty_member_modifiers { $$ = $1; } ; non_empty_member_modifiers: member_modifier { $$ = $1; } | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } ; member_modifier: T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } ; property_declaration_list: property_declaration { init($1); } | property_declaration_list ',' property_declaration { push($1, $3); } ; property_decl_name: T_VARIABLE { $$ = Node\VarLikeIdentifier[parseVar($1)]; } ; property_declaration: property_decl_name { $$ = Stmt\PropertyProperty[$1, null]; } | property_decl_name '=' static_scalar { $$ = Stmt\PropertyProperty[$1, $3]; } ; expr_list: expr_list ',' expr { push($1, $3); } | expr { init($1); } ; for_expr: /* empty */ { $$ = array(); } | expr_list { $$ = $1; } ; expr: variable { $$ = $1; } | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' '&' variable { $$ = Expr\AssignRef[$1, $4]; } | variable '=' '&' new_expr { $$ = Expr\AssignRef[$1, $4]; } | new_expr { $$ = $1; } | T_CLONE expr { $$ = Expr\Clone_[$2]; } | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } | variable T_COALESCE_EQUAL expr { $$ = Expr\AssignOp\Coalesce [$1, $3]; } | variable T_INC { $$ = Expr\PostInc[$1]; } | T_INC variable { $$ = Expr\PreInc [$2]; } | variable T_DEC { $$ = Expr\PostDec[$1]; } | T_DEC variable { $$ = Expr\PreDec [$2]; } | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } | expr '&' expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } | '!' expr { $$ = Expr\BooleanNot[$2]; } | '~' expr { $$ = Expr\BitwiseNot[$2]; } | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } | parentheses_expr { $$ = $1; } /* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */ | '(' new_expr ')' { $$ = $2; } | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } | T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; } | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } | T_EVAL parentheses_expr { $$ = Expr\Eval_[$2]; } | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } | T_DOUBLE_CAST expr { $attrs = attributes(); $attrs['kind'] = $this->getFloatCastKind($1); $$ = new Expr\Cast\Double($2, $attrs); } | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } | T_EXIT exit_expr { $attrs = attributes(); $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; $$ = new Expr\Exit_($2, $attrs); } | '@' expr { $$ = Expr\ErrorSuppress[$2]; } | scalar { $$ = $1; } | array_expr { $$ = $1; } | scalar_dereference { $$ = $1; } | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } | T_PRINT expr { $$ = Expr\Print_[$2]; } | T_YIELD { $$ = Expr\Yield_[null, null]; } | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type '{' inner_statement_list '}' { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; } | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type '{' inner_statement_list '}' { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; } ; parentheses_expr: '(' expr ')' { $$ = $2; } | '(' yield_expr ')' { $$ = $2; } ; yield_expr: T_YIELD expr { $$ = Expr\Yield_[$2, null]; } | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } ; array_expr: T_ARRAY '(' array_pair_list ')' { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; $$ = new Expr\Array_($3, $attrs); } | '[' array_pair_list ']' { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; $$ = new Expr\Array_($2, $attrs); } ; scalar_dereference: array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $attrs = attributes(); $attrs['kind'] = strKind($1); $$ = Expr\ArrayDimFetch[new Scalar\String_(Scalar\String_::parse($1), $attrs), $3]; } | constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } /* alternative array syntax missing intentionally */ ; anonymous_class: T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2); $this->checkClass($$[0], -1); } ; new_expr: T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } | T_NEW anonymous_class { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } ; lexical_vars: /* empty */ { $$ = array(); } | T_USE '(' lexical_var_list ')' { $$ = $3; } ; lexical_var_list: lexical_var { init($1); } | lexical_var_list ',' lexical_var { push($1, $3); } ; lexical_var: optional_ref plain_variable { $$ = Expr\ClosureUse[$2, $1]; } ; function_call: name argument_list { $$ = Expr\FuncCall[$1, $2]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex argument_list { $$ = Expr\StaticCall[$1, $3, $4]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list { $$ = Expr\StaticCall[$1, $4, $6]; } | static_property argument_list { $$ = $this->fixupPhp5StaticPropCall($1, $2, attributes()); } | variable_without_objects argument_list { $$ = Expr\FuncCall[$1, $2]; } | function_call '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } /* alternative array syntax missing intentionally */ ; class_name: T_STATIC { $$ = Name[$1]; } | name { $$ = $1; } ; name: T_STRING { $$ = Name[$1]; } | T_NAME_QUALIFIED { $$ = Name[$1]; } | T_NAME_FULLY_QUALIFIED { $$ = Name\FullyQualified[substr($1, 1)]; } | T_NAME_RELATIVE { $$ = Name\Relative[substr($1, 10)]; } ; class_name_reference: class_name { $$ = $1; } | dynamic_class_name_reference { $$ = $1; } ; dynamic_class_name_reference: object_access_for_dcnr { $$ = $1; } | base_variable { $$ = $1; } ; class_name_or_var: class_name { $$ = $1; } | reference_variable { $$ = $1; } ; object_access_for_dcnr: base_variable T_OBJECT_OPERATOR object_property { $$ = Expr\PropertyFetch[$1, $3]; } | object_access_for_dcnr T_OBJECT_OPERATOR object_property { $$ = Expr\PropertyFetch[$1, $3]; } | object_access_for_dcnr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | object_access_for_dcnr '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } ; exit_expr: /* empty */ { $$ = null; } | '(' ')' { $$ = null; } | parentheses_expr { $$ = $1; } ; backticks_expr: /* empty */ { $$ = array(); } | T_ENCAPSED_AND_WHITESPACE { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`', false)]); } | encaps_list { parseEncapsed($1, '`', false); $$ = $1; } ; ctor_arguments: /* empty */ { $$ = array(); } | argument_list { $$ = $1; } ; common_scalar: T_LNUMBER { $$ = $this->parseLNumber($1, attributes(), true); } | T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; } | T_CONSTANT_ENCAPSED_STRING { $attrs = attributes(); $attrs['kind'] = strKind($1); $$ = new Scalar\String_(Scalar\String_::parse($1, false), $attrs); } | T_LINE { $$ = Scalar\MagicConst\Line[]; } | T_FILE { $$ = Scalar\MagicConst\File[]; } | T_DIR { $$ = Scalar\MagicConst\Dir[]; } | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), false); } | T_START_HEREDOC T_END_HEREDOC { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), false); } ; static_scalar: common_scalar { $$ = $1; } | class_name T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = Expr\ClassConstFetch[$1, $3]; } | name { $$ = Expr\ConstFetch[$1]; } | T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; } | '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; } | static_operation { $$ = $1; } ; static_operation: static_scalar T_BOOLEAN_OR static_scalar { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } | static_scalar T_BOOLEAN_AND static_scalar { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } | static_scalar T_LOGICAL_OR static_scalar { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } | static_scalar T_LOGICAL_AND static_scalar { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } | static_scalar T_LOGICAL_XOR static_scalar { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } | static_scalar '|' static_scalar { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } | static_scalar '&' static_scalar { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | static_scalar '^' static_scalar { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } | static_scalar '.' static_scalar { $$ = Expr\BinaryOp\Concat [$1, $3]; } | static_scalar '+' static_scalar { $$ = Expr\BinaryOp\Plus [$1, $3]; } | static_scalar '-' static_scalar { $$ = Expr\BinaryOp\Minus [$1, $3]; } | static_scalar '*' static_scalar { $$ = Expr\BinaryOp\Mul [$1, $3]; } | static_scalar '/' static_scalar { $$ = Expr\BinaryOp\Div [$1, $3]; } | static_scalar '%' static_scalar { $$ = Expr\BinaryOp\Mod [$1, $3]; } | static_scalar T_SL static_scalar { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } | static_scalar T_SR static_scalar { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } | static_scalar T_POW static_scalar { $$ = Expr\BinaryOp\Pow [$1, $3]; } | '+' static_scalar %prec T_INC { $$ = Expr\UnaryPlus [$2]; } | '-' static_scalar %prec T_INC { $$ = Expr\UnaryMinus[$2]; } | '!' static_scalar { $$ = Expr\BooleanNot[$2]; } | '~' static_scalar { $$ = Expr\BitwiseNot[$2]; } | static_scalar T_IS_IDENTICAL static_scalar { $$ = Expr\BinaryOp\Identical [$1, $3]; } | static_scalar T_IS_NOT_IDENTICAL static_scalar { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } | static_scalar T_IS_EQUAL static_scalar { $$ = Expr\BinaryOp\Equal [$1, $3]; } | static_scalar T_IS_NOT_EQUAL static_scalar { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } | static_scalar '<' static_scalar { $$ = Expr\BinaryOp\Smaller [$1, $3]; } | static_scalar T_IS_SMALLER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } | static_scalar '>' static_scalar { $$ = Expr\BinaryOp\Greater [$1, $3]; } | static_scalar T_IS_GREATER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } | static_scalar '?' static_scalar ':' static_scalar { $$ = Expr\Ternary[$1, $3, $5]; } | static_scalar '?' ':' static_scalar { $$ = Expr\Ternary[$1, null, $4]; } | static_scalar '[' static_scalar ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | '(' static_scalar ')' { $$ = $2; } ; constant: name { $$ = Expr\ConstFetch[$1]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_ex { $$ = Expr\ClassConstFetch[$1, $3]; } ; scalar: common_scalar { $$ = $1; } | constant { $$ = $1; } | '"' encaps_list '"' { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); } ; static_array_pair_list: /* empty */ { $$ = array(); } | non_empty_static_array_pair_list optional_comma { $$ = $1; } ; optional_comma: /* empty */ | ',' ; non_empty_static_array_pair_list: non_empty_static_array_pair_list ',' static_array_pair { push($1, $3); } | static_array_pair { init($1); } ; static_array_pair: static_scalar T_DOUBLE_ARROW static_scalar { $$ = Expr\ArrayItem[$3, $1, false]; } | static_scalar { $$ = Expr\ArrayItem[$1, null, false]; } ; variable: object_access { $$ = $1; } | base_variable { $$ = $1; } | function_call { $$ = $1; } | new_expr_array_deref { $$ = $1; } ; new_expr_array_deref: '(' new_expr ')' '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$2, $5]; } | new_expr_array_deref '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } /* alternative array syntax missing intentionally */ ; object_access: variable_or_new_expr T_OBJECT_OPERATOR object_property { $$ = Expr\PropertyFetch[$1, $3]; } | variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list { $$ = Expr\MethodCall[$1, $3, $4]; } | object_access argument_list { $$ = Expr\FuncCall[$1, $2]; } | object_access '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | object_access '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } ; variable_or_new_expr: variable { $$ = $1; } | '(' new_expr ')' { $$ = $2; } ; variable_without_objects: reference_variable { $$ = $1; } | '$' variable_without_objects { $$ = Expr\Variable[$2]; } ; base_variable: variable_without_objects { $$ = $1; } | static_property { $$ = $1; } ; static_property: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable { $$ = Expr\StaticPropertyFetch[$1, $4]; } | static_property_with_arrays { $$ = $1; } ; static_property_simple_name: T_VARIABLE { $var = parseVar($1); $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; } ; static_property_with_arrays: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_property_simple_name { $$ = Expr\StaticPropertyFetch[$1, $3]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}' { $$ = Expr\StaticPropertyFetch[$1, $5]; } | static_property_with_arrays '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | static_property_with_arrays '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } ; reference_variable: reference_variable '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | reference_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } | plain_variable { $$ = $1; } | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } ; dim_offset: /* empty */ { $$ = null; } | expr { $$ = $1; } ; object_property: identifier { $$ = $1; } | '{' expr '}' { $$ = $2; } | variable_without_objects { $$ = $1; } | error { $$ = Expr\Error[]; $this->errorState = 2; } ; list_expr: T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; } ; list_expr_elements: list_expr_elements ',' list_expr_element { push($1, $3); } | list_expr_element { init($1); } ; list_expr_element: variable { $$ = Expr\ArrayItem[$1, null, false]; } | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } | /* empty */ { $$ = null; } ; array_pair_list: /* empty */ { $$ = array(); } | non_empty_array_pair_list optional_comma { $$ = $1; } ; non_empty_array_pair_list: non_empty_array_pair_list ',' array_pair { push($1, $3); } | array_pair { init($1); } ; array_pair: expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } | expr { $$ = Expr\ArrayItem[$1, null, false]; } | expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; } | '&' variable { $$ = Expr\ArrayItem[$2, null, true]; } | T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; } ; encaps_list: encaps_list encaps_var { push($1, $2); } | encaps_list encaps_string_part { push($1, $2); } | encaps_var { init($1); } | encaps_string_part encaps_var { init($1, $2); } ; encaps_string_part: T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } ; encaps_str_varname: T_STRING_VARNAME { $$ = Expr\Variable[$1]; } ; encaps_var: plain_variable { $$ = $1; } | plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | plain_variable T_OBJECT_OPERATOR identifier { $$ = Expr\PropertyFetch[$1, $3]; } | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}' { $$ = Expr\ArrayDimFetch[$2, $4]; } | T_CURLY_OPEN variable '}' { $$ = $2; } ; encaps_var_offset: T_STRING { $$ = Scalar\String_[$1]; } | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } | plain_variable { $$ = $1; } ; %% semValue #semval($,%t) $this->semValue #semval(%n) $stackPos-(%l-%n) #semval(%n,%t) $stackPos-(%l-%n) namespace PhpParser\Parser; use PhpParser\Error; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Name; use PhpParser\Node\Scalar; use PhpParser\Node\Stmt; #include; /* This is an automatically GENERATED file, which should not be manually edited. * Instead edit one of the following: * * the grammar files grammar/php5.y or grammar/php7.y * * the skeleton file grammar/parser.template * * the preprocessing script grammar/rebuildParsers.php */ class #(-p) extends \PhpParser\ParserAbstract { protected $tokenToSymbolMapSize = #(YYMAXLEX); protected $actionTableSize = #(YYLAST); protected $gotoTableSize = #(YYGLAST); protected $invalidSymbol = #(YYBADCH); protected $errorSymbol = #(YYINTERRTOK); protected $defaultAction = #(YYDEFAULT); protected $unexpectedTokenRule = #(YYUNEXPECTED); protected $YY2TBLSTATE = #(YY2TBLSTATE); protected $numNonLeafStates = #(YYNLSTATES); protected $symbolToName = array( #listvar terminals ); protected $tokenToSymbol = array( #listvar yytranslate ); protected $action = array( #listvar yyaction ); protected $actionCheck = array( #listvar yycheck ); protected $actionBase = array( #listvar yybase ); protected $actionDefault = array( #listvar yydefault ); protected $goto = array( #listvar yygoto ); protected $gotoCheck = array( #listvar yygcheck ); protected $gotoBase = array( #listvar yygbase ); protected $gotoDefault = array( #listvar yygdefault ); protected $ruleToNonTerminal = array( #listvar yylhs ); protected $ruleToLength = array( #listvar yylen ); #if -t protected $productions = array( #production-strings; ); #endif protected function initReduceCallbacks() { $this->reduceCallbacks = [ #reduce %n => function ($stackPos) { %b }, #noact %n => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, #endreduce ]; } } #tailcode; 'Php5', __DIR__ . '/php7.y' => 'Php7']; $tokensFile = __DIR__ . '/tokens.y'; $tokensTemplate = __DIR__ . '/tokens.template'; $skeletonFile = __DIR__ . '/parser.template'; $tmpGrammarFile = __DIR__ . '/tmp_parser.phpy'; $tmpResultFile = __DIR__ . '/tmp_parser.php'; $resultDir = __DIR__ . '/../lib/PhpParser/Parser'; $tokensResultsFile = $resultDir . '/Tokens.php'; $kmyacc = \getenv('KMYACC'); if (!$kmyacc) { // Use phpyacc from dev dependencies by default. $kmyacc = __DIR__ . '/../vendor/bin/phpyacc'; } $options = \array_flip($argv); $optionDebug = isset($options['--debug']); $optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']); /////////////////////////////// /// Utility regex constants /// /////////////////////////////// const LIB = '(?(DEFINE) (?\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\') (?"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+") (?(?&singleQuotedString)|(?&doubleQuotedString)) (?/\\*[^*]*+(?:\\*(?!/)[^*]*+)*+\\*/) (?\\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+}) )'; const PARAMS = '\\[(?[^[\\]]*+(?:\\[(?¶ms)\\][^[\\]]*+)*+)\\]'; const ARGS = '\\((?[^()]*+(?:\\((?&args)\\)[^()]*+)*+)\\)'; /////////////////// /// Main script /// /////////////////// $tokens = \file_get_contents($tokensFile); foreach ($grammarFileToName as $grammarFile => $name) { echo "Building temporary {$name} grammar file.\n"; $grammarCode = \file_get_contents($grammarFile); $grammarCode = \str_replace('%tokens', $tokens, $grammarCode); $grammarCode = \_HumbugBoxd02f763d3c56\resolveNodes($grammarCode); $grammarCode = \_HumbugBoxd02f763d3c56\resolveMacros($grammarCode); $grammarCode = \_HumbugBoxd02f763d3c56\resolveStackAccess($grammarCode); \file_put_contents($tmpGrammarFile, $grammarCode); $additionalArgs = $optionDebug ? '-t -v' : ''; echo "Building {$name} parser.\n"; $output = \_HumbugBoxd02f763d3c56\execCmd("{$kmyacc} {$additionalArgs} -m {$skeletonFile} -p {$name} {$tmpGrammarFile}"); $resultCode = \file_get_contents($tmpResultFile); $resultCode = \_HumbugBoxd02f763d3c56\removeTrailingWhitespace($resultCode); \_HumbugBoxd02f763d3c56\ensureDirExists($resultDir); \file_put_contents("{$resultDir}/{$name}.php", $resultCode); \unlink($tmpResultFile); echo "Building token definition.\n"; $output = \_HumbugBoxd02f763d3c56\execCmd("{$kmyacc} -m {$tokensTemplate} {$tmpGrammarFile}"); \rename($tmpResultFile, $tokensResultsFile); if (!$optionKeepTmpGrammar) { \unlink($tmpGrammarFile); } } /////////////////////////////// /// Preprocessing functions /// /////////////////////////////// function resolveNodes($code) { return \preg_replace_callback('~\\b(?[A-Z][a-zA-Z_\\\\]++)\\s*' . \PARAMS . '~', function ($matches) { // recurse $matches['params'] = \_HumbugBoxd02f763d3c56\resolveNodes($matches['params']); $params = \_HumbugBoxd02f763d3c56\magicSplit('(?:' . \PARAMS . '|' . \ARGS . ')(*SKIP)(*FAIL)|,', $matches['params']); $paramCode = ''; foreach ($params as $param) { $paramCode .= $param . ', '; } return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())'; }, $code); } function resolveMacros($code) { return \preg_replace_callback('~\\b(?)(?!array\\()(?[a-z][A-Za-z]++)' . \ARGS . '~', function ($matches) { // recurse $matches['args'] = \_HumbugBoxd02f763d3c56\resolveMacros($matches['args']); $name = $matches['name']; $args = \_HumbugBoxd02f763d3c56\magicSplit('(?:' . \PARAMS . '|' . \ARGS . ')(*SKIP)(*FAIL)|,', $matches['args']); if ('attributes' === $name) { \_HumbugBoxd02f763d3c56\assertArgs(0, $args, $name); return '$this->startAttributeStack[#1] + $this->endAttributes'; } if ('stackAttributes' === $name) { \_HumbugBoxd02f763d3c56\assertArgs(1, $args, $name); return '$this->startAttributeStack[' . $args[0] . ']' . ' + $this->endAttributeStack[' . $args[0] . ']'; } if ('init' === $name) { return '$$ = array(' . \implode(', ', $args) . ')'; } if ('push' === $name) { \_HumbugBoxd02f763d3c56\assertArgs(2, $args, $name); return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0]; } if ('pushNormalizing' === $name) { \_HumbugBoxd02f763d3c56\assertArgs(2, $args, $name); return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); }' . ' else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }'; } if ('toArray' == $name) { \_HumbugBoxd02f763d3c56\assertArgs(1, $args, $name); return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')'; } if ('parseVar' === $name) { \_HumbugBoxd02f763d3c56\assertArgs(1, $args, $name); return 'substr(' . $args[0] . ', 1)'; } if ('parseEncapsed' === $name) { \_HumbugBoxd02f763d3c56\assertArgs(3, $args, $name); return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\\Scalar\\EncapsedStringPart) {' . ' $s->value = Node\\Scalar\\String_::parseEscapeSequences($s->value, ' . $args[1] . ', ' . $args[2] . '); } }'; } if ('makeNop' === $name) { \_HumbugBoxd02f763d3c56\assertArgs(3, $args, $name); return '$startAttributes = ' . $args[1] . ';' . ' if (isset($startAttributes[\'comments\']))' . ' { ' . $args[0] . ' = new Stmt\\Nop($startAttributes + ' . $args[2] . '); }' . ' else { ' . $args[0] . ' = null; }'; } if ('makeZeroLengthNop' == $name) { \_HumbugBoxd02f763d3c56\assertArgs(2, $args, $name); return '$startAttributes = ' . $args[1] . ';' . ' if (isset($startAttributes[\'comments\']))' . ' { ' . $args[0] . ' = new Stmt\\Nop($this->createCommentNopAttributes($startAttributes[\'comments\'])); }' . ' else { ' . $args[0] . ' = null; }'; } if ('strKind' === $name) { \_HumbugBoxd02f763d3c56\assertArgs(1, $args, $name); return '(' . $args[0] . '[0] === "\'" || (' . $args[0] . '[1] === "\'" && ' . '(' . $args[0] . '[0] === \'b\' || ' . $args[0] . '[0] === \'B\')) ' . '? Scalar\\String_::KIND_SINGLE_QUOTED : Scalar\\String_::KIND_DOUBLE_QUOTED)'; } if ('prependLeadingComments' === $name) { \_HumbugBoxd02f763d3c56\assertArgs(1, $args, $name); return '$attrs = $this->startAttributeStack[#1]; $stmts = ' . $args[0] . '; ' . 'if (!empty($attrs[\'comments\'])) {' . '$stmts[0]->setAttribute(\'comments\', ' . 'array_merge($attrs[\'comments\'], $stmts[0]->getAttribute(\'comments\', []))); }'; } return $matches[0]; }, $code); } function assertArgs($num, $args, $name) { if ($num != \count($args)) { die('Wrong argument count for ' . $name . '().'); } } function resolveStackAccess($code) { $code = \preg_replace('/\\$\\d+/', '$this->semStack[$0]', $code); $code = \preg_replace('/#(\\d+)/', '$$1', $code); return $code; } function removeTrailingWhitespace($code) { $lines = \explode("\n", $code); $lines = \array_map('rtrim', $lines); return \implode("\n", $lines); } function ensureDirExists($dir) { if (!\is_dir($dir)) { \mkdir($dir, 0777, \true); } } function execCmd($cmd) { $output = \trim(\shell_exec("{$cmd} 2>&1")); if ($output !== "") { echo "> " . $cmd . "\n"; echo $output; } return $output; } ////////////////////////////// /// Regex helper functions /// ////////////////////////////// function regex($regex) { return '~' . \LIB . '(?:' . \str_replace('~', '\\~', $regex) . ')~'; } function magicSplit($regex, $string) { $pieces = \preg_split(\_HumbugBoxd02f763d3c56\regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string); foreach ($pieces as &$piece) { $piece = \trim($piece); } if ($pieces === ['']) { return []; } return $pieces; } semValue #semval($,%t) $this->semValue #semval(%n) $this->stackPos-(%l-%n) #semval(%n,%t) $this->stackPos-(%l-%n) namespace PhpParser\Parser; #include; /* GENERATED file based on grammar/tokens.y */ final class Tokens { #tokenval const %s = %n; #endtokenval } BSD 3-Clause License Copyright (c) 2011, Nikita Popov All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. lineNumber = $lineNumber; $this->columnNumber = $columnNumber; } /** * Returns the line number that is covered by this location. */ public function getLineNumber() : int { return $this->lineNumber; } /** * Returns the column number (character position on a line) for this location object. */ public function getColumnNumber() : int { return $this->columnNumber; } } fqsen = $fqsen; if (isset($matches[2])) { $this->name = $matches[2]; } else { $matches = \explode('\\', $fqsen); $name = \end($matches); \assert(\is_string($name)); $this->name = \trim($name, '()'); } } /** * converts this class to string. */ public function __toString() : string { return $this->fqsen; } /** * Returns the name of the element without path. */ public function getName() : string { return $this->name; } } descriptionFactory = $descriptionFactory; $this->tagFactory = $tagFactory; } /** * Factory method for easy instantiation. * * @param array> $additionalTags */ public static function createInstance(array $additionalTags = []) : self { $fqsenResolver = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver(); $tagFactory = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\StandardTagFactory($fqsenResolver); $descriptionFactory = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory($tagFactory); $tagFactory->addService($descriptionFactory); $tagFactory->addService(new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\TypeResolver($fqsenResolver)); $docBlockFactory = new self($descriptionFactory, $tagFactory); foreach ($additionalTags as $tagName => $tagHandler) { $docBlockFactory->registerTagHandler($tagName, $tagHandler); } return $docBlockFactory; } /** * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the * getDocComment method (such as a ReflectionClass object). */ public function create($docblock, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Location $location = null) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock { if (\is_object($docblock)) { if (!\method_exists($docblock, 'getDocComment')) { $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method'; throw new \InvalidArgumentException($exceptionMessage); } $docblock = $docblock->getDocComment(); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($docblock); } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($docblock); if ($context === null) { $context = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context(''); } $parts = $this->splitDocBlock($this->stripDocComment($docblock)); [$templateMarker, $summary, $description, $tags] = $parts; return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock($summary, $description ? $this->descriptionFactory->create($description, $context) : null, $this->parseTagBlock($tags, $context), $context, $location, $templateMarker === '#@+', $templateMarker === '#@-'); } /** * @param class-string $handler */ public function registerTagHandler(string $tagName, string $handler) : void { $this->tagFactory->registerTagHandler($tagName, $handler); } /** * Strips the asterisks from the DocBlock comment. * * @param string $comment String containing the comment text. */ private function stripDocComment(string $comment) : string { $comment = \preg_replace('#[ \\t]*(?:\\/\\*\\*|\\*\\/|\\*)?[ \\t]?(.*)?#u', '$1', $comment); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($comment); $comment = \trim($comment); // reg ex above is not able to remove */ from a single line docblock if (\substr($comment, -2) === '*/') { $comment = \trim(\substr($comment, 0, -2)); } return \str_replace(["\r\n", "\r"], "\n", $comment); } // phpcs:disable /** * Splits the DocBlock into a template marker, summary, description and block of tags. * * @param string $comment Comment to split into the sub-parts. * * @return string[] containing the template marker (if any), summary, description and a string containing the tags. * * @author Mike van Riel for extending the regex with template marker support. * * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. */ private function splitDocBlock(string $comment) : array { // phpcs:enable // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the // performance impact of running a regular expression if (\strpos($comment, '@') === 0) { return ['', '', '', $comment]; } // clears all extra horizontal whitespace from the line endings to prevent parsing issues $comment = \preg_replace('/\\h*$/Sum', '', $comment); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::string($comment); /* * Splits the docblock into a template marker, summary, description and tags section. * * - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may * occur after it and will be stripped). * - The short description is started from the first character until a dot is encountered followed by a * newline OR two consecutive newlines (horizontal whitespace is taken into account to consider spacing * errors). This is optional. * - The long description, any character until a new line is encountered followed by an @ and word * characters (a tag). This is optional. * - Tags; the remaining characters * * Big thanks to RichardJ for contributing this Regular Expression */ \preg_match('/ \\A # 1. Extract the template marker (?:(\\#\\@\\+|\\#\\@\\-)\\n?)? # 2. Extract the summary (?: (?! @\\pL ) # The summary may not start with an @ ( [^\\n.]+ (?: (?! \\. \\n | \\n{2} ) # End summary upon a dot followed by newline or two newlines [\\n.]* (?! [ \\t]* @\\pL ) # End summary when an @ is found as first character on a new line [^\\n.]+ # Include anything else )* \\.? )? ) # 3. Extract the description (?: \\s* # Some form of whitespace _must_ precede a description because a summary must be there (?! @\\pL ) # The description may not start with an @ ( [^\\n]+ (?: \\n+ (?! [ \\t]* @\\pL ) # End description when an @ is found as first character on a new line [^\\n]+ # Include anything else )* ) )? # 4. Extract the tags (anything that follows) (\\s+ [\\s\\S]*)? # everything that follows /ux', $comment, $matches); \array_shift($matches); while (\count($matches) < 4) { $matches[] = ''; } return $matches; } /** * Creates the tag objects. * * @param string $tags Tag block to parse. * @param Types\Context $context Context of the parsed Tag * * @return DocBlock\Tag[] */ private function parseTagBlock(string $tags, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : array { $tags = $this->filterTagBlock($tags); if ($tags === null) { return []; } $result = []; $lines = $this->splitTagBlockIntoTagLines($tags); foreach ($lines as $key => $tagLine) { $result[$key] = $this->tagFactory->create(\trim($tagLine), $context); } return $result; } /** * @return string[] */ private function splitTagBlockIntoTagLines(string $tags) : array { $result = []; foreach (\explode("\n", $tags) as $tagLine) { if ($tagLine !== '' && \strpos($tagLine, '@') === 0) { $result[] = $tagLine; } else { $result[\count($result) - 1] .= "\n" . $tagLine; } } return $result; } private function filterTagBlock(string $tags) : ?string { $tags = \trim($tags); if (!$tags) { return null; } if ($tags[0] !== '@') { // @codeCoverageIgnoreStart // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that // we didn't foresee. throw new \LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); // @codeCoverageIgnoreEnd } return $tags; } } summary = $summary; $this->description = $description ?: new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Description(''); foreach ($tags as $tag) { $this->addTag($tag); } $this->context = $context; $this->location = $location; $this->isTemplateEnd = $isTemplateEnd; $this->isTemplateStart = $isTemplateStart; } public function getSummary() : string { return $this->summary; } public function getDescription() : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Description { return $this->description; } /** * Returns the current context. */ public function getContext() : ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context { return $this->context; } /** * Returns the current location. */ public function getLocation() : ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Location { return $this->location; } /** * Returns whether this DocBlock is the start of a Template section. * * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker * (`#@+`) that is appended directly after the opening `/**` of a DocBlock. * * An example of such an opening is: * * ``` * /**#@+ * * My DocBlock * * / * ``` * * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all * elements that follow until another DocBlock is found that contains the closing marker (`#@-`). * * @see self::isTemplateEnd() for the check whether a closing marker was provided. */ public function isTemplateStart() : bool { return $this->isTemplateStart; } /** * Returns whether this DocBlock is the end of a Template section. * * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality. */ public function isTemplateEnd() : bool { return $this->isTemplateEnd; } /** * Returns the tags for this DocBlock. * * @return Tag[] */ public function getTags() : array { return $this->tags; } /** * Returns an array of tags matching the given name. If no tags are found * an empty array is returned. * * @param string $name String to search by. * * @return Tag[] */ public function getTagsByName(string $name) : array { $result = []; foreach ($this->getTags() as $tag) { if ($tag->getName() !== $name) { continue; } $result[] = $tag; } return $result; } /** * Checks if a tag of a certain type is present in this DocBlock. * * @param string $name Tag name to check for. */ public function hasTag(string $name) : bool { foreach ($this->getTags() as $tag) { if ($tag->getName() === $name) { return \true; } } return \false; } /** * Remove a tag from this DocBlock. * * @param Tag $tagToRemove The tag to remove. */ public function removeTag(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tag $tagToRemove) : void { foreach ($this->tags as $key => $tag) { if ($tag === $tagToRemove) { unset($this->tags[$key]); break; } } } /** * Adds a tag to this DocBlock. * * @param Tag $tag The tag to add. */ private function addTag(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tag $tag) : void { $this->tags[] = $tag; } } getFilePath(); $file = $this->getExampleFileContents($filename); if (!$file) { return \sprintf('** File not found : %s **', $filename); } return \implode('', \array_slice($file, $example->getStartingLine() - 1, $example->getLineCount())); } /** * Registers the project's root directory where an 'examples' folder can be expected. */ public function setSourceDirectory(string $directory = '') : void { $this->sourceDirectory = $directory; } /** * Returns the project's root directory where an 'examples' folder can be expected. */ public function getSourceDirectory() : string { return $this->sourceDirectory; } /** * Registers a series of directories that may contain examples. * * @param string[] $directories */ public function setExampleDirectories(array $directories) : void { $this->exampleDirectories = $directories; } /** * Returns a series of directories that may contain examples. * * @return string[] */ public function getExampleDirectories() : array { return $this->exampleDirectories; } /** * Attempts to find the requested example file and returns its contents or null if no file was found. * * This method will try several methods in search of the given example file, the first one it encounters is * returned: * * 1. Iterates through all examples folders for the given filename * 2. Checks the source folder for the given filename * 3. Checks the 'examples' folder in the current working directory for examples * 4. Checks the path relative to the current working directory for the given filename * * @return string[] all lines of the example file */ private function getExampleFileContents(string $filename) : ?array { $normalizedPath = null; foreach ($this->exampleDirectories as $directory) { $exampleFileFromConfig = $this->constructExamplePath($directory, $filename); if (\is_readable($exampleFileFromConfig)) { $normalizedPath = $exampleFileFromConfig; break; } } if (!$normalizedPath) { if (\is_readable($this->getExamplePathFromSource($filename))) { $normalizedPath = $this->getExamplePathFromSource($filename); } elseif (\is_readable($this->getExamplePathFromExampleDirectory($filename))) { $normalizedPath = $this->getExamplePathFromExampleDirectory($filename); } elseif (\is_readable($filename)) { $normalizedPath = $filename; } } $lines = $normalizedPath && \is_readable($normalizedPath) ? \file($normalizedPath) : \false; return $lines !== \false ? $lines : null; } /** * Get example filepath based on the example directory inside your project. */ private function getExamplePathFromExampleDirectory(string $file) : string { return \getcwd() . \DIRECTORY_SEPARATOR . 'examples' . \DIRECTORY_SEPARATOR . $file; } /** * Returns a path to the example file in the given directory.. */ private function constructExamplePath(string $directory, string $file) : string { return \rtrim($directory, '\\/') . \DIRECTORY_SEPARATOR . $file; } /** * Get example filepath based on sourcecode. */ private function getExamplePathFromSource(string $file) : string { return \sprintf('%s%s%s', \trim($this->getSourceDirectory(), '\\/'), \DIRECTORY_SEPARATOR, \trim($file, '"')); } } create('This is a {@see Description}', $context); * * The description factory will interpret the given body and create a body template and list of tags from them, and pass * that onto the constructor if this class. * * > The $context variable is a class of type {@see \phpDocumentor\Reflection\Types\Context} and contains the namespace * > and the namespace aliases that apply to this DocBlock. These are used by the Factory to resolve and expand partial * > type names and FQSENs. * * If you do not want to use the DescriptionFactory you can pass a body template and tag listing like this: * * $description = new Description( * 'This is a %1$s', * [ new See(new Fqsen('\phpDocumentor\Reflection\DocBlock\Description')) ] * ); * * It is generally recommended to use the Factory as that will also apply escaping rules, while the Description object * is mainly responsible for rendering. * * @see DescriptionFactory to create a new Description. * @see Description\Formatter for the formatting of the body and tags. */ class Description { /** @var string */ private $bodyTemplate; /** @var Tag[] */ private $tags; /** * Initializes a Description with its body (template) and a listing of the tags used in the body template. * * @param Tag[] $tags */ public function __construct(string $bodyTemplate, array $tags = []) { $this->bodyTemplate = $bodyTemplate; $this->tags = $tags; } /** * Returns the body template. */ public function getBodyTemplate() : string { return $this->bodyTemplate; } /** * Returns the tags for this DocBlock. * * @return Tag[] */ public function getTags() : array { return $this->tags; } /** * Renders this description as a string where the provided formatter will format the tags in the expected string * format. */ public function render(?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Formatter $formatter = null) : string { if ($formatter === null) { $formatter = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter(); } $tags = []; foreach ($this->tags as $tag) { $tags[] = '{' . $formatter->format($tag) . '}'; } return \vsprintf($this->bodyTemplate, $tags); } /** * Returns a plain string representation of this description. */ public function __toString() : string { return $this->render(); } } tagFactory = $tagFactory; } /** * Returns the parsed text of this description. */ public function create(string $contents, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Description { $tokens = $this->lex($contents); $count = \count($tokens); $tagCount = 0; $tags = []; for ($i = 1; $i < $count; $i += 2) { $tags[] = $this->tagFactory->create($tokens[$i], $context); $tokens[$i] = '%' . ++$tagCount . '$s'; } //In order to allow "literal" inline tags, the otherwise invalid //sequence "{@}" is changed to "@", and "{}" is changed to "}". //"%" is escaped to "%%" because of vsprintf. //See unit tests for examples. for ($i = 0; $i < $count; $i += 2) { $tokens[$i] = \str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]); } return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Description(\implode('', $tokens), $tags); } /** * Strips the contents from superfluous whitespace and splits the description into a series of tokens. * * @return string[] A series of tokens of which the description text is composed. */ private function lex(string $contents) : array { $contents = $this->removeSuperfluousStartingWhitespace($contents); // performance optimalization; if there is no inline tag, don't bother splitting it up. if (\strpos($contents, '{@') === \false) { return [$contents]; } return \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/\\{ # "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally. (?!@\\}) # We want to capture the whole tag line, but without the inline tag delimiters. (\\@ # Match everything up to the next delimiter. [^{}]* # Nested inline tag content should not be captured, or it will appear in the result separately. (?: # Match nested inline tags. (?: # Because we did not catch the tag delimiters earlier, we must be explicit with them here. # Notice that this also matches "{}", as a way to later introduce it as an escape sequence. \\{(?1)?\\} | # Make sure we match hanging "{". \\{ ) # Match content after the nested inline tag. [^{}]* )* # If there are more inline tags, match them as well. We use "*" since there may not be any # nested inline tags. ) \\}/Sux', $contents, 0, \PREG_SPLIT_DELIM_CAPTURE); } /** * Removes the superfluous from a multi-line description. * * When a description has more than one line then it can happen that the second and subsequent lines have an * additional indentation. This is commonly in use with tags like this: * * {@}since 1.1.0 This is an example * description where we have an * indentation in the second and * subsequent lines. * * If we do not normalize the indentation then we have superfluous whitespace on the second and subsequent * lines and this may cause rendering issues when, for example, using a Markdown converter. */ private function removeSuperfluousStartingWhitespace(string $contents) : string { $lines = \explode("\n", $contents); // if there is only one line then we don't have lines with superfluous whitespace and // can use the contents as-is if (\count($lines) <= 1) { return $contents; } // determine how many whitespace characters need to be stripped $startingSpaceCount = 9999999; for ($i = 1, $iMax = \count($lines); $i < $iMax; ++$i) { // lines with a no length do not count as they are not indented at all if (\trim($lines[$i]) === '') { continue; } // determine the number of prefixing spaces by checking the difference in line length before and after // an ltrim $startingSpaceCount = \min($startingSpaceCount, \strlen($lines[$i]) - \strlen(\ltrim($lines[$i]))); } // strip the number of spaces from each line if ($startingSpaceCount > 0) { for ($i = 1, $iMax = \count($lines); $i < $iMax; ++$i) { $lines[$i] = \substr($lines[$i], $startingSpaceCount); } } return \implode("\n", $lines); } } indent = $indent; $this->indentString = $indentString; $this->isFirstLineIndented = $indentFirstLine; $this->lineLength = $lineLength; $this->tagFormatter = $tagFormatter ?: new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter(); } /** * Generate a DocBlock comment. * * @param DocBlock $docblock The DocBlock to serialize. * * @return string The serialized doc block. */ public function getDocComment(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock $docblock) : string { $indent = \str_repeat($this->indentString, $this->indent); $firstIndent = $this->isFirstLineIndented ? $indent : ''; // 3 === strlen(' * ') $wrapLength = $this->lineLength ? $this->lineLength - \strlen($indent) - 3 : null; $text = $this->removeTrailingSpaces($indent, $this->addAsterisksForEachLine($indent, $this->getSummaryAndDescriptionTextBlock($docblock, $wrapLength))); $comment = $firstIndent . "/**\n"; if ($text) { $comment .= $indent . ' * ' . $text . "\n"; $comment .= $indent . " *\n"; } $comment = $this->addTagBlock($docblock, $wrapLength, $indent, $comment); return $comment . $indent . ' */'; } private function removeTrailingSpaces(string $indent, string $text) : string { return \str_replace(\sprintf("\n%s * \n", $indent), \sprintf("\n%s *\n", $indent), $text); } private function addAsterisksForEachLine(string $indent, string $text) : string { return \str_replace("\n", \sprintf("\n%s * ", $indent), $text); } private function getSummaryAndDescriptionTextBlock(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock $docblock, ?int $wrapLength) : string { $text = $docblock->getSummary() . ((string) $docblock->getDescription() ? "\n\n" . $docblock->getDescription() : ''); if ($wrapLength !== null) { $text = \wordwrap($text, $wrapLength); return $text; } return $text; } private function addTagBlock(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock $docblock, ?int $wrapLength, string $indent, string $comment) : string { foreach ($docblock->getTags() as $tag) { $tagText = $this->tagFormatter->format($tag); if ($wrapLength !== null) { $tagText = \wordwrap($tagText, $wrapLength); } $tagText = \str_replace("\n", \sprintf("\n%s * ", $indent), $tagText); $comment .= \sprintf("%s * %s\n", $indent, $tagText); } return $comment; } } $handler FQCN of handler. * * @throws InvalidArgumentException If the tag name is not a string. * @throws InvalidArgumentException If the tag name is namespaced (contains backslashes) but * does not start with a backslash. * @throws InvalidArgumentException If the handler is not a string. * @throws InvalidArgumentException If the handler is not an existing class. * @throws InvalidArgumentException If the handler does not implement the {@see Tag} interface. */ public function registerTagHandler(string $tagName, string $handler) : void; } refers = $refers; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver $resolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($body); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($resolver); $parts = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/\\s+/Su', $body, 2); return new static(self::resolveFqsen($parts[0], $resolver, $context), $descriptionFactory->create($parts[1] ?? '', $context)); } private static function resolveFqsen(string $parts, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver $fqsenResolver, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($fqsenResolver); $fqsenParts = \explode('::', $parts); $resolved = $fqsenResolver->resolve($fqsenParts[0], $context); if (!\array_key_exists(1, $fqsenParts)) { return $resolved; } return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen($resolved . '::' . $fqsenParts[1]); } /** * Returns the structural element this tag refers to. */ public function getReference() : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen { return $this->refers; } /** * Returns a string representation of this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $refers = (string) $this->refers; return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); } } refers = $refers; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver $resolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($resolver); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); $parts = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/\\s+/Su', $body, 2); return new static(self::resolveFqsen($parts[0], $resolver, $context), $descriptionFactory->create($parts[1] ?? '', $context)); } private static function resolveFqsen(string $parts, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver $fqsenResolver, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($fqsenResolver); $fqsenParts = \explode('::', $parts); $resolved = $fqsenResolver->resolve($fqsenParts[0], $context); if (!\array_key_exists(1, $fqsenParts)) { return $resolved; } return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen($resolved . '::' . $fqsenParts[1]); } /** * Returns the structural element this tag refers to. */ public function getReference() : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen { return $this->refers; } /** * Returns a string representation of this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $refers = (string) $this->refers; return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); } } * @var array> */ private $arguments; /** @var bool */ private $isStatic; /** @var Type */ private $returnType; /** * @param array> $arguments * * @phpstan-param array $arguments */ public function __construct(string $methodName, array $arguments = [], ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type $returnType = null, bool $static = \false, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Description $description = null) { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($methodName); if ($returnType === null) { $returnType = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Void_(); } $this->methodName = $methodName; $this->arguments = $this->filterArguments($arguments); $this->returnType = $returnType; $this->isStatic = $static; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : ?self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($body); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($typeResolver); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); // 1. none or more whitespace // 2. optionally the keyword "static" followed by whitespace // 3. optionally a word with underscores followed by whitespace : as // type for the return value // 4. then optionally a word with underscores followed by () and // whitespace : as method name as used by phpDocumentor // 5. then a word with underscores, followed by ( and any character // until a ) and whitespace : as method name with signature // 6. any remaining text : as description if (!\preg_match('/^ # Static keyword # Declares a static method ONLY if type is also present (?: (static) \\s+ )? # Return type (?: ( (?:[\\w\\|_\\\\]*\\$this[\\w\\|_\\\\]*) | (?: (?:[\\w\\|_\\\\]+) # array notation (?:\\[\\])* )*+ ) \\s+ )? # Method name ([\\w_]+) # Arguments (?: \\(([^\\)]*)\\) )? \\s* # Description (.*) $/sux', $body, $matches)) { return null; } [, $static, $returnType, $methodName, $argumentLines, $description] = $matches; $static = $static === 'static'; if ($returnType === '') { $returnType = 'void'; } $returnType = $typeResolver->resolve($returnType, $context); $description = $descriptionFactory->create($description, $context); /** @phpstan-var array $arguments */ $arguments = []; if ($argumentLines !== '') { $argumentsExploded = \explode(',', $argumentLines); foreach ($argumentsExploded as $argument) { $argument = \explode(' ', self::stripRestArg(\trim($argument)), 2); if (\strpos($argument[0], '$') === 0) { $argumentName = \substr($argument[0], 1); $argumentType = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Mixed_(); } else { $argumentType = $typeResolver->resolve($argument[0], $context); $argumentName = ''; if (isset($argument[1])) { $argument[1] = self::stripRestArg($argument[1]); $argumentName = \substr($argument[1], 1); } } $arguments[] = ['name' => $argumentName, 'type' => $argumentType]; } } return new static($methodName, $arguments, $returnType, $static, $description); } /** * Retrieves the method name. */ public function getMethodName() : string { return $this->methodName; } /** * @return array> * * @phpstan-return array */ public function getArguments() : array { return $this->arguments; } /** * Checks whether the method tag describes a static method or not. * * @return bool TRUE if the method declaration is for a static method, FALSE otherwise. */ public function isStatic() : bool { return $this->isStatic; } public function getReturnType() : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { return $this->returnType; } public function __toString() : string { $arguments = []; foreach ($this->arguments as $argument) { $arguments[] = $argument['type'] . ' $' . $argument['name']; } $argumentStr = '(' . \implode(', ', $arguments) . ')'; if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $static = $this->isStatic ? 'static' : ''; $returnType = (string) $this->returnType; $methodName = (string) $this->methodName; return $static . ($returnType !== '' ? ($static !== '' ? ' ' : '') . $returnType : '') . ($methodName !== '' ? ($static !== '' || $returnType !== '' ? ' ' : '') . $methodName : '') . $argumentStr . ($description !== '' ? ' ' . $description : ''); } /** * @param mixed[][]|string[] $arguments * * @return mixed[][] * * @phpstan-param array $arguments * @phpstan-return array */ private function filterArguments(array $arguments = []) : array { $result = []; foreach ($arguments as $argument) { if (\is_string($argument)) { $argument = ['name' => $argument]; } if (!isset($argument['type'])) { $argument['type'] = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Mixed_(); } $keys = \array_keys($argument); \sort($keys); if ($keys !== ['name', 'type']) { throw new \InvalidArgumentException('Arguments can only have the "name" and "type" fields, found: ' . \var_export($keys, \true)); } $result[] = $argument; } return $result; } private static function stripRestArg(string $argument) : string { if (\strpos($argument, '...') === 0) { $argument = \trim(\substr($argument, 3)); } return $argument; } } name = 'property-write'; $this->variableName = $variableName; $this->type = $type; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($body); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($typeResolver); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); [$firstPart, $body] = self::extractTypeFromBody($body); $type = null; $parts = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; // if the first item that is encountered is not a variable; it is a type if ($firstPart && $firstPart[0] !== '$') { $type = $typeResolver->resolve($firstPart, $context); } else { // first part is not a type; we should prepend it to the parts array for further processing \array_unshift($parts, $firstPart); } // if the next item starts with a $ it must be the variable name if (isset($parts[0]) && \strpos($parts[0], '$') === 0) { $variableName = \array_shift($parts); if ($type) { \array_shift($parts); } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($variableName); $variableName = \substr($variableName, 1); } $description = $descriptionFactory->create(\implode('', $parts), $context); return new static($variableName, $type, $description); } /** * Returns the variable's name. */ public function getVariableName() : ?string { return $this->variableName; } /** * Returns a string representation for this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } if ($this->variableName) { $variableName = '$' . $this->variableName; } else { $variableName = ''; } $type = (string) $this->type; return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); } } name; } public function getDescription() : ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Description { return $this->description; } public function render(?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Formatter $formatter = null) : string { if ($formatter === null) { $formatter = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter(); } return $formatter->format($this); } } version = $version; $this->description = $description; } public static function create(?string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : ?self { if (empty($body)) { return new static(); } $matches = []; if (!\preg_match('/^(' . self::REGEX_VECTOR . ')\\s*(.+)?$/sux', $body, $matches)) { return null; } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); return new static($matches[1], $descriptionFactory->create($matches[2] ?? '', $context)); } /** * Gets the version section of the tag. */ public function getVersion() : ?string { return $this->version; } /** * Returns a string representation for this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $version = (string) $this->version; return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); } } type; } /** * @return string[] */ protected static function extractTypeFromBody(string $body) : array { $type = ''; $nestingLevel = 0; for ($i = 0, $iMax = \strlen($body); $i < $iMax; $i++) { $character = $body[$i]; if ($nestingLevel === 0 && \trim($character) === '') { break; } $type .= $character; if (\in_array($character, ['<', '(', '[', '{'])) { $nestingLevel++; continue; } if (\in_array($character, ['>', ')', ']', '}'])) { $nestingLevel--; continue; } } $description = \trim(\substr($body, \strlen($type))); return [$type, $description]; } } name = 'return'; $this->type = $type; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($typeResolver); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); [$type, $description] = self::extractTypeFromBody($body); $type = $typeResolver->resolve($type, $context); $description = $descriptionFactory->create($description, $context); return new static($type, $description); } public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $type = $this->type ? '' . $this->type : 'mixed'; return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : ''); } } name = 'param'; $this->variableName = $variableName; $this->type = $type; $this->isVariadic = $isVariadic; $this->description = $description; $this->isReference = $isReference; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($body); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($typeResolver); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); [$firstPart, $body] = self::extractTypeFromBody($body); $type = null; $parts = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; $isVariadic = \false; $isReference = \false; // if the first item that is encountered is not a variable; it is a type if ($firstPart && !self::strStartsWithVariable($firstPart)) { $type = $typeResolver->resolve($firstPart, $context); } else { // first part is not a type; we should prepend it to the parts array for further processing \array_unshift($parts, $firstPart); } // if the next item starts with a $ or ...$ or &$ or &...$ it must be the variable name if (isset($parts[0]) && self::strStartsWithVariable($parts[0])) { $variableName = \array_shift($parts); if ($type) { \array_shift($parts); } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($variableName); if (\strpos($variableName, '$') === 0) { $variableName = \substr($variableName, 1); } elseif (\strpos($variableName, '&$') === 0) { $isReference = \true; $variableName = \substr($variableName, 2); } elseif (\strpos($variableName, '...$') === 0) { $isVariadic = \true; $variableName = \substr($variableName, 4); } elseif (\strpos($variableName, '&...$') === 0) { $isVariadic = \true; $isReference = \true; $variableName = \substr($variableName, 5); } } $description = $descriptionFactory->create(\implode('', $parts), $context); return new static($variableName, $type, $isVariadic, $description, $isReference); } /** * Returns the variable's name. */ public function getVariableName() : ?string { return $this->variableName; } /** * Returns whether this tag is variadic. */ public function isVariadic() : bool { return $this->isVariadic; } /** * Returns whether this tag is passed by reference. */ public function isReference() : bool { return $this->isReference; } /** * Returns a string representation for this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $variableName = ''; if ($this->variableName) { $variableName .= ($this->isReference ? '&' : '') . ($this->isVariadic ? '...' : ''); $variableName .= '$' . $this->variableName; } $type = (string) $this->type; return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); } private static function strStartsWithVariable(string $str) : bool { return \strpos($str, '$') === 0 || \strpos($str, '...$') === 0 || \strpos($str, '&$') === 0 || \strpos($str, '&...$') === 0; } } version = $version; $this->description = $description; } public static function create(?string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : ?self { if (empty($body)) { return new static(); } $matches = []; if (!\preg_match('/^(' . self::REGEX_VECTOR . ')\\s*(.+)?$/sux', $body, $matches)) { return null; } $description = null; if ($descriptionFactory !== null) { $description = $descriptionFactory->create($matches[2] ?? '', $context); } return new static($matches[1], $description); } /** * Gets the version section of the tag. */ public function getVersion() : ?string { return $this->version; } /** * Returns a string representation for this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $version = (string) $this->version; return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); } } version = $version; $this->description = $description; } /** * @return static */ public static function create(?string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { if (empty($body)) { return new static(); } $matches = []; if (!\preg_match('/^(' . self::REGEX_VECTOR . ')\\s*(.+)?$/sux', $body, $matches)) { return new static(null, $descriptionFactory !== null ? $descriptionFactory->create($body, $context) : null); } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); return new static($matches[1], $descriptionFactory->create($matches[2] ?? '', $context)); } /** * Gets the version section of the tag. */ public function getVersion() : ?string { return $this->version; } /** * Returns a string representation for this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $version = (string) $this->version; return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); } } name = 'var'; $this->variableName = $variableName; $this->type = $type; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($body); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($typeResolver); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); [$firstPart, $body] = self::extractTypeFromBody($body); $parts = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE); $type = null; $variableName = ''; // if the first item that is encountered is not a variable; it is a type if ($firstPart && $firstPart[0] !== '$') { $type = $typeResolver->resolve($firstPart, $context); } else { // first part is not a type; we should prepend it to the parts array for further processing \array_unshift($parts, $firstPart); } // if the next item starts with a $ it must be the variable name if (isset($parts[0]) && \strpos($parts[0], '$') === 0) { $variableName = \array_shift($parts); if ($type) { \array_shift($parts); } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($variableName); $variableName = \substr($variableName, 1); } $description = $descriptionFactory->create(\implode('', $parts), $context); return new static($variableName, $type, $description); } /** * Returns the variable's name. */ public function getVariableName() : ?string { return $this->variableName; } /** * Returns a string representation for this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } if ($this->variableName) { $variableName = '$' . $this->variableName; } else { $variableName = ''; } $type = (string) $this->type; return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); } } refers = $refers; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver $typeResolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); $parts = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/\\s+/Su', $body, 2); $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; // https://tools.ietf.org/html/rfc2396#section-3 if (\preg_match('/\\w:\\/\\/\\w/i', $parts[0])) { return new static(new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Reference\Url($parts[0]), $description); } return new static(new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen(self::resolveFqsen($parts[0], $typeResolver, $context)), $description); } private static function resolveFqsen(string $parts, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver $fqsenResolver, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($fqsenResolver); $fqsenParts = \explode('::', $parts); $resolved = $fqsenResolver->resolve($fqsenParts[0], $context); if (!\array_key_exists(1, $fqsenParts)) { return $resolved; } return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen($resolved . '::' . $fqsenParts[1]); } /** * Returns the ref of this tag. */ public function getReference() : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference { return $this->refers; } /** * Returns a string representation of this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $refers = (string) $this->refers; return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); } } authorName = $authorName; $this->authorEmail = $authorEmail; } /** * Gets the author's name. * * @return string The author's name. */ public function getAuthorName() : string { return $this->authorName; } /** * Returns the author's email. * * @return string The author's email. */ public function getEmail() : string { return $this->authorEmail; } /** * Returns this tag in string form. */ public function __toString() : string { if ($this->authorEmail) { $authorEmail = '<' . $this->authorEmail . '>'; } else { $authorEmail = ''; } $authorName = (string) $this->authorName; return $authorName . ($authorEmail !== '' ? ($authorName !== '' ? ' ' : '') . $authorEmail : ''); } /** * Attempts to create a new Author object based on †he tag body. */ public static function create(string $body) : ?self { $splitTagContent = \preg_match('/^([^\\<]*)(?:\\<([^\\>]*)\\>)?$/u', $body, $matches); if (!$splitTagContent) { return null; } $authorName = \trim($matches[1]); $email = isset($matches[2]) ? \trim($matches[2]) : ''; return new static($authorName, $email); } } link = $link; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); $parts = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/\\s+/Su', $body, 2); $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; return new static($parts[0], $description); } /** * Gets the link */ public function getLink() : string { return $this->link; } /** * Returns a string representation for this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $link = (string) $this->link; return $link . ($description !== '' ? ($link !== '' ? ' ' : '') . $description : ''); } } name = 'property'; $this->variableName = $variableName; $this->type = $type; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($body); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($typeResolver); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); [$firstPart, $body] = self::extractTypeFromBody($body); $type = null; $parts = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; // if the first item that is encountered is not a variable; it is a type if ($firstPart && $firstPart[0] !== '$') { $type = $typeResolver->resolve($firstPart, $context); } else { // first part is not a type; we should prepend it to the parts array for further processing \array_unshift($parts, $firstPart); } // if the next item starts with a $ it must be the variable name if (isset($parts[0]) && \strpos($parts[0], '$') === 0) { $variableName = \array_shift($parts); if ($type) { \array_shift($parts); } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($variableName); $variableName = \substr($variableName, 1); } $description = $descriptionFactory->create(\implode('', $parts), $context); return new static($variableName, $type, $description); } /** * Returns the variable's name. */ public function getVariableName() : ?string { return $this->variableName; } /** * Returns a string representation for this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } if ($this->variableName) { $variableName = '$' . $this->variableName; } else { $variableName = ''; } $type = (string) $this->type; return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); } } name = 'throws'; $this->type = $type; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($typeResolver); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); [$type, $description] = self::extractTypeFromBody($body); $type = $typeResolver->resolve($type, $context); $description = $descriptionFactory->create($description, $context); return new static($type, $description); } public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $type = (string) $this->type; return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : ''); } } startingLine = (int) $startingLine; $this->lineCount = $lineCount !== null ? (int) $lineCount : null; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($body); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); $startingLine = 1; $lineCount = null; $description = null; // Starting line / Number of lines / Description if (\preg_match('/^([1-9]\\d*)\\s*(?:((?1))\\s+)?(.*)$/sux', $body, $matches)) { $startingLine = (int) $matches[1]; if (isset($matches[2]) && $matches[2] !== '') { $lineCount = (int) $matches[2]; } $description = $matches[3]; } return new static($startingLine, $lineCount, $descriptionFactory->create($description ?? '', $context)); } /** * Gets the starting line. * * @return int The starting line, relative to the structural element's * location. */ public function getStartingLine() : int { return $this->startingLine; } /** * Returns the number of lines. * * @return int|null The number of lines, relative to the starting line. NULL * means "to the end". */ public function getLineCount() : ?int { return $this->lineCount; } public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } $startingLine = (string) $this->startingLine; $lineCount = $this->lineCount !== null ? '' . $this->lineCount : ''; return $startingLine . ($lineCount !== '' ? ($startingLine || $startingLine === '0' ? ' ' : '') . $lineCount : '') . ($description !== '' ? ($startingLine || $startingLine === '0' || $lineCount !== '' ? ' ' : '') . $description : ''); } } name = 'property-read'; $this->variableName = $variableName; $this->type = $type; $this->description = $description; } public static function create(string $body, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\TypeResolver $typeResolver = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($body); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($typeResolver); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); [$firstPart, $body] = self::extractTypeFromBody($body); $type = null; $parts = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Utils::pregSplit('/(\\s+)/Su', $body, 2, \PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; // if the first item that is encountered is not a variable; it is a type if ($firstPart && $firstPart[0] !== '$') { $type = $typeResolver->resolve($firstPart, $context); } else { // first part is not a type; we should prepend it to the parts array for further processing \array_unshift($parts, $firstPart); } // if the next item starts with a $ it must be the variable name if (isset($parts[0]) && \strpos($parts[0], '$') === 0) { $variableName = \array_shift($parts); if ($type) { \array_shift($parts); } \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($variableName); $variableName = \substr($variableName, 1); } $description = $descriptionFactory->create(\implode('', $parts), $context); return new static($variableName, $type, $description); } /** * Returns the variable's name. */ public function getVariableName() : ?string { return $this->variableName; } /** * Returns a string representation for this tag. */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } if ($this->variableName) { $variableName = '$' . $this->variableName; } else { $variableName = ''; } $type = (string) $this->type; return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); } } name = $name; $this->body = $body; } public function getException() : ?\Throwable { return $this->throwable; } public function getName() : string { return $this->name; } public static function create(string $body, string $name = '') : self { return new self($name, $body); } public function withError(\Throwable $exception) : self { $this->flattenExceptionBacktrace($exception); $tag = new self($this->name, $this->body); $tag->throwable = $exception; return $tag; } /** * Removes all complex types from backtrace * * Not all objects are serializable. So we need to remove them from the * stored exception to be sure that we do not break existing library usage. */ private function flattenExceptionBacktrace(\Throwable $exception) : void { $traceProperty = (new \ReflectionClass(\Exception::class))->getProperty('trace'); $traceProperty->setAccessible(\true); do { $trace = $exception->getTrace(); if (isset($trace[0]['args'])) { $trace = \array_map(function (array $call) : array { $call['args'] = \array_map([$this, 'flattenArguments'], $call['args']); return $call; }, $trace); } $traceProperty->setValue($exception, $trace); $exception = $exception->getPrevious(); } while ($exception !== null); $traceProperty->setAccessible(\false); } /** * @param mixed $value * * @return mixed * * @throws ReflectionException */ private function flattenArguments($value) { if ($value instanceof \Closure) { $closureReflection = new \ReflectionFunction($value); $value = \sprintf('(Closure at %s:%s)', $closureReflection->getFileName(), $closureReflection->getStartLine()); } elseif (\is_object($value)) { $value = \sprintf('object(%s)', \get_class($value)); } elseif (\is_resource($value)) { $value = \sprintf('resource(%s)', \get_resource_type($value)); } elseif (\is_array($value)) { $value = \array_map([$this, 'flattenArguments'], $value); } return $value; } public function render(?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Formatter $formatter = null) : string { if ($formatter === null) { $formatter = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter(); } return $formatter->format($this); } public function __toString() : string { return $this->body; } } filePath = $filePath; $this->startingLine = $startingLine; $this->lineCount = $lineCount; if ($content !== null) { $this->content = \trim($content); } $this->isURI = $isURI; } public function getContent() : string { if ($this->content === null || $this->content === '') { $filePath = $this->filePath; if ($this->isURI) { $filePath = $this->isUriRelative($this->filePath) ? \str_replace('%2F', '/', \rawurlencode($this->filePath)) : $this->filePath; } return \trim($filePath); } return $this->content; } public function getDescription() : ?string { return $this->content; } public static function create(string $body) : ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tag { // File component: File path in quotes or File URI / Source information if (!\preg_match('/^\\s*(?:(\\"[^\\"]+\\")|(\\S+))(?:\\s+(.*))?$/sux', $body, $matches)) { return null; } $filePath = null; $fileUri = null; if ($matches[1] !== '') { $filePath = $matches[1]; } else { $fileUri = $matches[2]; } $startingLine = 1; $lineCount = 0; $description = null; if (\array_key_exists(3, $matches)) { $description = $matches[3]; // Starting line / Number of lines / Description if (\preg_match('/^([1-9]\\d*)(?:\\s+((?1))\\s*)?(.*)$/sux', $matches[3], $contentMatches)) { $startingLine = (int) $contentMatches[1]; if (isset($contentMatches[2])) { $lineCount = (int) $contentMatches[2]; } if (\array_key_exists(3, $contentMatches)) { $description = $contentMatches[3]; } } } return new static($filePath ?? $fileUri ?? '', $fileUri !== null, $startingLine, $lineCount, $description); } /** * Returns the file path. * * @return string Path to a file to use as an example. * May also be an absolute URI. */ public function getFilePath() : string { return \trim($this->filePath, '"'); } /** * Returns a string representation for this tag. */ public function __toString() : string { $filePath = (string) $this->filePath; $isDefaultLine = $this->startingLine === 1 && $this->lineCount === 0; $startingLine = !$isDefaultLine ? (string) $this->startingLine : ''; $lineCount = !$isDefaultLine ? (string) $this->lineCount : ''; $content = (string) $this->content; return $filePath . ($startingLine !== '' ? ($filePath !== '' ? ' ' : '') . $startingLine : '') . ($lineCount !== '' ? ($filePath !== '' || $startingLine !== '' ? ' ' : '') . $lineCount : '') . ($content !== '' ? ($filePath !== '' || $startingLine !== '' || $lineCount !== '' ? ' ' : '') . $content : ''); } /** * Returns true if the provided URI is relative or contains a complete scheme (and thus is absolute). */ private function isUriRelative(string $uri) : bool { return \strpos($uri, ':') === \false; } public function getStartingLine() : int { return $this->startingLine; } public function getLineCount() : int { return $this->lineCount; } public function getName() : string { return 'example'; } public function render(?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Formatter $formatter = null) : string { if ($formatter === null) { $formatter = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter(); } return $formatter->format($this); } } getName() . ' ' . $tag); } } maxLen = \max($this->maxLen, \strlen($tag->getName())); } } /** * Formats the given tag to return a simple plain text version. */ public function format(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tag $tag) : string { return '@' . $tag->getName() . \str_repeat(' ', $this->maxLen - \strlen($tag->getName()) + 1) . $tag; } } uri = $uri; } public function __toString() : string { return $this->uri; } } fqsen = $fqsen; } /** * @return string string representation of the referenced fqsen */ public function __toString() : string { return (string) $this->fqsen; } } validateTagName($name); $this->name = $name; $this->description = $description; } /** * Creates a new tag that represents any unknown tag type. * * @return static */ public static function create(string $body, string $name = '', ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\DescriptionFactory $descriptionFactory = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : self { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($name); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::notNull($descriptionFactory); $description = $body !== '' ? $descriptionFactory->create($body, $context) : null; return new static($name, $description); } /** * Returns the tag as a serialized string */ public function __toString() : string { if ($this->description) { $description = $this->description->render(); } else { $description = ''; } return $description; } /** * Validates if the tag name matches the expected format, otherwise throws an exception. */ private function validateTagName(string $name) : void { if (!\preg_match('/^' . \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) { throw new \InvalidArgumentException('The tag name "' . $name . '" is not wellformed. Tags may only consist of letters, underscores, ' . 'hyphens and backslashes.'); } } } Important: each parameter in addition to the body variable for the `create` method must default to null, otherwise * > it violates the constraint with the interface; it is recommended to use the {@see Assert::notNull()} method to * > verify that a dependency is actually passed. * * This Factory also features a Service Locator component that is used to pass the right dependencies to the * `create` method of a tag; each dependency should be registered as a service or as a parameter. * * When you want to use a Tag of your own with custom handling you need to call the `registerTagHandler` method, pass * the name of the tag and a Fully Qualified Class Name pointing to a class that implements the Tag interface. */ final class StandardTagFactory implements \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\TagFactory { /** PCRE regular expression matching a tag name. */ public const REGEX_TAGNAME = '[\\w\\-\\_\\\\:]+'; /** * @var array> An array with a tag as a key, and an * FQCN to a class that handles it as an array value. */ private $tagHandlerMappings = [ 'author' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Author::class, 'covers' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Covers::class, 'deprecated' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Deprecated::class, // 'example' => '\phpDocumentor\Reflection\DocBlock\Tags\Example', 'link' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Link::class, 'method' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Method::class, 'param' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Param::class, 'property-read' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead::class, 'property' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Property::class, 'property-write' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite::class, 'return' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Return_::class, 'see' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\See::class, 'since' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Since::class, 'source' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Source::class, 'throw' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Throws::class, 'throws' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Throws::class, 'uses' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Uses::class, 'var' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Var_::class, 'version' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Version::class, ]; /** * @var array> An array with a anotation s a key, and an * FQCN to a class that handles it as an array value. */ private $annotationMappings = []; /** * @var ReflectionParameter[][] a lazy-loading cache containing parameters * for each tagHandler that has been used. */ private $tagHandlerParameterCache = []; /** @var FqsenResolver */ private $fqsenResolver; /** * @var mixed[] an array representing a simple Service Locator where we can store parameters and * services that can be inserted into the Factory Methods of Tag Handlers. */ private $serviceLocator = []; /** * Initialize this tag factory with the means to resolve an FQSEN and optionally a list of tag handlers. * * If no tag handlers are provided than the default list in the {@see self::$tagHandlerMappings} property * is used. * * @see self::registerTagHandler() to add a new tag handler to the existing default list. * * @param array> $tagHandlers */ public function __construct(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver $fqsenResolver, ?array $tagHandlers = null) { $this->fqsenResolver = $fqsenResolver; if ($tagHandlers !== null) { $this->tagHandlerMappings = $tagHandlers; } $this->addService($fqsenResolver, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver::class); } public function create(string $tagLine, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tag { if (!$context) { $context = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context(''); } [$tagName, $tagBody] = $this->extractTagParts($tagLine); return $this->createTag(\trim($tagBody), $tagName, $context); } /** * @param mixed $value */ public function addParameter(string $name, $value) : void { $this->serviceLocator[$name] = $value; } public function addService(object $service, ?string $alias = null) : void { $this->serviceLocator[$alias ?: \get_class($service)] = $service; } public function registerTagHandler(string $tagName, string $handler) : void { \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::stringNotEmpty($tagName); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::classExists($handler); \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::implementsInterface($handler, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tag::class); if (\strpos($tagName, '\\') && $tagName[0] !== '\\') { throw new \InvalidArgumentException('A namespaced tag must have a leading backslash as it must be fully qualified'); } $this->tagHandlerMappings[$tagName] = $handler; } /** * Extracts all components for a tag. * * @return string[] */ private function extractTagParts(string $tagLine) : array { $matches = []; if (!\preg_match('/^@(' . self::REGEX_TAGNAME . ')((?:[\\s\\(\\{])\\s*([^\\s].*)|$)/us', $tagLine, $matches)) { throw new \InvalidArgumentException('The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors'); } if (\count($matches) < 3) { $matches[] = ''; } return \array_slice($matches, 1); } /** * Creates a new tag object with the given name and body or returns null if the tag name was recognized but the * body was invalid. */ private function createTag(string $body, string $name, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tag { $handlerClassName = $this->findHandlerClassName($name, $context); $arguments = $this->getArgumentsForParametersFromWiring($this->fetchParametersForHandlerFactoryMethod($handlerClassName), $this->getServiceLocatorWithDynamicParameters($context, $name, $body)); try { $callable = [$handlerClassName, 'create']; \_HumbugBoxd02f763d3c56\Webmozart\Assert\Assert::isCallable($callable); /** @phpstan-var callable(string): ?Tag $callable */ $tag = \call_user_func_array($callable, $arguments); return $tag ?? \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\InvalidTag::create($body, $name); } catch (\InvalidArgumentException $e) { return \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\InvalidTag::create($body, $name)->withError($e); } } /** * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`). * * @return class-string */ private function findHandlerClassName(string $tagName, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : string { $handlerClassName = \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock\Tags\Generic::class; if (isset($this->tagHandlerMappings[$tagName])) { $handlerClassName = $this->tagHandlerMappings[$tagName]; } elseif ($this->isAnnotation($tagName)) { // TODO: Annotation support is planned for a later stage and as such is disabled for now $tagName = (string) $this->fqsenResolver->resolve($tagName, $context); if (isset($this->annotationMappings[$tagName])) { $handlerClassName = $this->annotationMappings[$tagName]; } } return $handlerClassName; } /** * Retrieves the arguments that need to be passed to the Factory Method with the given Parameters. * * @param ReflectionParameter[] $parameters * @param mixed[] $locator * * @return mixed[] A series of values that can be passed to the Factory Method of the tag whose parameters * is provided with this method. */ private function getArgumentsForParametersFromWiring(array $parameters, array $locator) : array { $arguments = []; foreach ($parameters as $parameter) { $type = $parameter->getType(); $typeHint = null; if ($type instanceof \ReflectionNamedType) { $typeHint = $type->getName(); if ($typeHint === 'self') { $declaringClass = $parameter->getDeclaringClass(); if ($declaringClass !== null) { $typeHint = $declaringClass->getName(); } } } if (isset($locator[$typeHint])) { $arguments[] = $locator[$typeHint]; continue; } $parameterName = $parameter->getName(); if (isset($locator[$parameterName])) { $arguments[] = $locator[$parameterName]; continue; } $arguments[] = null; } return $arguments; } /** * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given * tag handler class name. * * @param class-string $handlerClassName * * @return ReflectionParameter[] */ private function fetchParametersForHandlerFactoryMethod(string $handlerClassName) : array { if (!isset($this->tagHandlerParameterCache[$handlerClassName])) { $methodReflection = new \ReflectionMethod($handlerClassName, 'create'); $this->tagHandlerParameterCache[$handlerClassName] = $methodReflection->getParameters(); } return $this->tagHandlerParameterCache[$handlerClassName]; } /** * Returns a copy of this class' Service Locator with added dynamic parameters, * such as the tag's name, body and Context. * * @param TypeContext $context The Context (namespace and aliasses) that may be * passed and is used to resolve FQSENs. * @param string $tagName The name of the tag that may be * passed onto the factory method of the Tag class. * @param string $tagBody The body of the tag that may be * passed onto the factory method of the Tag class. * * @return mixed[] */ private function getServiceLocatorWithDynamicParameters(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context, string $tagName, string $tagBody) : array { return \array_merge($this->serviceLocator, ['name' => $tagName, 'body' => $tagBody, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context::class => $context]); } /** * Returns whether the given tag belongs to an annotation. * * @todo this method should be populated once we implement Annotation notation support. */ private function isAnnotation(string $tagContent) : bool { // 1. Contains a namespace separator // 2. Contains parenthesis // 3. Is present in a list of known annotations (make the algorithm smart by first checking is the last part // of the annotation class name matches the found tag name return \false; } } > $additionalTags */ public static function createInstance(array $additionalTags = []) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlockFactory; /** * @param string|object $docblock */ public function create($docblock, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Location $location = null) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\DocBlock; } The MIT License (MIT) Copyright (c) 2010 Mike van Riel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Fully Qualified Namespace. * @psalm-var array */ private $namespaceAliases; /** * Initializes the new context and normalizes all passed namespaces to be in Qualified Namespace Name (QNN) * format (without a preceding `\`). * * @param string $namespace The namespace where this DocBlock resides in. * @param string[] $namespaceAliases List of namespace aliases => Fully Qualified Namespace. * * @psalm-param array $namespaceAliases */ public function __construct(string $namespace, array $namespaceAliases = []) { $this->namespace = $namespace !== 'global' && $namespace !== 'default' ? \trim($namespace, '\\') : ''; foreach ($namespaceAliases as $alias => $fqnn) { if ($fqnn[0] === '\\') { $fqnn = \substr($fqnn, 1); } if ($fqnn[\strlen($fqnn) - 1] === '\\') { $fqnn = \substr($fqnn, 0, -1); } $namespaceAliases[$alias] = $fqnn; } $this->namespaceAliases = $namespaceAliases; } /** * Returns the Qualified Namespace Name (thus without `\` in front) where the associated element is in. */ public function getNamespace() : string { return $this->namespace; } /** * Returns a list of Qualified Namespace Names (thus without `\` in front) that are imported, the keys represent * the alias for the imported Namespace. * * @return string[] * * @psalm-return array */ public function getNamespaceAliases() : array { return $this->namespaceAliases; } } valueType = $valueType; } /** * Returns the value for the keys of this array. */ public function getValueType() : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { return $this->valueType; } /** * Returns a rendered output of the Type as it would be used in a DocBlock. */ public function __toString() : string { return '(' . $this->valueType . ')'; } } */ abstract class AggregatedType implements \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type, \IteratorAggregate { /** * @psalm-allow-private-mutation * @var array */ private $types = []; /** @var string */ private $token; /** * @param array $types */ public function __construct(array $types, string $token) { foreach ($types as $type) { $this->add($type); } $this->token = $token; } /** * Returns the type at the given index. */ public function get(int $index) : ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { if (!$this->has($index)) { return null; } return $this->types[$index]; } /** * Tests if this compound type has a type with the given index. */ public function has(int $index) : bool { return \array_key_exists($index, $this->types); } /** * Tests if this compound type contains the given type. */ public function contains(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type $type) : bool { foreach ($this->types as $typePart) { // if the type is duplicate; do not add it if ((string) $typePart === (string) $type) { return \true; } } return \false; } /** * Returns a rendered output of the Type as it would be used in a DocBlock. */ public function __toString() : string { return \implode($this->token, $this->types); } /** * @return ArrayIterator */ public function getIterator() : \ArrayIterator { return new \ArrayIterator($this->types); } /** * @psalm-suppress ImpureMethodCall */ private function add(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type $type) : void { if ($type instanceof self) { foreach ($type->getIterator() as $subType) { $this->add($subType); } return; } // if the type is duplicate; do not add it if ($this->contains($type)) { return; } $this->types[] = $type; } } fqsen = $fqsen; } /** * Returns the FQSEN associated with this object. */ public function getFqsen() : ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen { return $this->fqsen; } /** * Returns a rendered output of the Type as it would be used in a DocBlock. */ public function __toString() : string { if ($this->fqsen === null) { return 'class-string'; } return 'class-string<' . (string) $this->fqsen . '>'; } } keyType) { return 'iterable<' . $this->keyType . ',' . $this->valueType . '>'; } if ($this->valueType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Mixed_) { return 'iterable'; } return 'iterable<' . $this->valueType . '>'; } } realType = $realType; } /** * Provide access to the actual type directly, if needed. */ public function getActualType() : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { return $this->realType; } /** * Returns a rendered output of the Type as it would be used in a DocBlock. */ public function __toString() : string { return '?' . $this->realType->__toString(); } } $types */ public function __construct(array $types) { parent::__construct($types, '|'); } } fqsen = $fqsen; } /** * Returns the FQSEN associated with this object. */ public function getFqsen() : ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen { return $this->fqsen; } public function __toString() : string { if ($this->fqsen) { return (string) $this->fqsen; } return 'object'; } } ` * 2. `ACollectionObject` * * - ACollectionObject can be 'array' or an object that can act as an array * - aValueType and aKeyType can be any type expression * * @psalm-immutable */ final class Collection extends \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\AbstractList { /** @var Fqsen|null */ private $fqsen; /** * Initializes this representation of an array with the given Type or Fqsen. */ public function __construct(?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen $fqsen, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type $valueType, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type $keyType = null) { parent::__construct($valueType, $keyType); $this->fqsen = $fqsen; } /** * Returns the FQSEN associated with this object. */ public function getFqsen() : ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen { return $this->fqsen; } /** * Returns a rendered output of the Type as it would be used in a DocBlock. */ public function __toString() : string { $objectType = (string) ($this->fqsen ?? 'object'); if ($this->keyType === null) { return $objectType . '<' . $this->valueType . '>'; } return $objectType . '<' . $this->keyType . ',' . $this->valueType . '>'; } } $types */ public function __construct(array $types) { parent::__construct($types, '&'); } } $reflector */ return $this->createFromReflectionClass($reflector); } if ($reflector instanceof \ReflectionParameter) { return $this->createFromReflectionParameter($reflector); } if ($reflector instanceof \ReflectionMethod) { return $this->createFromReflectionMethod($reflector); } if ($reflector instanceof \ReflectionProperty) { return $this->createFromReflectionProperty($reflector); } if ($reflector instanceof \ReflectionClassConstant) { return $this->createFromReflectionClassConstant($reflector); } throw new \UnexpectedValueException('Unhandled \\Reflector instance given: ' . \get_class($reflector)); } private function createFromReflectionParameter(\ReflectionParameter $parameter) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context { $class = $parameter->getDeclaringClass(); if (!$class) { throw new \InvalidArgumentException('Unable to get class of ' . $parameter->getName()); } //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable /** @var ReflectionClass $class */ return $this->createFromReflectionClass($class); } private function createFromReflectionMethod(\ReflectionMethod $method) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context { //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable /** @var ReflectionClass $class */ $class = $method->getDeclaringClass(); return $this->createFromReflectionClass($class); } private function createFromReflectionProperty(\ReflectionProperty $property) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context { //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable /** @var ReflectionClass $class */ $class = $property->getDeclaringClass(); return $this->createFromReflectionClass($class); } private function createFromReflectionClassConstant(\ReflectionClassConstant $constant) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context { //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable /** @var ReflectionClass $class */ $class = $constant->getDeclaringClass(); return $this->createFromReflectionClass($class); } /** * @param ReflectionClass $class */ private function createFromReflectionClass(\ReflectionClass $class) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context { $fileName = $class->getFileName(); $namespace = $class->getNamespaceName(); if (\is_string($fileName) && \file_exists($fileName)) { $contents = \file_get_contents($fileName); if ($contents === \false) { throw new \RuntimeException('Unable to read file "' . $fileName . '"'); } return $this->createForNamespace($namespace, $contents); } return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context($namespace, []); } /** * Build a Context for a namespace in the provided file contents. * * @see Context for more information on Contexts. * * @param string $namespace It does not matter if a `\` precedes the namespace name, * this method first normalizes. * @param string $fileContents The file's contents to retrieve the aliases from with the given namespace. */ public function createForNamespace(string $namespace, string $fileContents) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context { $namespace = \trim($namespace, '\\'); $useStatements = []; $currentNamespace = ''; $tokens = new \ArrayIterator(\token_get_all($fileContents)); while ($tokens->valid()) { $currentToken = $tokens->current(); switch ($currentToken[0]) { case \T_NAMESPACE: $currentNamespace = $this->parseNamespace($tokens); break; case \T_CLASS: // Fast-forward the iterator through the class so that any // T_USE tokens found within are skipped - these are not // valid namespace use statements so should be ignored. $braceLevel = 0; $firstBraceFound = \false; while ($tokens->valid() && ($braceLevel > 0 || !$firstBraceFound)) { $currentToken = $tokens->current(); if ($currentToken === '{' || \in_array($currentToken[0], [\T_CURLY_OPEN, \T_DOLLAR_OPEN_CURLY_BRACES], \true)) { if (!$firstBraceFound) { $firstBraceFound = \true; } ++$braceLevel; } if ($currentToken === '}') { --$braceLevel; } $tokens->next(); } break; case \T_USE: if ($currentNamespace === $namespace) { $useStatements += $this->parseUseStatement($tokens); } break; } $tokens->next(); } return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context($namespace, $useStatements); } /** * Deduce the name from tokens when we are at the T_NAMESPACE token. * * @param ArrayIterator $tokens */ private function parseNamespace(\ArrayIterator $tokens) : string { // skip to the first string or namespace separator $this->skipToNextStringOrNamespaceSeparator($tokens); $name = ''; $acceptedTokens = [\T_STRING, \T_NS_SEPARATOR, \T_NAME_QUALIFIED]; while ($tokens->valid() && \in_array($tokens->current()[0], $acceptedTokens, \true)) { $name .= $tokens->current()[1]; $tokens->next(); } return $name; } /** * Deduce the names of all imports when we are at the T_USE token. * * @param ArrayIterator $tokens * * @return string[] * * @psalm-return array */ private function parseUseStatement(\ArrayIterator $tokens) : array { $uses = []; while ($tokens->valid()) { $this->skipToNextStringOrNamespaceSeparator($tokens); $uses += $this->extractUseStatements($tokens); $currentToken = $tokens->current(); if ($currentToken[0] === self::T_LITERAL_END_OF_USE) { return $uses; } } return $uses; } /** * Fast-forwards the iterator as longs as we don't encounter a T_STRING or T_NS_SEPARATOR token. * * @param ArrayIterator $tokens */ private function skipToNextStringOrNamespaceSeparator(\ArrayIterator $tokens) : void { while ($tokens->valid()) { $currentToken = $tokens->current(); if (\in_array($currentToken[0], [\T_STRING, \T_NS_SEPARATOR], \true)) { break; } if ($currentToken[0] === \T_NAME_QUALIFIED) { break; } if (\defined('T_NAME_FULLY_QUALIFIED') && $currentToken[0] === \T_NAME_FULLY_QUALIFIED) { break; } $tokens->next(); } } /** * Deduce the namespace name and alias of an import when we are at the T_USE token or have not reached the end of * a USE statement yet. This will return a key/value array of the alias => namespace. * * @param ArrayIterator $tokens * * @return string[] * * @psalm-suppress TypeDoesNotContainType * * @psalm-return array */ private function extractUseStatements(\ArrayIterator $tokens) : array { $extractedUseStatements = []; $groupedNs = ''; $currentNs = ''; $currentAlias = ''; $state = 'start'; while ($tokens->valid()) { $currentToken = $tokens->current(); $tokenId = \is_string($currentToken) ? $currentToken : $currentToken[0]; $tokenValue = \is_string($currentToken) ? null : $currentToken[1]; switch ($state) { case 'start': switch ($tokenId) { case \T_STRING: case \T_NS_SEPARATOR: $currentNs .= (string) $tokenValue; $currentAlias = $tokenValue; break; case \T_NAME_QUALIFIED: case \T_NAME_FULLY_QUALIFIED: $currentNs .= (string) $tokenValue; $currentAlias = \substr((string) $tokenValue, (int) \strrpos((string) $tokenValue, '\\') + 1); break; case \T_CURLY_OPEN: case '{': $state = 'grouped'; $groupedNs = $currentNs; break; case \T_AS: $state = 'start-alias'; break; case self::T_LITERAL_USE_SEPARATOR: case self::T_LITERAL_END_OF_USE: $state = 'end'; break; default: break; } break; case 'start-alias': switch ($tokenId) { case \T_STRING: $currentAlias = $tokenValue; break; case self::T_LITERAL_USE_SEPARATOR: case self::T_LITERAL_END_OF_USE: $state = 'end'; break; default: break; } break; case 'grouped': switch ($tokenId) { case \T_STRING: case \T_NS_SEPARATOR: $currentNs .= (string) $tokenValue; $currentAlias = $tokenValue; break; case \T_AS: $state = 'grouped-alias'; break; case self::T_LITERAL_USE_SEPARATOR: $state = 'grouped'; $extractedUseStatements[(string) $currentAlias] = $currentNs; $currentNs = $groupedNs; $currentAlias = ''; break; case self::T_LITERAL_END_OF_USE: $state = 'end'; break; default: break; } break; case 'grouped-alias': switch ($tokenId) { case \T_STRING: $currentAlias = $tokenValue; break; case self::T_LITERAL_USE_SEPARATOR: $state = 'grouped'; $extractedUseStatements[(string) $currentAlias] = $currentNs; $currentNs = $groupedNs; $currentAlias = ''; break; case self::T_LITERAL_END_OF_USE: $state = 'end'; break; default: break; } } if ($state === 'end') { break; } $tokens->next(); } if ($groupedNs !== $currentNs) { $extractedUseStatements[(string) $currentAlias] = $currentNs; } return $extractedUseStatements; } } valueType = $valueType; $this->defaultKeyType = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Compound([new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\String_(), new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Integer()]); $this->keyType = $keyType; } /** * Returns the type for the keys of this array. */ public function getKeyType() : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { return $this->keyType ?? $this->defaultKeyType; } /** * Returns the value for the keys of this array. */ public function getValueType() : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { return $this->valueType; } /** * Returns a rendered output of the Type as it would be used in a DocBlock. */ public function __toString() : string { if ($this->keyType) { return 'array<' . $this->keyType . ',' . $this->valueType . '>'; } if ($this->valueType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Mixed_) { return 'array'; } if ($this->valueType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Compound) { return '(' . $this->valueType . ')[]'; } return $this->valueType . '[]'; } } List of recognized keywords and unto which Value Object they map * @psalm-var array> */ private $keywords = ['string' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\String_::class, 'class-string' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\ClassString::class, 'int' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Integer::class, 'integer' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Integer::class, 'bool' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Boolean::class, 'boolean' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Boolean::class, 'real' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Float_::class, 'float' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Float_::class, 'double' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Float_::class, 'object' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Object_::class, 'mixed' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Mixed_::class, 'array' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Array_::class, 'resource' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Resource_::class, 'void' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Void_::class, 'null' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Null_::class, 'scalar' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Scalar::class, 'callback' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Callable_::class, 'callable' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Callable_::class, 'false' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\PseudoTypes\False_::class, 'true' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\PseudoTypes\True_::class, 'self' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Self_::class, '$this' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\This::class, 'static' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Static_::class, 'parent' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Parent_::class, 'iterable' => \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Iterable_::class]; /** * @var FqsenResolver * @psalm-readonly */ private $fqsenResolver; /** * Initializes this TypeResolver with the means to create and resolve Fqsen objects. */ public function __construct(?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver $fqsenResolver = null) { $this->fqsenResolver = $fqsenResolver ?: new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\FqsenResolver(); } /** * Analyzes the given type and returns the FQCN variant. * * When a type is provided this method checks whether it is not a keyword or * Fully Qualified Class Name. If so it will use the given namespace and * aliases to expand the type to a FQCN representation. * * This method only works as expected if the namespace and aliases are set; * no dynamic reflection is being performed here. * * @uses Context::getNamespaceAliases() to check whether the first part of the relative type name should not be * replaced with another namespace. * @uses Context::getNamespace() to determine with what to prefix the type name. * * @param string $type The relative or absolute type. */ public function resolve(string $type, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { $type = \trim($type); if (!$type) { throw new \InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty'); } if ($context === null) { $context = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context(''); } // split the type string into tokens `|`, `?`, `<`, `>`, `,`, `(`, `)`, `[]`, '<', '>' and type names $tokens = \preg_split('/(\\||\\?|<|>|&|, ?|\\(|\\)|\\[\\]+)/', $type, -1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE); if ($tokens === \false) { throw new \InvalidArgumentException('Unable to split the type string "' . $type . '" into tokens'); } /** @var ArrayIterator $tokenIterator */ $tokenIterator = new \ArrayIterator($tokens); return $this->parseTypes($tokenIterator, $context, self::PARSER_IN_COMPOUND); } /** * Analyse each tokens and creates types * * @param ArrayIterator $tokens the iterator on tokens * @param int $parserContext on of self::PARSER_* constants, indicating * the context where we are in the parsing */ private function parseTypes(\ArrayIterator $tokens, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context, int $parserContext) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { $types = []; $token = ''; $compoundToken = '|'; while ($tokens->valid()) { $token = $tokens->current(); if ($token === null) { throw new \RuntimeException('Unexpected nullable character'); } if ($token === '|' || $token === '&') { if (\count($types) === 0) { throw new \RuntimeException('A type is missing before a type separator'); } if (!\in_array($parserContext, [self::PARSER_IN_COMPOUND, self::PARSER_IN_ARRAY_EXPRESSION, self::PARSER_IN_COLLECTION_EXPRESSION], \true)) { throw new \RuntimeException('Unexpected type separator'); } $compoundToken = $token; $tokens->next(); } elseif ($token === '?') { if (!\in_array($parserContext, [self::PARSER_IN_COMPOUND, self::PARSER_IN_ARRAY_EXPRESSION, self::PARSER_IN_COLLECTION_EXPRESSION], \true)) { throw new \RuntimeException('Unexpected nullable character'); } $tokens->next(); $type = $this->parseTypes($tokens, $context, self::PARSER_IN_NULLABLE); $types[] = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Nullable($type); } elseif ($token === '(') { $tokens->next(); $type = $this->parseTypes($tokens, $context, self::PARSER_IN_ARRAY_EXPRESSION); $token = $tokens->current(); if ($token === null) { // Someone did not properly close their array expression .. break; } $tokens->next(); $resolvedType = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Expression($type); $types[] = $resolvedType; } elseif ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION && $token[0] === ')') { break; } elseif ($token === '<') { if (\count($types) === 0) { throw new \RuntimeException('Unexpected collection operator "<", class name is missing'); } $classType = \array_pop($types); if ($classType !== null) { if ((string) $classType === 'class-string') { $types[] = $this->resolveClassString($tokens, $context); } else { $types[] = $this->resolveCollection($tokens, $classType, $context); } } $tokens->next(); } elseif ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION && ($token === '>' || \trim($token) === ',')) { break; } elseif ($token === self::OPERATOR_ARRAY) { \end($types); $last = \key($types); $lastItem = $types[$last]; if ($lastItem instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Expression) { $lastItem = $lastItem->getValueType(); } $types[$last] = new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Array_($lastItem); $tokens->next(); } else { $type = $this->resolveSingleType($token, $context); $tokens->next(); if ($parserContext === self::PARSER_IN_NULLABLE) { return $type; } $types[] = $type; } } if ($token === '|' || $token === '&') { throw new \RuntimeException('A type is missing after a type separator'); } if (\count($types) === 0) { if ($parserContext === self::PARSER_IN_NULLABLE) { throw new \RuntimeException('A type is missing after a nullable character'); } if ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION) { throw new \RuntimeException('A type is missing in an array expression'); } if ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION) { throw new \RuntimeException('A type is missing in a collection expression'); } } elseif (\count($types) === 1) { return $types[0]; } if ($compoundToken === '|') { return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Compound(\array_values($types)); } return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Intersection(\array_values($types)); } /** * resolve the given type into a type object * * @param string $type the type string, representing a single type * * @return Type|Array_|Object_ * * @psalm-mutation-free */ private function resolveSingleType(string $type, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : object { switch (\true) { case $this->isKeyword($type): return $this->resolveKeyword($type); case $this->isFqsen($type): return $this->resolveTypedObject($type); case $this->isPartialStructuralElementName($type): return $this->resolveTypedObject($type, $context); // @codeCoverageIgnoreStart default: // I haven't got the foggiest how the logic would come here but added this as a defense. throw new \RuntimeException('Unable to resolve type "' . $type . '", there is no known method to resolve it'); } // @codeCoverageIgnoreEnd } /** * Adds a keyword to the list of Keywords and associates it with a specific Value Object. * * @psalm-param class-string $typeClassName */ public function addKeyword(string $keyword, string $typeClassName) : void { if (!\class_exists($typeClassName)) { throw new \InvalidArgumentException('The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class' . ' but we could not find the class ' . $typeClassName); } if (!\in_array(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type::class, \class_implements($typeClassName), \true)) { throw new \InvalidArgumentException('The class "' . $typeClassName . '" must implement the interface "phpDocumentor\\Reflection\\Type"'); } $this->keywords[$keyword] = $typeClassName; } /** * Detects whether the given type represents a PHPDoc keyword. * * @param string $type A relative or absolute type as defined in the phpDocumentor documentation. * * @psalm-mutation-free */ private function isKeyword(string $type) : bool { return \array_key_exists(\strtolower($type), $this->keywords); } /** * Detects whether the given type represents a relative structural element name. * * @param string $type A relative or absolute type as defined in the phpDocumentor documentation. * * @psalm-mutation-free */ private function isPartialStructuralElementName(string $type) : bool { return $type[0] !== self::OPERATOR_NAMESPACE && !$this->isKeyword($type); } /** * Tests whether the given type is a Fully Qualified Structural Element Name. * * @psalm-mutation-free */ private function isFqsen(string $type) : bool { return \strpos($type, self::OPERATOR_NAMESPACE) === 0; } /** * Resolves the given keyword (such as `string`) into a Type object representing that keyword. * * @psalm-mutation-free */ private function resolveKeyword(string $type) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { $className = $this->keywords[\strtolower($type)]; return new $className(); } /** * Resolves the given FQSEN string into an FQSEN object. * * @psalm-mutation-free */ private function resolveTypedObject(string $type, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context = null) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Object_ { return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Object_($this->fqsenResolver->resolve($type, $context)); } /** * Resolves class string * * @param ArrayIterator $tokens */ private function resolveClassString(\ArrayIterator $tokens, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { $tokens->next(); $classType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION); if (!$classType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Object_ || $classType->getFqsen() === null) { throw new \RuntimeException($classType . ' is not a class string'); } $token = $tokens->current(); if ($token !== '>') { if (empty($token)) { throw new \RuntimeException('class-string: ">" is missing'); } throw new \RuntimeException('Unexpected character "' . $token . '", ">" is missing'); } return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\ClassString($classType->getFqsen()); } /** * Resolves the collection values and keys * * @param ArrayIterator $tokens * * @return Array_|Iterable_|Collection */ private function resolveCollection(\ArrayIterator $tokens, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type $classType, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type { $isArray = (string) $classType === 'array'; $isIterable = (string) $classType === 'iterable'; // allow only "array", "iterable" or class name before "<" if (!$isArray && !$isIterable && (!$classType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Object_ || $classType->getFqsen() === null)) { throw new \RuntimeException($classType . ' is not a collection'); } $tokens->next(); $valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION); $keyType = null; $token = $tokens->current(); if ($token !== null && \trim($token) === ',') { // if we have a comma, then we just parsed the key type, not the value type $keyType = $valueType; if ($isArray) { // check the key type for an "array" collection. We allow only // strings or integers. if (!$keyType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\String_ && !$keyType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Integer && !$keyType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Compound) { throw new \RuntimeException('An array can have only integers or strings as keys'); } if ($keyType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Compound) { foreach ($keyType->getIterator() as $item) { if (!$item instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\String_ && !$item instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Integer) { throw new \RuntimeException('An array can have only integers or strings as keys'); } } } } $tokens->next(); // now let's parse the value type $valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION); } $token = $tokens->current(); if ($token !== '>') { if (empty($token)) { throw new \RuntimeException('Collection: ">" is missing'); } throw new \RuntimeException('Unexpected character "' . $token . '", ">" is missing'); } if ($isArray) { return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Array_($valueType, $keyType); } if ($isIterable) { return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Iterable_($valueType, $keyType); } if ($classType instanceof \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Object_) { return $this->makeCollectionFromObject($classType, $valueType, $keyType); } throw new \RuntimeException('Invalid $classType provided'); } /** * @psalm-pure */ private function makeCollectionFromObject(\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Object_ $object, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type $valueType, ?\_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Type $keyType = null) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Collection { return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Collection($object->getFqsen(), $valueType, $keyType); } } isFqsen($fqsen)) { return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen($fqsen); } return $this->resolvePartialStructuralElementName($fqsen, $context); } /** * Tests whether the given type is a Fully Qualified Structural Element Name. */ private function isFqsen(string $type) : bool { return \strpos($type, self::OPERATOR_NAMESPACE) === 0; } /** * Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation * (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context. * * @throws InvalidArgumentException When type is not a valid FQSEN. */ private function resolvePartialStructuralElementName(string $type, \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Types\Context $context) : \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen { $typeParts = \explode(self::OPERATOR_NAMESPACE, $type, 2); $namespaceAliases = $context->getNamespaceAliases(); // if the first segment is not an alias; prepend namespace name and return if (!isset($namespaceAliases[$typeParts[0]])) { $namespace = $context->getNamespace(); if ($namespace !== '') { $namespace .= self::OPERATOR_NAMESPACE; } return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type); } $typeParts[0] = $namespaceAliases[$typeParts[0]]; return new \_HumbugBoxd02f763d3c56\phpDocumentor\Reflection\Fqsen(self::OPERATOR_NAMESPACE . \implode(self::OPERATOR_NAMESPACE, $typeParts)); } } getHomeDir(); $path = \DIRECTORY_SEPARATOR === $homeDir ? $homeDir . '.config' : $homeDir . \DIRECTORY_SEPARATOR . '.config'; return $path; } /** * @return string */ public function getHomeDataDir() { $path = \getenv('XDG_DATA_HOME') ?: $this->getHomeDir() . \DIRECTORY_SEPARATOR . '.local' . \DIRECTORY_SEPARATOR . 'share'; return $path; } /** * @return array */ public function getConfigDirs() { $configDirs = \getenv('XDG_CONFIG_DIRS') ? \explode(':', \getenv('XDG_CONFIG_DIRS')) : array('/etc/xdg'); $paths = \array_merge(array($this->getHomeConfigDir()), $configDirs); return $paths; } /** * @return array */ public function getDataDirs() { $dataDirs = \getenv('XDG_DATA_DIRS') ? \explode(':', \getenv('XDG_DATA_DIRS')) : array('/usr/local/share', '/usr/share'); $paths = \array_merge(array($this->getHomeDataDir()), $dataDirs); return $paths; } /** * @return string */ public function getHomeCacheDir() { $path = \getenv('XDG_CACHE_HOME') ?: $this->getHomeDir() . \DIRECTORY_SEPARATOR . '.cache'; return $path; } public function getRuntimeDir($strict = \true) { if ($runtimeDir = \getenv('XDG_RUNTIME_DIR')) { return $runtimeDir; } if ($strict) { throw new \RuntimeException('XDG_RUNTIME_DIR was not set'); } $fallback = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . self::RUNTIME_DIR_FALLBACK . \getenv('USER'); $create = \false; if (!\is_dir($fallback)) { \mkdir($fallback, 0700, \true); } $st = \lstat($fallback); # The fallback must be a directory if (!$st['mode'] & self::S_IFDIR) { \rmdir($fallback); $create = \true; } elseif ($st['uid'] != $this->getUid() || $st['mode'] & (self::S_IRWXG | self::S_IRWXO)) { \rmdir($fallback); $create = \true; } if ($create) { \mkdir($fallback, 0700, \true); } return $fallback; } private function getUid() { if (\function_exists('posix_getuid')) { return \posix_getuid(); } return \getmyuid(); } } Copyright (c) 2014 Daniel Nögel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 * @link http://cweiske.de/ */ /** * Automatically map JSON structures into objects. * * @category Netresearch * @package JsonMapper * @author Christian Weiske * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 * @link http://cweiske.de/ */ class JsonMapper { /** * PSR-3 compatible logger object * * @link http://www.php-fig.org/psr/psr-3/ * @var object * @see setLogger() */ protected $logger; /** * Throw an exception when JSON data contain a property * that is not defined in the PHP class * * @var boolean */ public $bExceptionOnUndefinedProperty = \false; /** * Throw an exception if the JSON data miss a property * that is marked with @required in the PHP class * * @var boolean */ public $bExceptionOnMissingData = \false; /** * If the types of map() parameters shall be checked. * * You have to disable it if you're using the json_decode "assoc" parameter. * * json_decode($str, false) * * @var boolean */ public $bEnforceMapType = \true; /** * Throw an exception when an object is expected but the JSON contains * a non-object type. * * @var boolean */ public $bStrictObjectTypeChecking = \false; /** * Throw an exception, if null value is found * but the type of attribute does not allow nulls. * * @var bool */ public $bStrictNullTypes = \true; /** * Allow mapping of private and proteted properties. * * @var boolean */ public $bIgnoreVisibility = \false; /** * Remove attributes that were not passed in JSON, * to avoid confusion between them and NULL values. * * @var boolean */ public $bRemoveUndefinedAttributes = \false; /** * Override class names that JsonMapper uses to create objects. * Useful when your setter methods accept abstract classes or interfaces. * * @var array */ public $classMap = array(); /** * Callback used when an undefined property is found. * * Works only when $bExceptionOnUndefinedProperty is disabled. * * Parameters to this function are: * 1. Object that is being filled * 2. Name of the unknown JSON property * 3. JSON value of the property * * @var callable */ public $undefinedPropertyHandler = null; /** * Runtime cache for inspected classes. This is particularly effective if * mapArray() is called with a large number of objects * * @var array property inspection result cache */ protected $arInspectedClasses = array(); /** * Method to call on each object after deserialization is done. * * Is only called if it exists on the object. * * @var string|null */ public $postMappingMethod = null; /** * Map data all data in $json into the given $object instance. * * @param object $json JSON object structure from json_decode() * @param object $object Object to map $json data into * * @return mixed Mapped object is returned. * @see mapArray() */ public function map($json, $object) { if ($this->bEnforceMapType && !\is_object($json)) { throw new \InvalidArgumentException('JsonMapper::map() requires first argument to be an object' . ', ' . \gettype($json) . ' given.'); } if (!\is_object($object)) { throw new \InvalidArgumentException('JsonMapper::map() requires second argument to be an object' . ', ' . \gettype($object) . ' given.'); } $strClassName = \get_class($object); $rc = new \ReflectionClass($object); $strNs = $rc->getNamespaceName(); $providedProperties = array(); foreach ($json as $key => $jvalue) { $key = $this->getSafeName($key); $providedProperties[$key] = \true; // Store the property inspection results so we don't have to do it // again for subsequent objects of the same type if (!isset($this->arInspectedClasses[$strClassName][$key])) { $this->arInspectedClasses[$strClassName][$key] = $this->inspectProperty($rc, $key); } list($hasProperty, $accessor, $type) = $this->arInspectedClasses[$strClassName][$key]; if (!$hasProperty) { if ($this->bExceptionOnUndefinedProperty) { throw new \_HumbugBoxd02f763d3c56\JsonMapper_Exception('JSON property "' . $key . '" does not exist' . ' in object of type ' . $strClassName); } else { if ($this->undefinedPropertyHandler !== null) { \call_user_func($this->undefinedPropertyHandler, $object, $key, $jvalue); } else { $this->log('info', 'Property {property} does not exist in {class}', array('property' => $key, 'class' => $strClassName)); } } continue; } if ($accessor === null) { if ($this->bExceptionOnUndefinedProperty) { throw new \_HumbugBoxd02f763d3c56\JsonMapper_Exception('JSON property "' . $key . '" has no public setter method' . ' in object of type ' . $strClassName); } $this->log('info', 'Property {property} has no public setter method in {class}', array('property' => $key, 'class' => $strClassName)); continue; } if ($this->isNullable($type) || !$this->bStrictNullTypes) { if ($jvalue === null) { $this->setProperty($object, $accessor, null); continue; } $type = $this->removeNullable($type); } else { if ($jvalue === null) { throw new \_HumbugBoxd02f763d3c56\JsonMapper_Exception('JSON property "' . $key . '" in class "' . $strClassName . '" must not be NULL'); } } $type = $this->getFullNamespace($type, $strNs); $type = $this->getMappedType($type, $jvalue); if ($type === null || $type === 'mixed') { //no given type - simply set the json data $this->setProperty($object, $accessor, $jvalue); continue; } else { if ($this->isObjectOfSameType($type, $jvalue)) { $this->setProperty($object, $accessor, $jvalue); continue; } else { if ($this->isSimpleType($type)) { if ($type === 'string' && \is_object($jvalue)) { throw new \_HumbugBoxd02f763d3c56\JsonMapper_Exception('JSON property "' . $key . '" in class "' . $strClassName . '" is an object and' . ' cannot be converted to a string'); } \settype($jvalue, $type); $this->setProperty($object, $accessor, $jvalue); continue; } } } //FIXME: check if type exists, give detailed error message if not if ($type === '') { throw new \_HumbugBoxd02f763d3c56\JsonMapper_Exception('Empty type at property "' . $strClassName . '::$' . $key . '"'); } $array = null; $subtype = null; if ($this->isArrayOfType($type)) { //array $array = array(); $subtype = \substr($type, 0, -2); } else { if (\substr($type, -1) == ']') { list($proptype, $subtype) = \explode('[', \substr($type, 0, -1)); if ($proptype == 'array') { $array = array(); } else { $array = $this->createInstance($proptype, \false, $jvalue); } } else { if (\is_a($type, 'ArrayObject', \true)) { $array = $this->createInstance($type, \false, $jvalue); } } } if ($array !== null) { if (!\is_array($jvalue) && $this->isFlatType(\gettype($jvalue))) { throw new \_HumbugBoxd02f763d3c56\JsonMapper_Exception('JSON property "' . $key . '" must be an array, ' . \gettype($jvalue) . ' given'); } $cleanSubtype = $this->removeNullable($subtype); $subtype = $this->getFullNamespace($cleanSubtype, $strNs); $child = $this->mapArray($jvalue, $array, $subtype, $key); } else { if ($this->isFlatType(\gettype($jvalue))) { //use constructor parameter if we have a class // but only a flat type (i.e. string, int) if ($this->bStrictObjectTypeChecking) { throw new \_HumbugBoxd02f763d3c56\JsonMapper_Exception('JSON property "' . $key . '" must be an object, ' . \gettype($jvalue) . ' given'); } $child = $this->createInstance($type, \true, $jvalue); } else { $child = $this->createInstance($type, \false, $jvalue); $this->map($jvalue, $child); } } $this->setProperty($object, $accessor, $child); } if ($this->bExceptionOnMissingData) { $this->checkMissingData($providedProperties, $rc); } if ($this->bRemoveUndefinedAttributes) { $this->removeUndefinedAttributes($object, $providedProperties); } if ($this->postMappingMethod !== null && $rc->hasMethod($this->postMappingMethod)) { $refDeserializePostMethod = $rc->getMethod($this->postMappingMethod); $refDeserializePostMethod->setAccessible(\true); $refDeserializePostMethod->invoke($object); } return $object; } /** * Convert a type name to a fully namespaced type name. * * @param string $type Type name (simple type or class name) * @param string $strNs Base namespace that gets prepended to the type name * * @return string Fully-qualified type name with namespace */ protected function getFullNamespace($type, $strNs) { if ($type === null || $type === '' || $type[0] == '\\' || $strNs == '') { return $type; } list($first) = \explode('[', $type, 2); if ($this->isSimpleType($first) || $first === 'mixed') { return $type; } //create a full qualified namespace return '\\' . $strNs . '\\' . $type; } /** * Check required properties exist in json * * @param array $providedProperties array with json properties * @param object $rc Reflection class to check * * @throws JsonMapper_Exception * * @return void */ protected function checkMissingData($providedProperties, \ReflectionClass $rc) { foreach ($rc->getProperties() as $property) { $rprop = $rc->getProperty($property->name); $docblock = $rprop->getDocComment(); $annotations = $this->parseAnnotations($docblock); if (isset($annotations['required']) && !isset($providedProperties[$property->name])) { throw new \_HumbugBoxd02f763d3c56\JsonMapper_Exception('Required property "' . $property->name . '" of class ' . $rc->getName() . ' is missing in JSON data'); } } } /** * Remove attributes from object that were not passed in JSON data. * * This is to avoid confusion between those that were actually passed * as NULL, and those that weren't provided at all. * * @param object $object Object to remove properties from * @param array $providedProperties Array with JSON properties * * @return void */ protected function removeUndefinedAttributes($object, $providedProperties) { foreach (\get_object_vars($object) as $propertyName => $dummy) { if (!isset($providedProperties[$propertyName])) { unset($object->{$propertyName}); } } } /** * Map an array * * @param array $json JSON array structure from json_decode() * @param mixed $array Array or ArrayObject that gets filled with * data from $json * @param string $class Class name for children objects. * All children will get mapped onto this type. * Supports class names and simple types * like "string" and nullability "string|null". * Pass "null" to not convert any values * @param string $parent_key Defines the key this array belongs to * in order to aid debugging. * * @return mixed Mapped $array is returned */ public function mapArray($json, $array, $class = null, $parent_key = '') { $originalClass = $class; foreach ($json as $key => $jvalue) { $class = $this->getMappedType($originalClass, $jvalue); if ($class === null) { $array[$key] = $jvalue; } else { if ($this->isArrayOfType($class)) { $array[$key] = $this->mapArray($jvalue, array(), \substr($class, 0, -2)); } else { if ($this->isFlatType(\gettype($jvalue))) { //use constructor parameter if we have a class // but only a flat type (i.e. string, int) if ($jvalue === null) { $array[$key] = null; } else { if ($this->isSimpleType($class)) { \settype($jvalue, $class); $array[$key] = $jvalue; } else { $array[$key] = $this->createInstance($class, \true, $jvalue); } } } else { if ($this->isFlatType($class)) { throw new \_HumbugBoxd02f763d3c56\JsonMapper_Exception('JSON property "' . ($parent_key ? $parent_key : '?') . '"' . ' is an array of type "' . $class . '"' . ' but contained a value of type' . ' "' . \gettype($jvalue) . '"'); } else { if (\is_a($class, 'ArrayObject', \true)) { $array[$key] = $this->mapArray($jvalue, $this->createInstance($class)); } else { $array[$key] = $this->map($jvalue, $this->createInstance($class, \false, $jvalue)); } } } } } } return $array; } /** * Try to find out if a property exists in a given class. * Checks property first, falls back to setter method. * * @param object $rc Reflection class to check * @param string $name Property name * * @return array First value: if the property exists * Second value: the accessor to use ( * ReflectionMethod or ReflectionProperty, or null) * Third value: type of the property */ protected function inspectProperty(\ReflectionClass $rc, $name) { //try setter method first $setter = 'set' . $this->getCamelCaseName($name); if ($rc->hasMethod($setter)) { $rmeth = $rc->getMethod($setter); if ($rmeth->isPublic() || $this->bIgnoreVisibility) { $rparams = $rmeth->getParameters(); if (\count($rparams) > 0) { $pclass = $rparams[0]->getClass(); $nullability = ''; if ($rparams[0]->allowsNull()) { $nullability = '|null'; } if ($pclass !== null) { return array(\true, $rmeth, '\\' . $pclass->getName() . $nullability); } } $docblock = $rmeth->getDocComment(); $annotations = $this->parseAnnotations($docblock); if (!isset($annotations['param'][0])) { // If there is no annotations (higher priority) inspect // if there's a scalar type being defined if (\PHP_MAJOR_VERSION >= 7) { $ptype = $rparams[0]->getType(); if ($ptype !== null) { // ReflectionType::__toString() is deprecated if (\PHP_VERSION >= 7.1 && $ptype instanceof \ReflectionNamedType) { $ptype = $ptype->getName(); } return array(\true, $rmeth, $ptype . $nullability); } } return array(\true, $rmeth, null); } list($type) = \explode(' ', \trim($annotations['param'][0])); return array(\true, $rmeth, $type); } } //now try to set the property directly //we have to look it up in the class hierarchy $class = $rc; $rprop = null; do { if ($class->hasProperty($name)) { $rprop = $class->getProperty($name); } } while ($rprop === null && ($class = $class->getParentClass())); if ($rprop === null) { //case-insensitive property matching foreach ($rc->getProperties() as $p) { if (\strcasecmp($p->name, $name) === 0) { $rprop = $p; break; } } } if ($rprop !== null) { if ($rprop->isPublic() || $this->bIgnoreVisibility) { $docblock = $rprop->getDocComment(); $annotations = $this->parseAnnotations($docblock); if (!isset($annotations['var'][0])) { return array(\true, $rprop, null); } //support "@var type description" list($type) = \explode(' ', $annotations['var'][0]); return array(\true, $rprop, $type); } else { //no setter, private property return array(\true, null, null); } } //no setter, no property return array(\false, null, null); } /** * Removes - and _ and makes the next letter uppercase * * @param string $name Property name * * @return string CamelCasedVariableName */ protected function getCamelCaseName($name) { return \str_replace(' ', '', \ucwords(\str_replace(array('_', '-'), ' ', $name))); } /** * Since hyphens cannot be used in variables we have to uppercase them. * * Technically you may use them, but they are awkward to access. * * @param string $name Property name * * @return string Name without hyphen */ protected function getSafeName($name) { if (\strpos($name, '-') !== \false) { $name = $this->getCamelCaseName($name); } return $name; } /** * Set a property on a given object to a given value. * * Checks if the setter or the property are public are made before * calling this method. * * @param object $object Object to set property on * @param object $accessor ReflectionMethod or ReflectionProperty * @param mixed $value Value of property * * @return void */ protected function setProperty($object, $accessor, $value) { if (!$accessor->isPublic() && $this->bIgnoreVisibility) { $accessor->setAccessible(\true); } if ($accessor instanceof \ReflectionProperty) { $accessor->setValue($object, $value); } else { //setter method $accessor->invoke($object, $value); } } /** * Create a new object of the given type. * * This method exists to be overwritten in child classes, * so you can do dependency injection or so. * * @param string $class Class name to instantiate * @param boolean $useParameter Pass $parameter to the constructor or not * @param mixed $jvalue Constructor parameter (the json value) * * @return object Freshly created object */ protected function createInstance($class, $useParameter = \false, $jvalue = null) { if ($useParameter) { return new $class($jvalue); } else { $reflectClass = new \ReflectionClass($class); $constructor = $reflectClass->getConstructor(); if (null === $constructor || $constructor->getNumberOfRequiredParameters() > 0) { return $reflectClass->newInstanceWithoutConstructor(); } return $reflectClass->newInstance(); } } /** * Get the mapped class/type name for this class. * Returns the incoming classname if not mapped. * * @param string $type Type name to map * @param mixed $jvalue Constructor parameter (the json value) * * @return string The mapped type/class name */ protected function getMappedType($type, $jvalue = null) { if (isset($this->classMap[$type])) { $target = $this->classMap[$type]; } else { if (\is_string($type) && $type !== '' && $type[0] == '\\' && isset($this->classMap[\substr($type, 1)])) { $target = $this->classMap[\substr($type, 1)]; } else { $target = null; } } if ($target) { if (\is_callable($target)) { $type = $target($type, $jvalue); } else { $type = $target; } } return $type; } /** * Checks if the given type is a "simple type" * * @param string $type type name from gettype() * * @return boolean True if it is a simple PHP type * * @see isFlatType() */ protected function isSimpleType($type) { return $type == 'string' || $type == 'boolean' || $type == 'bool' || $type == 'integer' || $type == 'int' || $type == 'double' || $type == 'float' || $type == 'array' || $type == 'object'; } /** * Checks if the object is of this type or has this type as one of its parents * * @param string $type class name of type being required * @param mixed $value Some PHP value to be tested * * @return boolean True if $object has type of $type */ protected function isObjectOfSameType($type, $value) { if (\false === \is_object($value)) { return \false; } return \is_a($value, $type); } /** * Checks if the given type is a type that is not nested * (simple type except array and object) * * @param string $type type name from gettype() * * @return boolean True if it is a non-nested PHP type * * @see isSimpleType() */ protected function isFlatType($type) { return $type == 'NULL' || $type == 'string' || $type == 'boolean' || $type == 'bool' || $type == 'integer' || $type == 'int' || $type == 'double' || $type == 'float'; } /** * Returns true if type is an array of elements * (bracket notation) * * @param string $strType type to be matched * * @return bool */ protected function isArrayOfType($strType) { return \substr($strType, -2) === '[]'; } /** * Checks if the given type is nullable * * @param string $type type name from the phpdoc param * * @return boolean True if it is nullable */ protected function isNullable($type) { return \stripos('|' . $type . '|', '|null|') !== \false; } /** * Remove the 'null' section of a type * * @param string $type type name from the phpdoc param * * @return string The new type value */ protected function removeNullable($type) { if ($type === null) { return null; } return \substr(\str_ireplace('|null|', '|', '|' . $type . '|'), 1, -1); } /** * Copied from PHPUnit 3.7.29, Util/Test.php * * @param string $docblock Full method docblock * * @return array */ protected static function parseAnnotations($docblock) { $annotations = array(); // Strip away the docblock header and footer // to ease parsing of one line annotations $docblock = \substr($docblock, 3, -2); $re = '/@(?P[A-Za-z_-]+)(?:[ \\t]+(?P.*?))?[ \\t]*\\r?$/m'; if (\preg_match_all($re, $docblock, $matches)) { $numMatches = \count($matches[0]); for ($i = 0; $i < $numMatches; ++$i) { $annotations[$matches['name'][$i]][] = $matches['value'][$i]; } } return $annotations; } /** * Log a message to the $logger object * * @param string $level Logging level * @param string $message Text to log * @param array $context Additional information * * @return null */ protected function log($level, $message, array $context = array()) { if ($this->logger) { $this->logger->log($level, $message, $context); } } /** * Sets a logger instance on the object * * @param LoggerInterface $logger PSR-3 compatible logger object * * @return null */ public function setLogger($logger) { $this->logger = $logger; } } if (!\class_exists(\JsonMapper::class, false)) { /** * Part of JsonMapper * * PHP version 5 * * @category Netresearch * @package JsonMapper * @author Christian Weiske * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 * @link http://cweiske.de/ */ /** * Automatically map JSON structures into objects. * * @category Netresearch * @package JsonMapper * @author Christian Weiske * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 * @link http://cweiske.de/ */ \class_alias('_HumbugBoxd02f763d3c56\\JsonMapper', 'JsonMapper', \false); } * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 * @link http://cweiske.de/ */ /** * Simple exception * * @category Netresearch * @package JsonMapper * @author Christian Weiske * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 * @link http://cweiske.de/ */ class JsonMapper_Exception extends \Exception { } if (!\class_exists(\JsonMapper_Exception::class, false)) { /** * Part of JsonMapper * * PHP version 5 * * @category Netresearch * @package JsonMapper * @author Christian Weiske * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 * @link http://cweiske.de/ */ /** * Simple exception * * @category Netresearch * @package JsonMapper * @author Christian Weiske * @license OSL-3.0 http://opensource.org/licenses/osl-3.0 * @link http://cweiske.de/ */ \class_alias('_HumbugBoxd02f763d3c56\\JsonMapper_Exception', 'JsonMapper_Exception', \false); } Open Software License v. 3.0 (OSL-3.0) This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: Licensed under the Open Software License version 3.0 1) Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: a) to reproduce the Original Work in copies, either alone or as part of a collective work; b) to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; c) to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; d) to perform the Original Work publicly; and e) to display the Original Work publicly. 2) Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. 3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. 4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor’s trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. 5) External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). 6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. 7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. 8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. 9) Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including “fair use” or “fair dealing”). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). 10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. 11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. 12) Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. 13) Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. 14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. 16) Modification of This License. This License is Copyright (c) 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process.. */ namespace _HumbugBoxd02f763d3c56\LSS; use DomDocument; use Exception; /** * Array2XML: A class to convert array in PHP to XML * It also takes into account attributes names unlike SimpleXML in PHP * It returns the XML in form of DOMDocument class for further manipulation. * It throws exception if the tag name or attribute name has illegal chars. * * Author : Lalit Patel * Website: http://www.lalit.org/lab/convert-php-array-to-xml-with-attributes * License: Apache License 2.0 * http://www.apache.org/licenses/LICENSE-2.0 * Version: 0.1 (10 July 2011) * Version: 0.2 (16 August 2011) * - replaced htmlentities() with htmlspecialchars() (Thanks to Liel Dulev) * - fixed a edge case where root node has a false/null/0 value. (Thanks to Liel Dulev) * Version: 0.3 (22 August 2011) * - fixed tag sanitize regex which didn't allow tagnames with single character. * Version: 0.4 (18 September 2011) * - Added support for CDATA section using @cdata instead of @value. * Version: 0.5 (07 December 2011) * - Changed logic to check numeric array indices not starting from 0. * Version: 0.6 (04 March 2012) * - Code now doesn't @cdata to be placed in an empty array * Version: 0.7 (24 March 2012) * - Reverted to version 0.5 * Version: 0.8 (02 May 2012) * - Removed htmlspecialchars() before adding to text node or attributes. * Version: 0.11 (28 October 2015) * - Fixed typos; Added support for plain insertion of XML trough @xml. * * Usage: * $xml = Array2XML::createXML('root_node_name', $php_array); * echo $xml->saveXML(); */ class Array2XML { /** * @var DOMDocument */ private static $xml = null; private static $encoding = 'UTF-8'; /** * Initialize the root XML node [optional] * @param $version * @param $encoding * @param $format_output */ public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = \true) { self::$xml = new \DomDocument($version, $encoding); self::$xml->formatOutput = $format_output; self::$encoding = $encoding; } /** * Convert an Array to XML * @param string $node_name - name of the root node to be converted * @param array $arr - aray to be converterd * @return DomDocument */ public static function &createXML($node_name, $arr = array()) { $xml = self::getXMLRoot(); $xml->appendChild(self::convert($node_name, $arr)); self::$xml = null; // clear the xml node in the class for 2nd time use. return $xml; } /** * Convert an Array to XML. * * @param string $node_name * Name of the root node to be converted. * @param array $arr * Array to be converted. * * @throws \Exception * * @return \DOMNode */ private static function &convert($node_name, $arr = array()) { //print_arr($node_name); $xml = self::getXMLRoot(); $node = $xml->createElement($node_name); if (\is_array($arr)) { // get the attributes first.; if (isset($arr['@attributes'])) { foreach ($arr['@attributes'] as $key => $value) { if (!self::isValidTagName($key)) { throw new \Exception('[Array2XML] Illegal character in attribute name. attribute: ' . $key . ' in node: ' . $node_name); } $node->setAttribute($key, self::bool2str($value)); } unset($arr['@attributes']); //remove the key from the array once done. } // check if it has a value stored in @value, if yes store the value and return // else check if its directly stored as string if (isset($arr['@value'])) { $node->appendChild($xml->createTextNode(self::bool2str($arr['@value']))); unset($arr['@value']); //remove the key from the array once done. //return from recursion, as a note with value cannot have child nodes. return $node; } else { if (isset($arr['@cdata'])) { $node->appendChild($xml->createCDATASection(self::bool2str($arr['@cdata']))); unset($arr['@cdata']); //remove the key from the array once done. //return from recursion, as a note with cdata cannot have child nodes. return $node; } else { if (isset($arr['@comment']) && \is_string($arr['@comment'])) { $node->appendChild($xml->createComment(self::bool2str($arr['@comment']))); unset($arr['@comment']); } else { if (isset($arr['@xml'])) { $fragment = $xml->createDocumentFragment(); $fragment->appendXML($arr['@xml']); $node->appendChild($fragment); unset($arr['@xml']); return $node; } } } } } //create subnodes using recursion if (\is_array($arr)) { // recurse to get the node for that key foreach ($arr as $key => $value) { if (!self::isValidTagName($key)) { throw new \Exception('[Array2XML] Illegal character in tag name. tag: ' . $key . ' in node: ' . $node_name); } if (\is_array($value) && \is_numeric(\key($value))) { // MORE THAN ONE NODE OF ITS KIND; // if the new array is numeric index, means it is array of nodes of the same kind // it should follow the parent key name foreach ($value as $k => $v) { $node->appendChild(self::convert($key, $v)); } } else { // ONLY ONE NODE OF ITS KIND $node->appendChild(self::convert($key, $value)); } unset($arr[$key]); //remove the key from the array once done. } } // after we are done with all the keys in the array (if it is one) // we check if it has any text value, if yes, append it. if (!\is_array($arr)) { $node->appendChild($xml->createTextNode(self::bool2str($arr))); } return $node; } /* * Get the root XML node, if there isn't one, create it. */ private static function getXMLRoot() { if (empty(self::$xml)) { self::init(); } return self::$xml; } /* * Get string representation of boolean value */ private static function bool2str($v) { //convert boolean to text value. $v = $v === \true ? 'true' : $v; $v = $v === \false ? 'false' : $v; return $v; } /* * Check if the tag name or attribute name contains illegal characters * Ref: http://www.w3.org/TR/xml/#sec-common-syn */ private static function isValidTagName($tag) { $pattern = '/^[a-z_]+[a-z0-9\\:\\-\\.\\_]*[^:]*$/i'; return \preg_match($pattern, $tag, $matches) && $matches[0] == $tag; } } . */ namespace _HumbugBoxd02f763d3c56\LSS; use DOMDocument; use Exception; /** * XML2Array: A class to convert XML to array in PHP * It returns the array which can be converted back to XML using the Array2XML script * It takes an XML string or a DOMDocument object as an input. * * See Array2XML: http://www.lalit.org/lab/convert-php-array-to-xml-with-attributes * * Author : Lalit Patel * Website: http://www.lalit.org/lab/convert-xml-to-array-in-php-xml2array * License: Apache License 2.0 * http://www.apache.org/licenses/LICENSE-2.0 * Version: 0.1 (07 Dec 2011) * Version: 0.2 (04 Mar 2012) * Fixed typo 'DomDocument' to 'DOMDocument' * * Usage: * $array = XML2Array::createArray($xml); */ class XML2Array { protected static $xml = null; protected static $encoding = 'UTF-8'; protected static $prefix_attributes = '@'; /** * Initialize the root XML node [optional] * @param $version * @param $encoding * @param $format_output */ public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = \true) { self::$xml = new \DOMDocument($version, $encoding); self::$xml->formatOutput = $format_output; self::$encoding = $encoding; } /** * Convert an XML to Array * @param string $node_name - name of the root node to be converted * @param int - Bitwise OR of the libxml option constants see @link http://php.net/manual/libxml.constants.php * @param array $arr - aray to be converterd * @param mixed $callback - callback function * @return array */ public static function &createArray($input_xml, $options = 0, $callback = null) { $xml = self::getXMLRoot(); if (\is_string($input_xml)) { $parsed = $xml->loadXML($input_xml, $options); if (!$parsed) { throw new \Exception('[XML2Array] Error parsing the XML string.'); } } else { if (\get_class($input_xml) != 'DOMDocument') { throw new \Exception('[XML2Array] The input XML object should be of type: DOMDocument.'); } $xml = self::$xml = $input_xml; } $array[$xml->documentElement->tagName] = self::convert($xml->documentElement, $callback); self::$xml = null; // clear the xml node in the class for 2nd time use. return $array; } /** * Convert an Array to XML * @param mixed $node - XML as a string or as an object of DOMDocument * @param mixed $callback - callback function * @return mixed */ protected static function &convert($node, $callback = null) { $output = array(); switch ($node->nodeType) { case \XML_CDATA_SECTION_NODE: $output[static::$prefix_attributes . 'cdata'] = \trim($node->textContent); break; case \XML_TEXT_NODE: $output = \trim($node->textContent); break; case \XML_ELEMENT_NODE: // for each child node, call the covert function recursively for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) { if ($callback !== null) { $callback($m = $node->childNodes->length, $i); } $child = $node->childNodes->item($i); $v = self::convert($child); if (isset($child->tagName)) { $t = $child->tagName; // avoid fatal error if the content looks like 'You are being redirected.' if (isset($output) && !\is_array($output)) { continue; } // assume more nodes of same kind are coming if (!isset($output[$t])) { $output[$t] = array(); } $output[$t][] = $v; } else { //check if it is not an empty text node if ($v !== '') { $output = $v; } } } if (\is_array($output)) { // if only one node of its kind, assign it directly instead if array($value); foreach ($output as $t => $v) { if (\is_array($v) && \count($v) == 1) { $output[$t] = $v[0]; } } if (empty($output)) { //for empty nodes $output = ''; } } // loop through the attributes and collect them if ($node->attributes->length) { $a = array(); foreach ($node->attributes as $attrName => $attrNode) { $a[$attrName] = (string) $attrNode->value; } // if its an leaf node, store the value in @value instead of directly storing it. if (!\is_array($output)) { $output = array(static::$prefix_attributes . 'value' => $output); } $output[static::$prefix_attributes . 'attributes'] = $a; } break; } return $output; } /* * Get the root XML node, if there isn't one, create it. */ protected static function getXMLRoot() { if (empty(self::$xml)) { self::init(); } return self::$xml; } } GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. $baseDir . '/src/Psalm/Aliases.php', 'Psalm\\CodeLocation' => $baseDir . '/src/Psalm/CodeLocation.php', 'Psalm\\CodeLocation\\DocblockTypeLocation' => $baseDir . '/src/Psalm/CodeLocation/DocblockTypeLocation.php', 'Psalm\\CodeLocation\\ParseErrorLocation' => $baseDir . '/src/Psalm/CodeLocation/ParseErrorLocation.php', 'Psalm\\CodeLocation\\Raw' => $baseDir . '/src/Psalm/CodeLocation/Raw.php', 'Psalm\\Codebase' => $baseDir . '/src/Psalm/Codebase.php', 'Psalm\\Config' => $baseDir . '/src/Psalm/Config.php', 'Psalm\\Config\\Creator' => $baseDir . '/src/Psalm/Config/Creator.php', 'Psalm\\Config\\ErrorLevelFileFilter' => $baseDir . '/src/Psalm/Config/ErrorLevelFileFilter.php', 'Psalm\\Config\\FileFilter' => $baseDir . '/src/Psalm/Config/FileFilter.php', 'Psalm\\Config\\IssueHandler' => $baseDir . '/src/Psalm/Config/IssueHandler.php', 'Psalm\\Config\\ProjectFileFilter' => $baseDir . '/src/Psalm/Config/ProjectFileFilter.php', 'Psalm\\Config\\TaintAnalysisFileFilter' => $baseDir . '/src/Psalm/Config/TaintAnalysisFileFilter.php', 'Psalm\\Context' => $baseDir . '/src/Psalm/Context.php', 'Psalm\\DocComment' => $baseDir . '/src/Psalm/DocComment.php', 'Psalm\\ErrorBaseline' => $baseDir . '/src/Psalm/ErrorBaseline.php', 'Psalm\\Exception\\CircularReferenceException' => $baseDir . '/src/Psalm/Exception/CircularReferenceException.php', 'Psalm\\Exception\\CodeException' => $baseDir . '/src/Psalm/Exception/CodeException.php', 'Psalm\\Exception\\ComplicatedExpressionException' => $baseDir . '/src/Psalm/Exception/ComplicatedExpressionException.php', 'Psalm\\Exception\\ConfigCreationException' => $baseDir . '/src/Psalm/Exception/ConfigCreationException.php', 'Psalm\\Exception\\ConfigException' => $baseDir . '/src/Psalm/Exception/ConfigException.php', 'Psalm\\Exception\\DocblockParseException' => $baseDir . '/src/Psalm/Exception/DocblockParseException.php', 'Psalm\\Exception\\FileIncludeException' => $baseDir . '/src/Psalm/Exception/FileIncludeException.php', 'Psalm\\Exception\\IncorrectDocblockException' => $baseDir . '/src/Psalm/Exception/IncorrectDocblockException.php', 'Psalm\\Exception\\InvalidClasslikeOverrideException' => $baseDir . '/src/Psalm/Exception/InvalidClasslikeOverrideException.php', 'Psalm\\Exception\\InvalidMethodOverrideException' => $baseDir . '/src/Psalm/Exception/InvalidMethodOverrideException.php', 'Psalm\\Exception\\RefactorException' => $baseDir . '/src/Psalm/Exception/RefactorException.php', 'Psalm\\Exception\\ScopeAnalysisException' => $baseDir . '/src/Psalm/Exception/ScopeAnalysisException.php', 'Psalm\\Exception\\TypeParseTreeException' => $baseDir . '/src/Psalm/Exception/TypeParseTreeException.php', 'Psalm\\Exception\\UnanalyzedFileException' => $baseDir . '/src/Psalm/Exception/UnanalyzedFileException.php', 'Psalm\\Exception\\UnpopulatedClasslikeException' => $baseDir . '/src/Psalm/Exception/UnpopulatedClasslikeException.php', 'Psalm\\Exception\\UnpreparedAnalysisException' => $baseDir . '/src/Psalm/Exception/UnpreparedAnalysisException.php', 'Psalm\\Exception\\UnsupportedIssueToFixException' => $baseDir . '/src/Psalm/Exception/UnsupportedIssueToFixException.php', 'Psalm\\FileBasedPluginAdapter' => $baseDir . '/src/Psalm/FileBasedPluginAdapter.php', 'Psalm\\FileManipulation' => $baseDir . '/src/Psalm/FileManipulation.php', 'Psalm\\FileSource' => $baseDir . '/src/Psalm/FileSource.php', 'Psalm\\Internal\\Analyzer\\AlgebraAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/AlgebraAnalyzer.php', 'Psalm\\Internal\\Analyzer\\CanAlias' => $baseDir . '/src/Psalm/Internal/Analyzer/CanAlias.php', 'Psalm\\Internal\\Analyzer\\ClassAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/ClassAnalyzer.php', 'Psalm\\Internal\\Analyzer\\ClassLikeAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\ClosureAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php', 'Psalm\\Internal\\Analyzer\\CommentAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/CommentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\DataFlowNodeData' => $baseDir . '/src/Psalm/Internal/Analyzer/DataFlowNodeData.php', 'Psalm\\Internal\\Analyzer\\FileAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/FileAnalyzer.php', 'Psalm\\Internal\\Analyzer\\FunctionAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/FunctionAnalyzer.php', 'Psalm\\Internal\\Analyzer\\FunctionLikeAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\FunctionLike\\ReturnTypeAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\FunctionLike\\ReturnTypeCollector' => $baseDir . '/src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeCollector.php', 'Psalm\\Internal\\Analyzer\\InterfaceAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/InterfaceAnalyzer.php', 'Psalm\\Internal\\Analyzer\\IssueData' => $baseDir . '/src/Psalm/Internal/Analyzer/IssueData.php', 'Psalm\\Internal\\Analyzer\\MethodAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/MethodAnalyzer.php', 'Psalm\\Internal\\Analyzer\\MethodComparator' => $baseDir . '/src/Psalm/Internal/Analyzer/MethodComparator.php', 'Psalm\\Internal\\Analyzer\\NamespaceAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php', 'Psalm\\Internal\\Analyzer\\ProjectAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php', 'Psalm\\Internal\\Analyzer\\ScopeAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/ScopeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\SourceAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/SourceAnalyzer.php', 'Psalm\\Internal\\Analyzer\\StatementsAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\DoAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\ForAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\ForeachAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\IfAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Block/IfAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\LoopAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\SwitchAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\SwitchCaseAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\TryAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\WhileAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\BreakAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/BreakAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\ContinueAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/ContinueAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\EchoAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/EchoAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\ExpressionAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\ArrayAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/ArrayAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\AssertionFinder' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\AssignmentAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Assignment\\ArrayAssignmentAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Assignment\\InstancePropertyAssignmentAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/InstancePropertyAssignmentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Assignment\\StaticPropertyAssignmentAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/StaticPropertyAssignmentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOpAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\AndAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\CoalesceAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/CoalesceAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\ConcatAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ConcatAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\NonComparisonOpAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/NonComparisonOpAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\NonDivArithmeticOpAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/NonDivArithmeticOpAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\OrAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BitwiseNotAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/BitwiseNotAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BooleanNotAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\CallAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ArgumentAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ArgumentMapPopulator' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentMapPopulator.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ArgumentsAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ArrayFunctionArgumentsAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ClassTemplateParamCollector' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ClassTemplateParamCollector.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\FunctionCallAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\MethodCallAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\AtomicCallContext' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicCallContext.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\AtomicMethodCallAnalysisResult' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalysisResult.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\AtomicMethodCallAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MethodCallProhibitionAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodCallProhibitionAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MethodCallPurityAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodCallPurityAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MethodCallReturnTypeFetcher' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodCallReturnTypeFetcher.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MethodVisibilityAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodVisibilityAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MissingMethodCallHandler' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MissingMethodCallHandler.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\NewAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\StaticCallAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\CastAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\CloneAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/CloneAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\EmptyAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\EncapsulatedStringAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/EncapsulatedStringAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\EvalAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/EvalAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\ExitAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/ExitAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\ExpressionIdentifier' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\ArrayFetchAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\AtomicPropertyFetchAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\ClassConstFetchAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ClassConstFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\ConstFetchAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\InstancePropertyFetchAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/InstancePropertyFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\StaticPropertyFetchAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\VariableFetchAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\IncDecExpressionAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/IncDecExpressionAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\IncludeAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\InstanceofAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\IssetAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/IssetAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\MagicConstAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/MagicConstAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\MatchAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\NullsafeAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/NullsafeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\PrintAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/PrintAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\SimpleTypeInferer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\TernaryAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\UnaryPlusMinusAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/UnaryPlusMinusAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\YieldAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/YieldAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\YieldFromAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/Expression/YieldFromAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\GlobalAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/GlobalAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\ReturnAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\StaticAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/StaticAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\ThrowAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/ThrowAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\UnsetAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/UnsetAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\UnusedAssignmentRemover' => $baseDir . '/src/Psalm/Internal/Analyzer/Statements/UnusedAssignmentRemover.php', 'Psalm\\Internal\\Analyzer\\TraitAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/TraitAnalyzer.php', 'Psalm\\Internal\\Analyzer\\TypeAnalyzer' => $baseDir . '/src/Psalm/Internal/Analyzer/TypeAnalyzer.php', 'Psalm\\Internal\\Clause' => $baseDir . '/src/Psalm/Internal/Clause.php', 'Psalm\\Internal\\Codebase\\Analyzer' => $baseDir . '/src/Psalm/Internal/Codebase/Analyzer.php', 'Psalm\\Internal\\Codebase\\ClassLikes' => $baseDir . '/src/Psalm/Internal/Codebase/ClassLikes.php', 'Psalm\\Internal\\Codebase\\ConstantTypeResolver' => $baseDir . '/src/Psalm/Internal/Codebase/ConstantTypeResolver.php', 'Psalm\\Internal\\Codebase\\DataFlowGraph' => $baseDir . '/src/Psalm/Internal/Codebase/DataFlowGraph.php', 'Psalm\\Internal\\Codebase\\Functions' => $baseDir . '/src/Psalm/Internal/Codebase/Functions.php', 'Psalm\\Internal\\Codebase\\InternalCallMapHandler' => $baseDir . '/src/Psalm/Internal/Codebase/InternalCallMapHandler.php', 'Psalm\\Internal\\Codebase\\Methods' => $baseDir . '/src/Psalm/Internal/Codebase/Methods.php', 'Psalm\\Internal\\Codebase\\Populator' => $baseDir . '/src/Psalm/Internal/Codebase/Populator.php', 'Psalm\\Internal\\Codebase\\Properties' => $baseDir . '/src/Psalm/Internal/Codebase/Properties.php', 'Psalm\\Internal\\Codebase\\PropertyMap' => $baseDir . '/src/Psalm/Internal/Codebase/PropertyMap.php', 'Psalm\\Internal\\Codebase\\ReferenceMapGenerator' => $baseDir . '/src/Psalm/Internal/Codebase/ReferenceMapGenerator.php', 'Psalm\\Internal\\Codebase\\Reflection' => $baseDir . '/src/Psalm/Internal/Codebase/Reflection.php', 'Psalm\\Internal\\Codebase\\Scanner' => $baseDir . '/src/Psalm/Internal/Codebase/Scanner.php', 'Psalm\\Internal\\Codebase\\TaintFlowGraph' => $baseDir . '/src/Psalm/Internal/Codebase/TaintFlowGraph.php', 'Psalm\\Internal\\Codebase\\VariableUseGraph' => $baseDir . '/src/Psalm/Internal/Codebase/VariableUseGraph.php', 'Psalm\\Internal\\Composer' => $baseDir . '/src/Psalm/Internal/Composer.php', 'Psalm\\Internal\\DataFlow\\DataFlowNode' => $baseDir . '/src/Psalm/Internal/DataFlow/DataFlowNode.php', 'Psalm\\Internal\\DataFlow\\Path' => $baseDir . '/src/Psalm/Internal/DataFlow/Path.php', 'Psalm\\Internal\\DataFlow\\TaintSink' => $baseDir . '/src/Psalm/Internal/DataFlow/TaintSink.php', 'Psalm\\Internal\\DataFlow\\TaintSource' => $baseDir . '/src/Psalm/Internal/DataFlow/TaintSource.php', 'Psalm\\Internal\\Diff\\AstDiffer' => $baseDir . '/src/Psalm/Internal/Diff/AstDiffer.php', 'Psalm\\Internal\\Diff\\ClassStatementsDiffer' => $baseDir . '/src/Psalm/Internal/Diff/ClassStatementsDiffer.php', 'Psalm\\Internal\\Diff\\DiffElem' => $baseDir . '/src/Psalm/Internal/Diff/DiffElem.php', 'Psalm\\Internal\\Diff\\FileDiffer' => $baseDir . '/src/Psalm/Internal/Diff/FileDiffer.php', 'Psalm\\Internal\\Diff\\FileStatementsDiffer' => $baseDir . '/src/Psalm/Internal/Diff/FileStatementsDiffer.php', 'Psalm\\Internal\\Diff\\NamespaceStatementsDiffer' => $baseDir . '/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php', 'Psalm\\Internal\\ExecutionEnvironment\\BuildInfoCollector' => $baseDir . '/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php', 'Psalm\\Internal\\ExecutionEnvironment\\GitInfoCollector' => $baseDir . '/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php', 'Psalm\\Internal\\ExecutionEnvironment\\SystemCommandExecutor' => $baseDir . '/src/Psalm/Internal/ExecutionEnvironment/SystemCommandExecutor.php', 'Psalm\\Internal\\FileManipulation\\ClassDocblockManipulator' => $baseDir . '/src/Psalm/Internal/FileManipulation/ClassDocblockManipulator.php', 'Psalm\\Internal\\FileManipulation\\CodeMigration' => $baseDir . '/src/Psalm/Internal/FileManipulation/CodeMigration.php', 'Psalm\\Internal\\FileManipulation\\FileManipulationBuffer' => $baseDir . '/src/Psalm/Internal/FileManipulation/FileManipulationBuffer.php', 'Psalm\\Internal\\FileManipulation\\FunctionDocblockManipulator' => $baseDir . '/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php', 'Psalm\\Internal\\FileManipulation\\PropertyDocblockManipulator' => $baseDir . '/src/Psalm/Internal/FileManipulation/PropertyDocblockManipulator.php', 'Psalm\\Internal\\Fork\\ForkMessage' => $baseDir . '/src/Psalm/Internal/Fork/ForkMessage.php', 'Psalm\\Internal\\Fork\\ForkProcessDoneMessage' => $baseDir . '/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php', 'Psalm\\Internal\\Fork\\ForkProcessErrorMessage' => $baseDir . '/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php', 'Psalm\\Internal\\Fork\\ForkTaskDoneMessage' => $baseDir . '/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php', 'Psalm\\Internal\\Fork\\Pool' => $baseDir . '/src/Psalm/Internal/Fork/Pool.php', 'Psalm\\Internal\\Fork\\PsalmRestarter' => $baseDir . '/src/Psalm/Internal/Fork/PsalmRestarter.php', 'Psalm\\Internal\\IncludeCollector' => $baseDir . '/src/Psalm/Internal/IncludeCollector.php', 'Psalm\\Internal\\Json\\Json' => $baseDir . '/src/Psalm/Internal/Json/Json.php', 'Psalm\\Internal\\LanguageServer\\ClientHandler' => $baseDir . '/src/Psalm/Internal/LanguageServer/ClientHandler.php', 'Psalm\\Internal\\LanguageServer\\Client\\TextDocument' => $baseDir . '/src/Psalm/Internal/LanguageServer/Client/TextDocument.php', 'Psalm\\Internal\\LanguageServer\\EmitterInterface' => $baseDir . '/src/Psalm/Internal/LanguageServer/EmitterInterface.php', 'Psalm\\Internal\\LanguageServer\\EmitterTrait' => $baseDir . '/src/Psalm/Internal/LanguageServer/EmitterTrait.php', 'Psalm\\Internal\\LanguageServer\\IdGenerator' => $baseDir . '/src/Psalm/Internal/LanguageServer/IdGenerator.php', 'Psalm\\Internal\\LanguageServer\\LanguageClient' => $baseDir . '/src/Psalm/Internal/LanguageServer/LanguageClient.php', 'Psalm\\Internal\\LanguageServer\\LanguageServer' => $baseDir . '/src/Psalm/Internal/LanguageServer/LanguageServer.php', 'Psalm\\Internal\\LanguageServer\\Message' => $baseDir . '/src/Psalm/Internal/LanguageServer/Message.php', 'Psalm\\Internal\\LanguageServer\\ProtocolReader' => $baseDir . '/src/Psalm/Internal/LanguageServer/ProtocolReader.php', 'Psalm\\Internal\\LanguageServer\\ProtocolStreamReader' => $baseDir . '/src/Psalm/Internal/LanguageServer/ProtocolStreamReader.php', 'Psalm\\Internal\\LanguageServer\\ProtocolStreamWriter' => $baseDir . '/src/Psalm/Internal/LanguageServer/ProtocolStreamWriter.php', 'Psalm\\Internal\\LanguageServer\\ProtocolWriter' => $baseDir . '/src/Psalm/Internal/LanguageServer/ProtocolWriter.php', 'Psalm\\Internal\\LanguageServer\\Server\\TextDocument' => $baseDir . '/src/Psalm/Internal/LanguageServer/Server/TextDocument.php', 'Psalm\\Internal\\MethodIdentifier' => $baseDir . '/src/Psalm/Internal/MethodIdentifier.php', 'Psalm\\Internal\\PhpTraverser\\CustomTraverser' => $baseDir . '/src/Psalm/Internal/PhpTraverser/CustomTraverser.php', 'Psalm\\Internal\\PhpVisitor\\AssignmentMapVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php', 'Psalm\\Internal\\PhpVisitor\\CheckTrivialExprVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/CheckTrivialExprVisitor.php', 'Psalm\\Internal\\PhpVisitor\\CloningVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/CloningVisitor.php', 'Psalm\\Internal\\PhpVisitor\\ConditionCloningVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php', 'Psalm\\Internal\\PhpVisitor\\NodeCleanerVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php', 'Psalm\\Internal\\PhpVisitor\\NodeCounterVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/NodeCounterVisitor.php', 'Psalm\\Internal\\PhpVisitor\\OffsetShifterVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php', 'Psalm\\Internal\\PhpVisitor\\ParamReplacementVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php', 'Psalm\\Internal\\PhpVisitor\\PartialParserVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php', 'Psalm\\Internal\\PhpVisitor\\ReflectorVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php', 'Psalm\\Internal\\PhpVisitor\\ShortClosureVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/ShortClosureVisitor.php', 'Psalm\\Internal\\PhpVisitor\\SimpleNameResolver' => $baseDir . '/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php', 'Psalm\\Internal\\PhpVisitor\\TraitFinder' => $baseDir . '/src/Psalm/Internal/PhpVisitor/TraitFinder.php', 'Psalm\\Internal\\PhpVisitor\\TypeMappingVisitor' => $baseDir . '/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php', 'Psalm\\Internal\\PluginManager\\Command\\DisableCommand' => $baseDir . '/src/Psalm/Internal/PluginManager/Command/DisableCommand.php', 'Psalm\\Internal\\PluginManager\\Command\\EnableCommand' => $baseDir . '/src/Psalm/Internal/PluginManager/Command/EnableCommand.php', 'Psalm\\Internal\\PluginManager\\Command\\ShowCommand' => $baseDir . '/src/Psalm/Internal/PluginManager/Command/ShowCommand.php', 'Psalm\\Internal\\PluginManager\\ComposerLock' => $baseDir . '/src/Psalm/Internal/PluginManager/ComposerLock.php', 'Psalm\\Internal\\PluginManager\\ConfigFile' => $baseDir . '/src/Psalm/Internal/PluginManager/ConfigFile.php', 'Psalm\\Internal\\PluginManager\\PluginList' => $baseDir . '/src/Psalm/Internal/PluginManager/PluginList.php', 'Psalm\\Internal\\PluginManager\\PluginListFactory' => $baseDir . '/src/Psalm/Internal/PluginManager/PluginListFactory.php', 'Psalm\\Internal\\Provider\\ClassLikeStorageCacheProvider' => $baseDir . '/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php', 'Psalm\\Internal\\Provider\\ClassLikeStorageProvider' => $baseDir . '/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php', 'Psalm\\Internal\\Provider\\FileProvider' => $baseDir . '/src/Psalm/Internal/Provider/FileProvider.php', 'Psalm\\Internal\\Provider\\FileReferenceCacheProvider' => $baseDir . '/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php', 'Psalm\\Internal\\Provider\\FileReferenceProvider' => $baseDir . '/src/Psalm/Internal/Provider/FileReferenceProvider.php', 'Psalm\\Internal\\Provider\\FileStorageCacheProvider' => $baseDir . '/src/Psalm/Internal/Provider/FileStorageCacheProvider.php', 'Psalm\\Internal\\Provider\\FileStorageProvider' => $baseDir . '/src/Psalm/Internal/Provider/FileStorageProvider.php', 'Psalm\\Internal\\Provider\\FunctionExistenceProvider' => $baseDir . '/src/Psalm/Internal/Provider/FunctionExistenceProvider.php', 'Psalm\\Internal\\Provider\\FunctionParamsProvider' => $baseDir . '/src/Psalm/Internal/Provider/FunctionParamsProvider.php', 'Psalm\\Internal\\Provider\\FunctionReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\MethodExistenceProvider' => $baseDir . '/src/Psalm/Internal/Provider/MethodExistenceProvider.php', 'Psalm\\Internal\\Provider\\MethodParamsProvider' => $baseDir . '/src/Psalm/Internal/Provider/MethodParamsProvider.php', 'Psalm\\Internal\\Provider\\MethodReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/MethodReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\MethodVisibilityProvider' => $baseDir . '/src/Psalm/Internal/Provider/MethodVisibilityProvider.php', 'Psalm\\Internal\\Provider\\NodeDataProvider' => $baseDir . '/src/Psalm/Internal/Provider/NodeDataProvider.php', 'Psalm\\Internal\\Provider\\ParserCacheProvider' => $baseDir . '/src/Psalm/Internal/Provider/ParserCacheProvider.php', 'Psalm\\Internal\\Provider\\ProjectCacheProvider' => $baseDir . '/src/Psalm/Internal/Provider/ProjectCacheProvider.php', 'Psalm\\Internal\\Provider\\PropertyExistenceProvider' => $baseDir . '/src/Psalm/Internal/Provider/PropertyExistenceProvider.php', 'Psalm\\Internal\\Provider\\PropertyTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/PropertyTypeProvider.php', 'Psalm\\Internal\\Provider\\PropertyVisibilityProvider' => $baseDir . '/src/Psalm/Internal/Provider/PropertyVisibilityProvider.php', 'Psalm\\Internal\\Provider\\Providers' => $baseDir . '/src/Psalm/Internal/Provider/Providers.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayChunkReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayChunkReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayColumnReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayColumnReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayFillReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayFilterReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFilterReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayMapReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayMergeReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMergeReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayPadReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPadReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayPointerAdjustmentReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPointerAdjustmentReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayPopReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPopReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayRandReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayRandReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayReduceReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReduceReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayReverseReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReverseReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArraySliceReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArraySliceReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayUniqueReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayUniqueReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayValuesReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayValuesReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ClosureFromCallableReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ClosureFromCallableReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\DomNodeAppendChild' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/DomNodeAppendChild.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ExplodeReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ExplodeReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\FilterVarReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/FilterVarReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\FirstArgStringReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/FirstArgStringReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\GetClassMethodsReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/GetClassMethodsReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\GetObjectVarsReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/GetObjectVarsReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\HexdecReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/HexdecReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\IteratorToArrayReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/IteratorToArrayReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\MktimeReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/MktimeReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ParseUrlReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ParseUrlReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\PdoStatementReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\PdoStatementSetFetchMode' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementSetFetchMode.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\SimpleXmlElementAsXml' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/SimpleXmlElementAsXml.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\StrReplaceReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\VersionCompareReturnTypeProvider' => $baseDir . '/src/Psalm/Internal/Provider/ReturnTypeProvider/VersionCompareReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\StatementsProvider' => $baseDir . '/src/Psalm/Internal/Provider/StatementsProvider.php', 'Psalm\\Internal\\ReferenceConstraint' => $baseDir . '/src/Psalm/Internal/ReferenceConstraint.php', 'Psalm\\Internal\\RuntimeCaches' => $baseDir . '/src/Psalm/Internal/RuntimeCaches.php', 'Psalm\\Internal\\Scanner\\ClassLikeDocblockComment' => $baseDir . '/src/Psalm/Internal/Scanner/ClassLikeDocblockComment.php', 'Psalm\\Internal\\Scanner\\DocblockParser' => $baseDir . '/src/Psalm/Internal/Scanner/DocblockParser.php', 'Psalm\\Internal\\Scanner\\FileScanner' => $baseDir . '/src/Psalm/Internal/Scanner/FileScanner.php', 'Psalm\\Internal\\Scanner\\FunctionDocblockComment' => $baseDir . '/src/Psalm/Internal/Scanner/FunctionDocblockComment.php', 'Psalm\\Internal\\Scanner\\ParsedDocblock' => $baseDir . '/src/Psalm/Internal/Scanner/ParsedDocblock.php', 'Psalm\\Internal\\Scanner\\PhpStormMetaScanner' => $baseDir . '/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstantComponent' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstantComponent.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\ArrayOffsetFetch' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\ArrayValue' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\ClassConstant' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\Constant' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\KeyValuePair' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\ScalarValue' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedAdditionOp' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedAdditionOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedBinaryOp' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedBitwiseOr' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBitwiseOr.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedConcatOp' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedConcatOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedDivisionOp' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedDivisionOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedMultiplicationOp' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedMultiplicationOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedSubtractionOp' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedSubtractionOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedTernary' => $baseDir . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php', 'Psalm\\Internal\\Scanner\\VarDocblockComment' => $baseDir . '/src/Psalm/Internal/Scanner/VarDocblockComment.php', 'Psalm\\Internal\\Scope\\CaseScope' => $baseDir . '/src/Psalm/Internal/Scope/CaseScope.php', 'Psalm\\Internal\\Scope\\FinallyScope' => $baseDir . '/src/Psalm/Internal/Scope/FinallyScope.php', 'Psalm\\Internal\\Scope\\IfConditionalScope' => $baseDir . '/src/Psalm/Internal/Scope/IfConditionalScope.php', 'Psalm\\Internal\\Scope\\IfScope' => $baseDir . '/src/Psalm/Internal/Scope/IfScope.php', 'Psalm\\Internal\\Scope\\LoopScope' => $baseDir . '/src/Psalm/Internal/Scope/LoopScope.php', 'Psalm\\Internal\\Scope\\SwitchScope' => $baseDir . '/src/Psalm/Internal/Scope/SwitchScope.php', 'Psalm\\Internal\\Stubs\\Generator\\ClassLikeStubGenerator' => $baseDir . '/src/Psalm/Internal/Stubs/Generator/ClassLikeStubGenerator.php', 'Psalm\\Internal\\Stubs\\Generator\\StubsGenerator' => $baseDir . '/src/Psalm/Internal/Stubs/Generator/StubsGenerator.php', 'Psalm\\Internal\\TypeVisitor\\ContainsClassLikeVisitor' => $baseDir . '/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php', 'Psalm\\Internal\\TypeVisitor\\FromDocblockSetter' => $baseDir . '/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php', 'Psalm\\Internal\\TypeVisitor\\TemplateTypeCollector' => $baseDir . '/src/Psalm/Internal/TypeVisitor/TemplateTypeCollector.php', 'Psalm\\Internal\\TypeVisitor\\TypeChecker' => $baseDir . '/src/Psalm/Internal/TypeVisitor/TypeChecker.php', 'Psalm\\Internal\\TypeVisitor\\TypeScanner' => $baseDir . '/src/Psalm/Internal/TypeVisitor/TypeScanner.php', 'Psalm\\Internal\\Type\\ArrayType' => $baseDir . '/src/Psalm/Internal/Type/ArrayType.php', 'Psalm\\Internal\\Type\\AssertionReconciler' => $baseDir . '/src/Psalm/Internal/Type/AssertionReconciler.php', 'Psalm\\Internal\\Type\\Comparator\\ArrayTypeComparator' => $baseDir . '/src/Psalm/Internal/Type/Comparator/ArrayTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\AtomicTypeComparator' => $baseDir . '/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\CallableTypeComparator' => $baseDir . '/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\ClassStringComparator' => $baseDir . '/src/Psalm/Internal/Type/Comparator/ClassStringComparator.php', 'Psalm\\Internal\\Type\\Comparator\\GenericTypeComparator' => $baseDir . '/src/Psalm/Internal/Type/Comparator/GenericTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\KeyedArrayComparator' => $baseDir . '/src/Psalm/Internal/Type/Comparator/KeyedArrayComparator.php', 'Psalm\\Internal\\Type\\Comparator\\ObjectComparator' => $baseDir . '/src/Psalm/Internal/Type/Comparator/ObjectComparator.php', 'Psalm\\Internal\\Type\\Comparator\\ScalarTypeComparator' => $baseDir . '/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\TypeComparisonResult' => $baseDir . '/src/Psalm/Internal/Type/Comparator/TypeComparisonResult.php', 'Psalm\\Internal\\Type\\Comparator\\UnionTypeComparator' => $baseDir . '/src/Psalm/Internal/Type/Comparator/UnionTypeComparator.php', 'Psalm\\Internal\\Type\\NegatedAssertionReconciler' => $baseDir . '/src/Psalm/Internal/Type/NegatedAssertionReconciler.php', 'Psalm\\Internal\\Type\\ParseTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree.php', 'Psalm\\Internal\\Type\\ParseTreeCreator' => $baseDir . '/src/Psalm/Internal/Type/ParseTreeCreator.php', 'Psalm\\Internal\\Type\\ParseTree\\CallableParamTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/CallableParamTree.php', 'Psalm\\Internal\\Type\\ParseTree\\CallableTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/CallableTree.php', 'Psalm\\Internal\\Type\\ParseTree\\CallableWithReturnTypeTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/CallableWithReturnTypeTree.php', 'Psalm\\Internal\\Type\\ParseTree\\ConditionalTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/ConditionalTree.php', 'Psalm\\Internal\\Type\\ParseTree\\EncapsulationTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/EncapsulationTree.php', 'Psalm\\Internal\\Type\\ParseTree\\GenericTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/GenericTree.php', 'Psalm\\Internal\\Type\\ParseTree\\IndexedAccessTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/IndexedAccessTree.php', 'Psalm\\Internal\\Type\\ParseTree\\IntersectionTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/IntersectionTree.php', 'Psalm\\Internal\\Type\\ParseTree\\KeyedArrayPropertyTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/KeyedArrayPropertyTree.php', 'Psalm\\Internal\\Type\\ParseTree\\KeyedArrayTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/KeyedArrayTree.php', 'Psalm\\Internal\\Type\\ParseTree\\MethodParamTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/MethodParamTree.php', 'Psalm\\Internal\\Type\\ParseTree\\MethodTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/MethodTree.php', 'Psalm\\Internal\\Type\\ParseTree\\MethodWithReturnTypeTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/MethodWithReturnTypeTree.php', 'Psalm\\Internal\\Type\\ParseTree\\NullableTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/NullableTree.php', 'Psalm\\Internal\\Type\\ParseTree\\Root' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/Root.php', 'Psalm\\Internal\\Type\\ParseTree\\TemplateAsTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/TemplateAsTree.php', 'Psalm\\Internal\\Type\\ParseTree\\TemplateIsTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/TemplateIsTree.php', 'Psalm\\Internal\\Type\\ParseTree\\UnionTree' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/UnionTree.php', 'Psalm\\Internal\\Type\\ParseTree\\Value' => $baseDir . '/src/Psalm/Internal/Type/ParseTree/Value.php', 'Psalm\\Internal\\Type\\SimpleAssertionReconciler' => $baseDir . '/src/Psalm/Internal/Type/SimpleAssertionReconciler.php', 'Psalm\\Internal\\Type\\SimpleNegatedAssertionReconciler' => $baseDir . '/src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php', 'Psalm\\Internal\\Type\\TemplateResult' => $baseDir . '/src/Psalm/Internal/Type/TemplateResult.php', 'Psalm\\Internal\\Type\\TypeAlias' => $baseDir . '/src/Psalm/Internal/Type/TypeAlias.php', 'Psalm\\Internal\\Type\\TypeAlias\\ClassTypeAlias' => $baseDir . '/src/Psalm/Internal/Type/TypeAlias/ClassTypeAlias.php', 'Psalm\\Internal\\Type\\TypeAlias\\InlineTypeAlias' => $baseDir . '/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php', 'Psalm\\Internal\\Type\\TypeAlias\\LinkableTypeAlias' => $baseDir . '/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php', 'Psalm\\Internal\\Type\\TypeCombination' => $baseDir . '/src/Psalm/Internal/Type/TypeCombination.php', 'Psalm\\Internal\\Type\\TypeExpander' => $baseDir . '/src/Psalm/Internal/Type/TypeExpander.php', 'Psalm\\Internal\\Type\\TypeParser' => $baseDir . '/src/Psalm/Internal/Type/TypeParser.php', 'Psalm\\Internal\\Type\\TypeTokenizer' => $baseDir . '/src/Psalm/Internal/Type/TypeTokenizer.php', 'Psalm\\Internal\\Type\\UnionTemplateHandler' => $baseDir . '/src/Psalm/Internal/Type/UnionTemplateHandler.php', 'Psalm\\IssueBuffer' => $baseDir . '/src/Psalm/IssueBuffer.php', 'Psalm\\Issue\\AbstractInstantiation' => $baseDir . '/src/Psalm/Issue/AbstractInstantiation.php', 'Psalm\\Issue\\AbstractMethodCall' => $baseDir . '/src/Psalm/Issue/AbstractMethodCall.php', 'Psalm\\Issue\\ArgumentIssue' => $baseDir . '/src/Psalm/Issue/ArgumentIssue.php', 'Psalm\\Issue\\ArgumentTypeCoercion' => $baseDir . '/src/Psalm/Issue/ArgumentTypeCoercion.php', 'Psalm\\Issue\\AssignmentToVoid' => $baseDir . '/src/Psalm/Issue/AssignmentToVoid.php', 'Psalm\\Issue\\CircularReference' => $baseDir . '/src/Psalm/Issue/CircularReference.php', 'Psalm\\Issue\\ClassIssue' => $baseDir . '/src/Psalm/Issue/ClassIssue.php', 'Psalm\\Issue\\CodeIssue' => $baseDir . '/src/Psalm/Issue/CodeIssue.php', 'Psalm\\Issue\\ConflictingReferenceConstraint' => $baseDir . '/src/Psalm/Issue/ConflictingReferenceConstraint.php', 'Psalm\\Issue\\ConstructorSignatureMismatch' => $baseDir . '/src/Psalm/Issue/ConstructorSignatureMismatch.php', 'Psalm\\Issue\\ContinueOutsideLoop' => $baseDir . '/src/Psalm/Issue/ContinueOutsideLoop.php', 'Psalm\\Issue\\DeprecatedClass' => $baseDir . '/src/Psalm/Issue/DeprecatedClass.php', 'Psalm\\Issue\\DeprecatedConstant' => $baseDir . '/src/Psalm/Issue/DeprecatedConstant.php', 'Psalm\\Issue\\DeprecatedFunction' => $baseDir . '/src/Psalm/Issue/DeprecatedFunction.php', 'Psalm\\Issue\\DeprecatedInterface' => $baseDir . '/src/Psalm/Issue/DeprecatedInterface.php', 'Psalm\\Issue\\DeprecatedMethod' => $baseDir . '/src/Psalm/Issue/DeprecatedMethod.php', 'Psalm\\Issue\\DeprecatedProperty' => $baseDir . '/src/Psalm/Issue/DeprecatedProperty.php', 'Psalm\\Issue\\DeprecatedTrait' => $baseDir . '/src/Psalm/Issue/DeprecatedTrait.php', 'Psalm\\Issue\\DocblockTypeContradiction' => $baseDir . '/src/Psalm/Issue/DocblockTypeContradiction.php', 'Psalm\\Issue\\DuplicateArrayKey' => $baseDir . '/src/Psalm/Issue/DuplicateArrayKey.php', 'Psalm\\Issue\\DuplicateClass' => $baseDir . '/src/Psalm/Issue/DuplicateClass.php', 'Psalm\\Issue\\DuplicateFunction' => $baseDir . '/src/Psalm/Issue/DuplicateFunction.php', 'Psalm\\Issue\\DuplicateMethod' => $baseDir . '/src/Psalm/Issue/DuplicateMethod.php', 'Psalm\\Issue\\DuplicateParam' => $baseDir . '/src/Psalm/Issue/DuplicateParam.php', 'Psalm\\Issue\\EmptyArrayAccess' => $baseDir . '/src/Psalm/Issue/EmptyArrayAccess.php', 'Psalm\\Issue\\ExtensionRequirementViolation' => $baseDir . '/src/Psalm/Issue/ExtensionRequirementViolation.php', 'Psalm\\Issue\\FalsableReturnStatement' => $baseDir . '/src/Psalm/Issue/FalsableReturnStatement.php', 'Psalm\\Issue\\FalseOperand' => $baseDir . '/src/Psalm/Issue/FalseOperand.php', 'Psalm\\Issue\\ForbiddenCode' => $baseDir . '/src/Psalm/Issue/ForbiddenCode.php', 'Psalm\\Issue\\ForbiddenEcho' => $baseDir . '/src/Psalm/Issue/ForbiddenEcho.php', 'Psalm\\Issue\\FunctionIssue' => $baseDir . '/src/Psalm/Issue/FunctionIssue.php', 'Psalm\\Issue\\ImplementationRequirementViolation' => $baseDir . '/src/Psalm/Issue/ImplementationRequirementViolation.php', 'Psalm\\Issue\\ImplementedParamTypeMismatch' => $baseDir . '/src/Psalm/Issue/ImplementedParamTypeMismatch.php', 'Psalm\\Issue\\ImplementedReturnTypeMismatch' => $baseDir . '/src/Psalm/Issue/ImplementedReturnTypeMismatch.php', 'Psalm\\Issue\\ImplicitToStringCast' => $baseDir . '/src/Psalm/Issue/ImplicitToStringCast.php', 'Psalm\\Issue\\ImpureByReferenceAssignment' => $baseDir . '/src/Psalm/Issue/ImpureByReferenceAssignment.php', 'Psalm\\Issue\\ImpureFunctionCall' => $baseDir . '/src/Psalm/Issue/ImpureFunctionCall.php', 'Psalm\\Issue\\ImpureMethodCall' => $baseDir . '/src/Psalm/Issue/ImpureMethodCall.php', 'Psalm\\Issue\\ImpurePropertyAssignment' => $baseDir . '/src/Psalm/Issue/ImpurePropertyAssignment.php', 'Psalm\\Issue\\ImpurePropertyFetch' => $baseDir . '/src/Psalm/Issue/ImpurePropertyFetch.php', 'Psalm\\Issue\\ImpureStaticProperty' => $baseDir . '/src/Psalm/Issue/ImpureStaticProperty.php', 'Psalm\\Issue\\ImpureStaticVariable' => $baseDir . '/src/Psalm/Issue/ImpureStaticVariable.php', 'Psalm\\Issue\\ImpureVariable' => $baseDir . '/src/Psalm/Issue/ImpureVariable.php', 'Psalm\\Issue\\InaccessibleClassConstant' => $baseDir . '/src/Psalm/Issue/InaccessibleClassConstant.php', 'Psalm\\Issue\\InaccessibleMethod' => $baseDir . '/src/Psalm/Issue/InaccessibleMethod.php', 'Psalm\\Issue\\InaccessibleProperty' => $baseDir . '/src/Psalm/Issue/InaccessibleProperty.php', 'Psalm\\Issue\\InterfaceInstantiation' => $baseDir . '/src/Psalm/Issue/InterfaceInstantiation.php', 'Psalm\\Issue\\InternalClass' => $baseDir . '/src/Psalm/Issue/InternalClass.php', 'Psalm\\Issue\\InternalMethod' => $baseDir . '/src/Psalm/Issue/InternalMethod.php', 'Psalm\\Issue\\InternalProperty' => $baseDir . '/src/Psalm/Issue/InternalProperty.php', 'Psalm\\Issue\\InvalidArgument' => $baseDir . '/src/Psalm/Issue/InvalidArgument.php', 'Psalm\\Issue\\InvalidArrayAccess' => $baseDir . '/src/Psalm/Issue/InvalidArrayAccess.php', 'Psalm\\Issue\\InvalidArrayAssignment' => $baseDir . '/src/Psalm/Issue/InvalidArrayAssignment.php', 'Psalm\\Issue\\InvalidArrayOffset' => $baseDir . '/src/Psalm/Issue/InvalidArrayOffset.php', 'Psalm\\Issue\\InvalidCast' => $baseDir . '/src/Psalm/Issue/InvalidCast.php', 'Psalm\\Issue\\InvalidCatch' => $baseDir . '/src/Psalm/Issue/InvalidCatch.php', 'Psalm\\Issue\\InvalidClass' => $baseDir . '/src/Psalm/Issue/InvalidClass.php', 'Psalm\\Issue\\InvalidClone' => $baseDir . '/src/Psalm/Issue/InvalidClone.php', 'Psalm\\Issue\\InvalidDocblock' => $baseDir . '/src/Psalm/Issue/InvalidDocblock.php', 'Psalm\\Issue\\InvalidDocblockParamName' => $baseDir . '/src/Psalm/Issue/InvalidDocblockParamName.php', 'Psalm\\Issue\\InvalidExtendClass' => $baseDir . '/src/Psalm/Issue/InvalidExtendClass.php', 'Psalm\\Issue\\InvalidFalsableReturnType' => $baseDir . '/src/Psalm/Issue/InvalidFalsableReturnType.php', 'Psalm\\Issue\\InvalidFunctionCall' => $baseDir . '/src/Psalm/Issue/InvalidFunctionCall.php', 'Psalm\\Issue\\InvalidGlobal' => $baseDir . '/src/Psalm/Issue/InvalidGlobal.php', 'Psalm\\Issue\\InvalidIterator' => $baseDir . '/src/Psalm/Issue/InvalidIterator.php', 'Psalm\\Issue\\InvalidLiteralArgument' => $baseDir . '/src/Psalm/Issue/InvalidLiteralArgument.php', 'Psalm\\Issue\\InvalidMethodCall' => $baseDir . '/src/Psalm/Issue/InvalidMethodCall.php', 'Psalm\\Issue\\InvalidNamedArgument' => $baseDir . '/src/Psalm/Issue/InvalidNamedArgument.php', 'Psalm\\Issue\\InvalidNullableReturnType' => $baseDir . '/src/Psalm/Issue/InvalidNullableReturnType.php', 'Psalm\\Issue\\InvalidOperand' => $baseDir . '/src/Psalm/Issue/InvalidOperand.php', 'Psalm\\Issue\\InvalidParamDefault' => $baseDir . '/src/Psalm/Issue/InvalidParamDefault.php', 'Psalm\\Issue\\InvalidParent' => $baseDir . '/src/Psalm/Issue/InvalidParent.php', 'Psalm\\Issue\\InvalidPassByReference' => $baseDir . '/src/Psalm/Issue/InvalidPassByReference.php', 'Psalm\\Issue\\InvalidPropertyAssignment' => $baseDir . '/src/Psalm/Issue/InvalidPropertyAssignment.php', 'Psalm\\Issue\\InvalidPropertyAssignmentValue' => $baseDir . '/src/Psalm/Issue/InvalidPropertyAssignmentValue.php', 'Psalm\\Issue\\InvalidPropertyFetch' => $baseDir . '/src/Psalm/Issue/InvalidPropertyFetch.php', 'Psalm\\Issue\\InvalidReturnStatement' => $baseDir . '/src/Psalm/Issue/InvalidReturnStatement.php', 'Psalm\\Issue\\InvalidReturnType' => $baseDir . '/src/Psalm/Issue/InvalidReturnType.php', 'Psalm\\Issue\\InvalidScalarArgument' => $baseDir . '/src/Psalm/Issue/InvalidScalarArgument.php', 'Psalm\\Issue\\InvalidScope' => $baseDir . '/src/Psalm/Issue/InvalidScope.php', 'Psalm\\Issue\\InvalidStaticInvocation' => $baseDir . '/src/Psalm/Issue/InvalidStaticInvocation.php', 'Psalm\\Issue\\InvalidStringClass' => $baseDir . '/src/Psalm/Issue/InvalidStringClass.php', 'Psalm\\Issue\\InvalidTemplateParam' => $baseDir . '/src/Psalm/Issue/InvalidTemplateParam.php', 'Psalm\\Issue\\InvalidThrow' => $baseDir . '/src/Psalm/Issue/InvalidThrow.php', 'Psalm\\Issue\\InvalidToString' => $baseDir . '/src/Psalm/Issue/InvalidToString.php', 'Psalm\\Issue\\InvalidTypeImport' => $baseDir . '/src/Psalm/Issue/InvalidTypeImport.php', 'Psalm\\Issue\\LessSpecificImplementedReturnType' => $baseDir . '/src/Psalm/Issue/LessSpecificImplementedReturnType.php', 'Psalm\\Issue\\LessSpecificReturnStatement' => $baseDir . '/src/Psalm/Issue/LessSpecificReturnStatement.php', 'Psalm\\Issue\\LessSpecificReturnType' => $baseDir . '/src/Psalm/Issue/LessSpecificReturnType.php', 'Psalm\\Issue\\LoopInvalidation' => $baseDir . '/src/Psalm/Issue/LoopInvalidation.php', 'Psalm\\Issue\\MethodIssue' => $baseDir . '/src/Psalm/Issue/MethodIssue.php', 'Psalm\\Issue\\MethodSignatureMismatch' => $baseDir . '/src/Psalm/Issue/MethodSignatureMismatch.php', 'Psalm\\Issue\\MethodSignatureMustOmitReturnType' => $baseDir . '/src/Psalm/Issue/MethodSignatureMustOmitReturnType.php', 'Psalm\\Issue\\MismatchingDocblockParamType' => $baseDir . '/src/Psalm/Issue/MismatchingDocblockParamType.php', 'Psalm\\Issue\\MismatchingDocblockReturnType' => $baseDir . '/src/Psalm/Issue/MismatchingDocblockReturnType.php', 'Psalm\\Issue\\MissingClosureParamType' => $baseDir . '/src/Psalm/Issue/MissingClosureParamType.php', 'Psalm\\Issue\\MissingClosureReturnType' => $baseDir . '/src/Psalm/Issue/MissingClosureReturnType.php', 'Psalm\\Issue\\MissingConstructor' => $baseDir . '/src/Psalm/Issue/MissingConstructor.php', 'Psalm\\Issue\\MissingDependency' => $baseDir . '/src/Psalm/Issue/MissingDependency.php', 'Psalm\\Issue\\MissingDocblockType' => $baseDir . '/src/Psalm/Issue/MissingDocblockType.php', 'Psalm\\Issue\\MissingFile' => $baseDir . '/src/Psalm/Issue/MissingFile.php', 'Psalm\\Issue\\MissingImmutableAnnotation' => $baseDir . '/src/Psalm/Issue/MissingImmutableAnnotation.php', 'Psalm\\Issue\\MissingParamType' => $baseDir . '/src/Psalm/Issue/MissingParamType.php', 'Psalm\\Issue\\MissingPropertyType' => $baseDir . '/src/Psalm/Issue/MissingPropertyType.php', 'Psalm\\Issue\\MissingReturnType' => $baseDir . '/src/Psalm/Issue/MissingReturnType.php', 'Psalm\\Issue\\MissingTemplateParam' => $baseDir . '/src/Psalm/Issue/MissingTemplateParam.php', 'Psalm\\Issue\\MissingThrowsDocblock' => $baseDir . '/src/Psalm/Issue/MissingThrowsDocblock.php', 'Psalm\\Issue\\MixedArgument' => $baseDir . '/src/Psalm/Issue/MixedArgument.php', 'Psalm\\Issue\\MixedArgumentTypeCoercion' => $baseDir . '/src/Psalm/Issue/MixedArgumentTypeCoercion.php', 'Psalm\\Issue\\MixedArrayAccess' => $baseDir . '/src/Psalm/Issue/MixedArrayAccess.php', 'Psalm\\Issue\\MixedArrayAssignment' => $baseDir . '/src/Psalm/Issue/MixedArrayAssignment.php', 'Psalm\\Issue\\MixedArrayOffset' => $baseDir . '/src/Psalm/Issue/MixedArrayOffset.php', 'Psalm\\Issue\\MixedArrayTypeCoercion' => $baseDir . '/src/Psalm/Issue/MixedArrayTypeCoercion.php', 'Psalm\\Issue\\MixedAssignment' => $baseDir . '/src/Psalm/Issue/MixedAssignment.php', 'Psalm\\Issue\\MixedClone' => $baseDir . '/src/Psalm/Issue/MixedClone.php', 'Psalm\\Issue\\MixedFunctionCall' => $baseDir . '/src/Psalm/Issue/MixedFunctionCall.php', 'Psalm\\Issue\\MixedInferredReturnType' => $baseDir . '/src/Psalm/Issue/MixedInferredReturnType.php', 'Psalm\\Issue\\MixedMethodCall' => $baseDir . '/src/Psalm/Issue/MixedMethodCall.php', 'Psalm\\Issue\\MixedOperand' => $baseDir . '/src/Psalm/Issue/MixedOperand.php', 'Psalm\\Issue\\MixedPropertyAssignment' => $baseDir . '/src/Psalm/Issue/MixedPropertyAssignment.php', 'Psalm\\Issue\\MixedPropertyFetch' => $baseDir . '/src/Psalm/Issue/MixedPropertyFetch.php', 'Psalm\\Issue\\MixedPropertyTypeCoercion' => $baseDir . '/src/Psalm/Issue/MixedPropertyTypeCoercion.php', 'Psalm\\Issue\\MixedReturnStatement' => $baseDir . '/src/Psalm/Issue/MixedReturnStatement.php', 'Psalm\\Issue\\MixedReturnTypeCoercion' => $baseDir . '/src/Psalm/Issue/MixedReturnTypeCoercion.php', 'Psalm\\Issue\\MixedStringOffsetAssignment' => $baseDir . '/src/Psalm/Issue/MixedStringOffsetAssignment.php', 'Psalm\\Issue\\MoreSpecificImplementedParamType' => $baseDir . '/src/Psalm/Issue/MoreSpecificImplementedParamType.php', 'Psalm\\Issue\\MoreSpecificReturnType' => $baseDir . '/src/Psalm/Issue/MoreSpecificReturnType.php', 'Psalm\\Issue\\MutableDependency' => $baseDir . '/src/Psalm/Issue/MutableDependency.php', 'Psalm\\Issue\\NoInterfaceProperties' => $baseDir . '/src/Psalm/Issue/NoInterfaceProperties.php', 'Psalm\\Issue\\NoValue' => $baseDir . '/src/Psalm/Issue/NoValue.php', 'Psalm\\Issue\\NonStaticSelfCall' => $baseDir . '/src/Psalm/Issue/NonStaticSelfCall.php', 'Psalm\\Issue\\NullArgument' => $baseDir . '/src/Psalm/Issue/NullArgument.php', 'Psalm\\Issue\\NullArrayAccess' => $baseDir . '/src/Psalm/Issue/NullArrayAccess.php', 'Psalm\\Issue\\NullArrayOffset' => $baseDir . '/src/Psalm/Issue/NullArrayOffset.php', 'Psalm\\Issue\\NullFunctionCall' => $baseDir . '/src/Psalm/Issue/NullFunctionCall.php', 'Psalm\\Issue\\NullIterator' => $baseDir . '/src/Psalm/Issue/NullIterator.php', 'Psalm\\Issue\\NullOperand' => $baseDir . '/src/Psalm/Issue/NullOperand.php', 'Psalm\\Issue\\NullPropertyAssignment' => $baseDir . '/src/Psalm/Issue/NullPropertyAssignment.php', 'Psalm\\Issue\\NullPropertyFetch' => $baseDir . '/src/Psalm/Issue/NullPropertyFetch.php', 'Psalm\\Issue\\NullReference' => $baseDir . '/src/Psalm/Issue/NullReference.php', 'Psalm\\Issue\\NullableReturnStatement' => $baseDir . '/src/Psalm/Issue/NullableReturnStatement.php', 'Psalm\\Issue\\OverriddenMethodAccess' => $baseDir . '/src/Psalm/Issue/OverriddenMethodAccess.php', 'Psalm\\Issue\\OverriddenPropertyAccess' => $baseDir . '/src/Psalm/Issue/OverriddenPropertyAccess.php', 'Psalm\\Issue\\ParadoxicalCondition' => $baseDir . '/src/Psalm/Issue/ParadoxicalCondition.php', 'Psalm\\Issue\\ParamNameMismatch' => $baseDir . '/src/Psalm/Issue/ParamNameMismatch.php', 'Psalm\\Issue\\ParentNotFound' => $baseDir . '/src/Psalm/Issue/ParentNotFound.php', 'Psalm\\Issue\\ParseError' => $baseDir . '/src/Psalm/Issue/ParseError.php', 'Psalm\\Issue\\PluginIssue' => $baseDir . '/src/Psalm/Issue/PluginIssue.php', 'Psalm\\Issue\\PossibleRawObjectIteration' => $baseDir . '/src/Psalm/Issue/PossibleRawObjectIteration.php', 'Psalm\\Issue\\PossiblyFalseArgument' => $baseDir . '/src/Psalm/Issue/PossiblyFalseArgument.php', 'Psalm\\Issue\\PossiblyFalseIterator' => $baseDir . '/src/Psalm/Issue/PossiblyFalseIterator.php', 'Psalm\\Issue\\PossiblyFalseOperand' => $baseDir . '/src/Psalm/Issue/PossiblyFalseOperand.php', 'Psalm\\Issue\\PossiblyFalsePropertyAssignmentValue' => $baseDir . '/src/Psalm/Issue/PossiblyFalsePropertyAssignmentValue.php', 'Psalm\\Issue\\PossiblyFalseReference' => $baseDir . '/src/Psalm/Issue/PossiblyFalseReference.php', 'Psalm\\Issue\\PossiblyInvalidArgument' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidArgument.php', 'Psalm\\Issue\\PossiblyInvalidArrayAccess' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidArrayAccess.php', 'Psalm\\Issue\\PossiblyInvalidArrayAssignment' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidArrayAssignment.php', 'Psalm\\Issue\\PossiblyInvalidArrayOffset' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidArrayOffset.php', 'Psalm\\Issue\\PossiblyInvalidCast' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidCast.php', 'Psalm\\Issue\\PossiblyInvalidClone' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidClone.php', 'Psalm\\Issue\\PossiblyInvalidFunctionCall' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidFunctionCall.php', 'Psalm\\Issue\\PossiblyInvalidIterator' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidIterator.php', 'Psalm\\Issue\\PossiblyInvalidMethodCall' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidMethodCall.php', 'Psalm\\Issue\\PossiblyInvalidOperand' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidOperand.php', 'Psalm\\Issue\\PossiblyInvalidPropertyAssignment' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidPropertyAssignment.php', 'Psalm\\Issue\\PossiblyInvalidPropertyAssignmentValue' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidPropertyAssignmentValue.php', 'Psalm\\Issue\\PossiblyInvalidPropertyFetch' => $baseDir . '/src/Psalm/Issue/PossiblyInvalidPropertyFetch.php', 'Psalm\\Issue\\PossiblyNullArgument' => $baseDir . '/src/Psalm/Issue/PossiblyNullArgument.php', 'Psalm\\Issue\\PossiblyNullArrayAccess' => $baseDir . '/src/Psalm/Issue/PossiblyNullArrayAccess.php', 'Psalm\\Issue\\PossiblyNullArrayAssignment' => $baseDir . '/src/Psalm/Issue/PossiblyNullArrayAssignment.php', 'Psalm\\Issue\\PossiblyNullArrayOffset' => $baseDir . '/src/Psalm/Issue/PossiblyNullArrayOffset.php', 'Psalm\\Issue\\PossiblyNullFunctionCall' => $baseDir . '/src/Psalm/Issue/PossiblyNullFunctionCall.php', 'Psalm\\Issue\\PossiblyNullIterator' => $baseDir . '/src/Psalm/Issue/PossiblyNullIterator.php', 'Psalm\\Issue\\PossiblyNullOperand' => $baseDir . '/src/Psalm/Issue/PossiblyNullOperand.php', 'Psalm\\Issue\\PossiblyNullPropertyAssignment' => $baseDir . '/src/Psalm/Issue/PossiblyNullPropertyAssignment.php', 'Psalm\\Issue\\PossiblyNullPropertyAssignmentValue' => $baseDir . '/src/Psalm/Issue/PossiblyNullPropertyAssignmentValue.php', 'Psalm\\Issue\\PossiblyNullPropertyFetch' => $baseDir . '/src/Psalm/Issue/PossiblyNullPropertyFetch.php', 'Psalm\\Issue\\PossiblyNullReference' => $baseDir . '/src/Psalm/Issue/PossiblyNullReference.php', 'Psalm\\Issue\\PossiblyUndefinedArrayOffset' => $baseDir . '/src/Psalm/Issue/PossiblyUndefinedArrayOffset.php', 'Psalm\\Issue\\PossiblyUndefinedGlobalVariable' => $baseDir . '/src/Psalm/Issue/PossiblyUndefinedGlobalVariable.php', 'Psalm\\Issue\\PossiblyUndefinedIntArrayOffset' => $baseDir . '/src/Psalm/Issue/PossiblyUndefinedIntArrayOffset.php', 'Psalm\\Issue\\PossiblyUndefinedMethod' => $baseDir . '/src/Psalm/Issue/PossiblyUndefinedMethod.php', 'Psalm\\Issue\\PossiblyUndefinedStringArrayOffset' => $baseDir . '/src/Psalm/Issue/PossiblyUndefinedStringArrayOffset.php', 'Psalm\\Issue\\PossiblyUndefinedVariable' => $baseDir . '/src/Psalm/Issue/PossiblyUndefinedVariable.php', 'Psalm\\Issue\\PossiblyUnusedMethod' => $baseDir . '/src/Psalm/Issue/PossiblyUnusedMethod.php', 'Psalm\\Issue\\PossiblyUnusedParam' => $baseDir . '/src/Psalm/Issue/PossiblyUnusedParam.php', 'Psalm\\Issue\\PossiblyUnusedProperty' => $baseDir . '/src/Psalm/Issue/PossiblyUnusedProperty.php', 'Psalm\\Issue\\PropertyIssue' => $baseDir . '/src/Psalm/Issue/PropertyIssue.php', 'Psalm\\Issue\\PropertyNotSetInConstructor' => $baseDir . '/src/Psalm/Issue/PropertyNotSetInConstructor.php', 'Psalm\\Issue\\PropertyTypeCoercion' => $baseDir . '/src/Psalm/Issue/PropertyTypeCoercion.php', 'Psalm\\Issue\\PsalmInternalError' => $baseDir . '/src/Psalm/Issue/PsalmInternalError.php', 'Psalm\\Issue\\RawObjectIteration' => $baseDir . '/src/Psalm/Issue/RawObjectIteration.php', 'Psalm\\Issue\\RedundantCondition' => $baseDir . '/src/Psalm/Issue/RedundantCondition.php', 'Psalm\\Issue\\RedundantConditionGivenDocblockType' => $baseDir . '/src/Psalm/Issue/RedundantConditionGivenDocblockType.php', 'Psalm\\Issue\\RedundantIdentityWithTrue' => $baseDir . '/src/Psalm/Issue/RedundantIdentityWithTrue.php', 'Psalm\\Issue\\ReferenceConstraintViolation' => $baseDir . '/src/Psalm/Issue/ReferenceConstraintViolation.php', 'Psalm\\Issue\\ReservedWord' => $baseDir . '/src/Psalm/Issue/ReservedWord.php', 'Psalm\\Issue\\StringIncrement' => $baseDir . '/src/Psalm/Issue/StringIncrement.php', 'Psalm\\Issue\\TaintedInput' => $baseDir . '/src/Psalm/Issue/TaintedInput.php', 'Psalm\\Issue\\TooFewArguments' => $baseDir . '/src/Psalm/Issue/TooFewArguments.php', 'Psalm\\Issue\\TooManyArguments' => $baseDir . '/src/Psalm/Issue/TooManyArguments.php', 'Psalm\\Issue\\TooManyTemplateParams' => $baseDir . '/src/Psalm/Issue/TooManyTemplateParams.php', 'Psalm\\Issue\\Trace' => $baseDir . '/src/Psalm/Issue/Trace.php', 'Psalm\\Issue\\TraitMethodSignatureMismatch' => $baseDir . '/src/Psalm/Issue/TraitMethodSignatureMismatch.php', 'Psalm\\Issue\\TypeDoesNotContainNull' => $baseDir . '/src/Psalm/Issue/TypeDoesNotContainNull.php', 'Psalm\\Issue\\TypeDoesNotContainType' => $baseDir . '/src/Psalm/Issue/TypeDoesNotContainType.php', 'Psalm\\Issue\\UncaughtThrowInGlobalScope' => $baseDir . '/src/Psalm/Issue/UncaughtThrowInGlobalScope.php', 'Psalm\\Issue\\UndefinedClass' => $baseDir . '/src/Psalm/Issue/UndefinedClass.php', 'Psalm\\Issue\\UndefinedConstant' => $baseDir . '/src/Psalm/Issue/UndefinedConstant.php', 'Psalm\\Issue\\UndefinedDocblockClass' => $baseDir . '/src/Psalm/Issue/UndefinedDocblockClass.php', 'Psalm\\Issue\\UndefinedFunction' => $baseDir . '/src/Psalm/Issue/UndefinedFunction.php', 'Psalm\\Issue\\UndefinedGlobalVariable' => $baseDir . '/src/Psalm/Issue/UndefinedGlobalVariable.php', 'Psalm\\Issue\\UndefinedInterface' => $baseDir . '/src/Psalm/Issue/UndefinedInterface.php', 'Psalm\\Issue\\UndefinedInterfaceMethod' => $baseDir . '/src/Psalm/Issue/UndefinedInterfaceMethod.php', 'Psalm\\Issue\\UndefinedMagicMethod' => $baseDir . '/src/Psalm/Issue/UndefinedMagicMethod.php', 'Psalm\\Issue\\UndefinedMagicPropertyAssignment' => $baseDir . '/src/Psalm/Issue/UndefinedMagicPropertyAssignment.php', 'Psalm\\Issue\\UndefinedMagicPropertyFetch' => $baseDir . '/src/Psalm/Issue/UndefinedMagicPropertyFetch.php', 'Psalm\\Issue\\UndefinedMethod' => $baseDir . '/src/Psalm/Issue/UndefinedMethod.php', 'Psalm\\Issue\\UndefinedPropertyAssignment' => $baseDir . '/src/Psalm/Issue/UndefinedPropertyAssignment.php', 'Psalm\\Issue\\UndefinedPropertyFetch' => $baseDir . '/src/Psalm/Issue/UndefinedPropertyFetch.php', 'Psalm\\Issue\\UndefinedThisPropertyAssignment' => $baseDir . '/src/Psalm/Issue/UndefinedThisPropertyAssignment.php', 'Psalm\\Issue\\UndefinedThisPropertyFetch' => $baseDir . '/src/Psalm/Issue/UndefinedThisPropertyFetch.php', 'Psalm\\Issue\\UndefinedTrace' => $baseDir . '/src/Psalm/Issue/UndefinedTrace.php', 'Psalm\\Issue\\UndefinedTrait' => $baseDir . '/src/Psalm/Issue/UndefinedTrait.php', 'Psalm\\Issue\\UndefinedVariable' => $baseDir . '/src/Psalm/Issue/UndefinedVariable.php', 'Psalm\\Issue\\UnevaluatedCode' => $baseDir . '/src/Psalm/Issue/UnevaluatedCode.php', 'Psalm\\Issue\\UnhandledMatchCondition' => $baseDir . '/src/Psalm/Issue/UnhandledMatchCondition.php', 'Psalm\\Issue\\UnimplementedAbstractMethod' => $baseDir . '/src/Psalm/Issue/UnimplementedAbstractMethod.php', 'Psalm\\Issue\\UnimplementedInterfaceMethod' => $baseDir . '/src/Psalm/Issue/UnimplementedInterfaceMethod.php', 'Psalm\\Issue\\UninitializedProperty' => $baseDir . '/src/Psalm/Issue/UninitializedProperty.php', 'Psalm\\Issue\\UnnecessaryVarAnnotation' => $baseDir . '/src/Psalm/Issue/UnnecessaryVarAnnotation.php', 'Psalm\\Issue\\UnrecognizedExpression' => $baseDir . '/src/Psalm/Issue/UnrecognizedExpression.php', 'Psalm\\Issue\\UnrecognizedStatement' => $baseDir . '/src/Psalm/Issue/UnrecognizedStatement.php', 'Psalm\\Issue\\UnresolvableInclude' => $baseDir . '/src/Psalm/Issue/UnresolvableInclude.php', 'Psalm\\Issue\\UnsafeInstantiation' => $baseDir . '/src/Psalm/Issue/UnsafeInstantiation.php', 'Psalm\\Issue\\UnusedClass' => $baseDir . '/src/Psalm/Issue/UnusedClass.php', 'Psalm\\Issue\\UnusedClosureParam' => $baseDir . '/src/Psalm/Issue/UnusedClosureParam.php', 'Psalm\\Issue\\UnusedFunctionCall' => $baseDir . '/src/Psalm/Issue/UnusedFunctionCall.php', 'Psalm\\Issue\\UnusedMethod' => $baseDir . '/src/Psalm/Issue/UnusedMethod.php', 'Psalm\\Issue\\UnusedMethodCall' => $baseDir . '/src/Psalm/Issue/UnusedMethodCall.php', 'Psalm\\Issue\\UnusedParam' => $baseDir . '/src/Psalm/Issue/UnusedParam.php', 'Psalm\\Issue\\UnusedProperty' => $baseDir . '/src/Psalm/Issue/UnusedProperty.php', 'Psalm\\Issue\\UnusedPsalmSuppress' => $baseDir . '/src/Psalm/Issue/UnusedPsalmSuppress.php', 'Psalm\\Issue\\UnusedVariable' => $baseDir . '/src/Psalm/Issue/UnusedVariable.php', 'Psalm\\Issue\\VariableIssue' => $baseDir . '/src/Psalm/Issue/VariableIssue.php', 'Psalm\\NodeTypeProvider' => $baseDir . '/src/Psalm/NodeTypeProvider.php', 'Psalm\\PluginRegistrationSocket' => $baseDir . '/src/Psalm/PluginRegistrationSocket.php', 'Psalm\\Plugin\\Hook\\AfterAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterClassLikeAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterClassLikeAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterClassLikeExistenceCheckInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterClassLikeExistenceCheckInterface.php', 'Psalm\\Plugin\\Hook\\AfterClassLikeVisitInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterClassLikeVisitInterface.php', 'Psalm\\Plugin\\Hook\\AfterCodebasePopulatedInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterCodebasePopulatedInterface.php', 'Psalm\\Plugin\\Hook\\AfterEveryFunctionCallAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterEveryFunctionCallAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterExpressionAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterExpressionAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterFileAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterFileAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterFunctionCallAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterFunctionCallAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterFunctionLikeAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterFunctionLikeAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterMethodCallAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterMethodCallAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterStatementAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/AfterStatementAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\BeforeFileAnalysisInterface' => $baseDir . '/src/Psalm/Plugin/Hook/BeforeFileAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\FunctionExistenceProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/FunctionExistenceProviderInterface.php', 'Psalm\\Plugin\\Hook\\FunctionParamsProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/FunctionParamsProviderInterface.php', 'Psalm\\Plugin\\Hook\\FunctionReturnTypeProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/FunctionReturnTypeProviderInterface.php', 'Psalm\\Plugin\\Hook\\MethodExistenceProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/MethodExistenceProviderInterface.php', 'Psalm\\Plugin\\Hook\\MethodParamsProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/MethodParamsProviderInterface.php', 'Psalm\\Plugin\\Hook\\MethodReturnTypeProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/MethodReturnTypeProviderInterface.php', 'Psalm\\Plugin\\Hook\\MethodVisibilityProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/MethodVisibilityProviderInterface.php', 'Psalm\\Plugin\\Hook\\PropertyExistenceProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/PropertyExistenceProviderInterface.php', 'Psalm\\Plugin\\Hook\\PropertyTypeProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/PropertyTypeProviderInterface.php', 'Psalm\\Plugin\\Hook\\PropertyVisibilityProviderInterface' => $baseDir . '/src/Psalm/Plugin/Hook/PropertyVisibilityProviderInterface.php', 'Psalm\\Plugin\\Hook\\StringInterpreterInterface' => $baseDir . '/src/Psalm/Plugin/Hook/StringInterpreterInterface.php', 'Psalm\\Plugin\\PluginEntryPointInterface' => $baseDir . '/src/Psalm/Plugin/PluginEntryPointInterface.php', 'Psalm\\Plugin\\RegistrationInterface' => $baseDir . '/src/Psalm/Plugin/RegistrationInterface.php', 'Psalm\\Plugin\\Shepherd' => $baseDir . '/src/Psalm/Plugin/Shepherd.php', 'Psalm\\Progress\\DebugProgress' => $baseDir . '/src/Psalm/Progress/DebugProgress.php', 'Psalm\\Progress\\DefaultProgress' => $baseDir . '/src/Psalm/Progress/DefaultProgress.php', 'Psalm\\Progress\\LongProgress' => $baseDir . '/src/Psalm/Progress/LongProgress.php', 'Psalm\\Progress\\Progress' => $baseDir . '/src/Psalm/Progress/Progress.php', 'Psalm\\Progress\\VoidProgress' => $baseDir . '/src/Psalm/Progress/VoidProgress.php', 'Psalm\\Report' => $baseDir . '/src/Psalm/Report.php', 'Psalm\\Report\\CheckstyleReport' => $baseDir . '/src/Psalm/Report/CheckstyleReport.php', 'Psalm\\Report\\CompactReport' => $baseDir . '/src/Psalm/Report/CompactReport.php', 'Psalm\\Report\\ConsoleReport' => $baseDir . '/src/Psalm/Report/ConsoleReport.php', 'Psalm\\Report\\EmacsReport' => $baseDir . '/src/Psalm/Report/EmacsReport.php', 'Psalm\\Report\\GithubActionsReport' => $baseDir . '/src/Psalm/Report/GithubActionsReport.php', 'Psalm\\Report\\JsonReport' => $baseDir . '/src/Psalm/Report/JsonReport.php', 'Psalm\\Report\\JsonSummaryReport' => $baseDir . '/src/Psalm/Report/JsonSummaryReport.php', 'Psalm\\Report\\JunitReport' => $baseDir . '/src/Psalm/Report/JunitReport.php', 'Psalm\\Report\\PhpStormReport' => $baseDir . '/src/Psalm/Report/PhpStormReport.php', 'Psalm\\Report\\PylintReport' => $baseDir . '/src/Psalm/Report/PylintReport.php', 'Psalm\\Report\\ReportOptions' => $baseDir . '/src/Psalm/Report/ReportOptions.php', 'Psalm\\Report\\SonarqubeReport' => $baseDir . '/src/Psalm/Report/SonarqubeReport.php', 'Psalm\\Report\\TextReport' => $baseDir . '/src/Psalm/Report/TextReport.php', 'Psalm\\Report\\XmlReport' => $baseDir . '/src/Psalm/Report/XmlReport.php', 'Psalm\\SourceControl\\Git\\CommitInfo' => $baseDir . '/src/Psalm/SourceControl/Git/CommitInfo.php', 'Psalm\\SourceControl\\Git\\GitInfo' => $baseDir . '/src/Psalm/SourceControl/Git/GitInfo.php', 'Psalm\\SourceControl\\Git\\RemoteInfo' => $baseDir . '/src/Psalm/SourceControl/Git/RemoteInfo.php', 'Psalm\\SourceControl\\SourceControlInfo' => $baseDir . '/src/Psalm/SourceControl/SourceControlInfo.php', 'Psalm\\StatementsSource' => $baseDir . '/src/Psalm/StatementsSource.php', 'Psalm\\Storage\\Assertion' => $baseDir . '/src/Psalm/Storage/Assertion.php', 'Psalm\\Storage\\ClassConstantStorage' => $baseDir . '/src/Psalm/Storage/ClassConstantStorage.php', 'Psalm\\Storage\\ClassLikeStorage' => $baseDir . '/src/Psalm/Storage/ClassLikeStorage.php', 'Psalm\\Storage\\CustomMetadataTrait' => $baseDir . '/src/Psalm/Storage/CustomMetadataTrait.php', 'Psalm\\Storage\\FileStorage' => $baseDir . '/src/Psalm/Storage/FileStorage.php', 'Psalm\\Storage\\FunctionLikeParameter' => $baseDir . '/src/Psalm/Storage/FunctionLikeParameter.php', 'Psalm\\Storage\\FunctionLikeStorage' => $baseDir . '/src/Psalm/Storage/FunctionLikeStorage.php', 'Psalm\\Storage\\FunctionStorage' => $baseDir . '/src/Psalm/Storage/FunctionStorage.php', 'Psalm\\Storage\\MethodStorage' => $baseDir . '/src/Psalm/Storage/MethodStorage.php', 'Psalm\\Storage\\PropertyStorage' => $baseDir . '/src/Psalm/Storage/PropertyStorage.php', 'Psalm\\Type' => $baseDir . '/src/Psalm/Type.php', 'Psalm\\Type\\Algebra' => $baseDir . '/src/Psalm/Type/Algebra.php', 'Psalm\\Type\\Atomic' => $baseDir . '/src/Psalm/Type/Atomic.php', 'Psalm\\Type\\Atomic\\CallableTrait' => $baseDir . '/src/Psalm/Type/Atomic/CallableTrait.php', 'Psalm\\Type\\Atomic\\GenericTrait' => $baseDir . '/src/Psalm/Type/Atomic/GenericTrait.php', 'Psalm\\Type\\Atomic\\HasIntersectionTrait' => $baseDir . '/src/Psalm/Type/Atomic/HasIntersectionTrait.php', 'Psalm\\Type\\Atomic\\Scalar' => $baseDir . '/src/Psalm/Type/Atomic/Scalar.php', 'Psalm\\Type\\Atomic\\TAnonymousClassInstance' => $baseDir . '/src/Psalm/Type/Atomic/TAnonymousClassInstance.php', 'Psalm\\Type\\Atomic\\TArray' => $baseDir . '/src/Psalm/Type/Atomic/TArray.php', 'Psalm\\Type\\Atomic\\TArrayKey' => $baseDir . '/src/Psalm/Type/Atomic/TArrayKey.php', 'Psalm\\Type\\Atomic\\TAssertionFalsy' => $baseDir . '/src/Psalm/Type/Atomic/TAssertionFalsy.php', 'Psalm\\Type\\Atomic\\TBool' => $baseDir . '/src/Psalm/Type/Atomic/TBool.php', 'Psalm\\Type\\Atomic\\TCallable' => $baseDir . '/src/Psalm/Type/Atomic/TCallable.php', 'Psalm\\Type\\Atomic\\TCallableArray' => $baseDir . '/src/Psalm/Type/Atomic/TCallableArray.php', 'Psalm\\Type\\Atomic\\TCallableKeyedArray' => $baseDir . '/src/Psalm/Type/Atomic/TCallableKeyedArray.php', 'Psalm\\Type\\Atomic\\TCallableList' => $baseDir . '/src/Psalm/Type/Atomic/TCallableList.php', 'Psalm\\Type\\Atomic\\TCallableObject' => $baseDir . '/src/Psalm/Type/Atomic/TCallableObject.php', 'Psalm\\Type\\Atomic\\TCallableString' => $baseDir . '/src/Psalm/Type/Atomic/TCallableString.php', 'Psalm\\Type\\Atomic\\TClassString' => $baseDir . '/src/Psalm/Type/Atomic/TClassString.php', 'Psalm\\Type\\Atomic\\TClassStringMap' => $baseDir . '/src/Psalm/Type/Atomic/TClassStringMap.php', 'Psalm\\Type\\Atomic\\TClosedResource' => $baseDir . '/src/Psalm/Type/Atomic/TClosedResource.php', 'Psalm\\Type\\Atomic\\TClosure' => $baseDir . '/src/Psalm/Type/Atomic/TClosure.php', 'Psalm\\Type\\Atomic\\TConditional' => $baseDir . '/src/Psalm/Type/Atomic/TConditional.php', 'Psalm\\Type\\Atomic\\TDependentGetClass' => $baseDir . '/src/Psalm/Type/Atomic/TDependentGetClass.php', 'Psalm\\Type\\Atomic\\TDependentGetDebugType' => $baseDir . '/src/Psalm/Type/Atomic/TDependentGetDebugType.php', 'Psalm\\Type\\Atomic\\TDependentGetType' => $baseDir . '/src/Psalm/Type/Atomic/TDependentGetType.php', 'Psalm\\Type\\Atomic\\TEmpty' => $baseDir . '/src/Psalm/Type/Atomic/TEmpty.php', 'Psalm\\Type\\Atomic\\TEmptyMixed' => $baseDir . '/src/Psalm/Type/Atomic/TEmptyMixed.php', 'Psalm\\Type\\Atomic\\TEmptyNumeric' => $baseDir . '/src/Psalm/Type/Atomic/TEmptyNumeric.php', 'Psalm\\Type\\Atomic\\TEmptyScalar' => $baseDir . '/src/Psalm/Type/Atomic/TEmptyScalar.php', 'Psalm\\Type\\Atomic\\TFalse' => $baseDir . '/src/Psalm/Type/Atomic/TFalse.php', 'Psalm\\Type\\Atomic\\TFloat' => $baseDir . '/src/Psalm/Type/Atomic/TFloat.php', 'Psalm\\Type\\Atomic\\TGenericObject' => $baseDir . '/src/Psalm/Type/Atomic/TGenericObject.php', 'Psalm\\Type\\Atomic\\THtmlEscapedString' => $baseDir . '/src/Psalm/Type/Atomic/THtmlEscapedString.php', 'Psalm\\Type\\Atomic\\TInt' => $baseDir . '/src/Psalm/Type/Atomic/TInt.php', 'Psalm\\Type\\Atomic\\TIterable' => $baseDir . '/src/Psalm/Type/Atomic/TIterable.php', 'Psalm\\Type\\Atomic\\TKeyOfClassConstant' => $baseDir . '/src/Psalm/Type/Atomic/TKeyOfClassConstant.php', 'Psalm\\Type\\Atomic\\TKeyedArray' => $baseDir . '/src/Psalm/Type/Atomic/TKeyedArray.php', 'Psalm\\Type\\Atomic\\TList' => $baseDir . '/src/Psalm/Type/Atomic/TList.php', 'Psalm\\Type\\Atomic\\TLiteralClassString' => $baseDir . '/src/Psalm/Type/Atomic/TLiteralClassString.php', 'Psalm\\Type\\Atomic\\TLiteralFloat' => $baseDir . '/src/Psalm/Type/Atomic/TLiteralFloat.php', 'Psalm\\Type\\Atomic\\TLiteralInt' => $baseDir . '/src/Psalm/Type/Atomic/TLiteralInt.php', 'Psalm\\Type\\Atomic\\TLiteralString' => $baseDir . '/src/Psalm/Type/Atomic/TLiteralString.php', 'Psalm\\Type\\Atomic\\TLowercaseString' => $baseDir . '/src/Psalm/Type/Atomic/TLowercaseString.php', 'Psalm\\Type\\Atomic\\TMixed' => $baseDir . '/src/Psalm/Type/Atomic/TMixed.php', 'Psalm\\Type\\Atomic\\TNamedObject' => $baseDir . '/src/Psalm/Type/Atomic/TNamedObject.php', 'Psalm\\Type\\Atomic\\TNever' => $baseDir . '/src/Psalm/Type/Atomic/TNever.php', 'Psalm\\Type\\Atomic\\TNonEmptyArray' => $baseDir . '/src/Psalm/Type/Atomic/TNonEmptyArray.php', 'Psalm\\Type\\Atomic\\TNonEmptyList' => $baseDir . '/src/Psalm/Type/Atomic/TNonEmptyList.php', 'Psalm\\Type\\Atomic\\TNonEmptyLowercaseString' => $baseDir . '/src/Psalm/Type/Atomic/TNonEmptyLowercaseString.php', 'Psalm\\Type\\Atomic\\TNonEmptyMixed' => $baseDir . '/src/Psalm/Type/Atomic/TNonEmptyMixed.php', 'Psalm\\Type\\Atomic\\TNonEmptyScalar' => $baseDir . '/src/Psalm/Type/Atomic/TNonEmptyScalar.php', 'Psalm\\Type\\Atomic\\TNonEmptyString' => $baseDir . '/src/Psalm/Type/Atomic/TNonEmptyString.php', 'Psalm\\Type\\Atomic\\TNull' => $baseDir . '/src/Psalm/Type/Atomic/TNull.php', 'Psalm\\Type\\Atomic\\TNumeric' => $baseDir . '/src/Psalm/Type/Atomic/TNumeric.php', 'Psalm\\Type\\Atomic\\TNumericString' => $baseDir . '/src/Psalm/Type/Atomic/TNumericString.php', 'Psalm\\Type\\Atomic\\TObject' => $baseDir . '/src/Psalm/Type/Atomic/TObject.php', 'Psalm\\Type\\Atomic\\TObjectWithProperties' => $baseDir . '/src/Psalm/Type/Atomic/TObjectWithProperties.php', 'Psalm\\Type\\Atomic\\TPositiveInt' => $baseDir . '/src/Psalm/Type/Atomic/TPositiveInt.php', 'Psalm\\Type\\Atomic\\TResource' => $baseDir . '/src/Psalm/Type/Atomic/TResource.php', 'Psalm\\Type\\Atomic\\TScalar' => $baseDir . '/src/Psalm/Type/Atomic/TScalar.php', 'Psalm\\Type\\Atomic\\TScalarClassConstant' => $baseDir . '/src/Psalm/Type/Atomic/TScalarClassConstant.php', 'Psalm\\Type\\Atomic\\TSingleLetter' => $baseDir . '/src/Psalm/Type/Atomic/TSingleLetter.php', 'Psalm\\Type\\Atomic\\TString' => $baseDir . '/src/Psalm/Type/Atomic/TString.php', 'Psalm\\Type\\Atomic\\TTemplateIndexedAccess' => $baseDir . '/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php', 'Psalm\\Type\\Atomic\\TTemplateKeyOf' => $baseDir . '/src/Psalm/Type/Atomic/TTemplateKeyOf.php', 'Psalm\\Type\\Atomic\\TTemplateParam' => $baseDir . '/src/Psalm/Type/Atomic/TTemplateParam.php', 'Psalm\\Type\\Atomic\\TTemplateParamClass' => $baseDir . '/src/Psalm/Type/Atomic/TTemplateParamClass.php', 'Psalm\\Type\\Atomic\\TTraitString' => $baseDir . '/src/Psalm/Type/Atomic/TTraitString.php', 'Psalm\\Type\\Atomic\\TTrue' => $baseDir . '/src/Psalm/Type/Atomic/TTrue.php', 'Psalm\\Type\\Atomic\\TTypeAlias' => $baseDir . '/src/Psalm/Type/Atomic/TTypeAlias.php', 'Psalm\\Type\\Atomic\\TValueOfClassConstant' => $baseDir . '/src/Psalm/Type/Atomic/TValueOfClassConstant.php', 'Psalm\\Type\\Atomic\\TVoid' => $baseDir . '/src/Psalm/Type/Atomic/TVoid.php', 'Psalm\\Type\\NodeVisitor' => $baseDir . '/src/Psalm/Type/NodeVisitor.php', 'Psalm\\Type\\Reconciler' => $baseDir . '/src/Psalm/Type/Reconciler.php', 'Psalm\\Type\\TaintKind' => $baseDir . '/src/Psalm/Type/TaintKind.php', 'Psalm\\Type\\TaintKindGroup' => $baseDir . '/src/Psalm/Type/TaintKindGroup.php', 'Psalm\\Type\\TypeNode' => $baseDir . '/src/Psalm/Type/TypeNode.php', 'Psalm\\Type\\Union' => $baseDir . '/src/Psalm/Type/Union.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Dispatcher' => $vendorDir . '/felixfbecker/advanced-json-rpc/lib/Dispatcher.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Error' => $vendorDir . '/felixfbecker/advanced-json-rpc/lib/Error.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\ErrorCode' => $vendorDir . '/felixfbecker/advanced-json-rpc/lib/ErrorCode.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\ErrorResponse' => $vendorDir . '/felixfbecker/advanced-json-rpc/lib/ErrorResponse.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Message' => $vendorDir . '/felixfbecker/advanced-json-rpc/lib/Message.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Notification' => $vendorDir . '/felixfbecker/advanced-json-rpc/lib/Notification.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Request' => $vendorDir . '/felixfbecker/advanced-json-rpc/lib/Request.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Response' => $vendorDir . '/felixfbecker/advanced-json-rpc/lib/Response.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\SuccessResponse' => $vendorDir . '/felixfbecker/advanced-json-rpc/lib/SuccessResponse.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Base64\\Base64DecodingInputStream' => $vendorDir . '/amphp/byte-stream/lib/Base64/Base64DecodingInputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Base64\\Base64DecodingOutputStream' => $vendorDir . '/amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Base64\\Base64EncodingInputStream' => $vendorDir . '/amphp/byte-stream/lib/Base64/Base64EncodingInputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Base64\\Base64EncodingOutputStream' => $vendorDir . '/amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ClosedException' => $vendorDir . '/amphp/byte-stream/lib/ClosedException.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\InMemoryStream' => $vendorDir . '/amphp/byte-stream/lib/InMemoryStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\InputStream' => $vendorDir . '/amphp/byte-stream/lib/InputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\InputStreamChain' => $vendorDir . '/amphp/byte-stream/lib/InputStreamChain.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\IteratorStream' => $vendorDir . '/amphp/byte-stream/lib/IteratorStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\LineReader' => $vendorDir . '/amphp/byte-stream/lib/LineReader.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Message' => $vendorDir . '/amphp/byte-stream/lib/Message.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\OutputBuffer' => $vendorDir . '/amphp/byte-stream/lib/OutputBuffer.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\OutputStream' => $vendorDir . '/amphp/byte-stream/lib/OutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Payload' => $vendorDir . '/amphp/byte-stream/lib/Payload.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\PendingReadError' => $vendorDir . '/amphp/byte-stream/lib/PendingReadError.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ResourceInputStream' => $vendorDir . '/amphp/byte-stream/lib/ResourceInputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ResourceOutputStream' => $vendorDir . '/amphp/byte-stream/lib/ResourceOutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\StreamException' => $vendorDir . '/amphp/byte-stream/lib/StreamException.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ZlibInputStream' => $vendorDir . '/amphp/byte-stream/lib/ZlibInputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ZlibOutputStream' => $vendorDir . '/amphp/byte-stream/lib/ZlibOutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\CallableMaker' => $vendorDir . '/amphp/amp/lib/CallableMaker.php', '_HumbugBoxd02f763d3c56\\Amp\\CancellationToken' => $vendorDir . '/amphp/amp/lib/CancellationToken.php', '_HumbugBoxd02f763d3c56\\Amp\\CancellationTokenSource' => $vendorDir . '/amphp/amp/lib/CancellationTokenSource.php', '_HumbugBoxd02f763d3c56\\Amp\\CancelledException' => $vendorDir . '/amphp/amp/lib/CancelledException.php', '_HumbugBoxd02f763d3c56\\Amp\\CombinedCancellationToken' => $vendorDir . '/amphp/amp/lib/CombinedCancellationToken.php', '_HumbugBoxd02f763d3c56\\Amp\\Coroutine' => $vendorDir . '/amphp/amp/lib/Coroutine.php', '_HumbugBoxd02f763d3c56\\Amp\\Deferred' => $vendorDir . '/amphp/amp/lib/Deferred.php', '_HumbugBoxd02f763d3c56\\Amp\\Delayed' => $vendorDir . '/amphp/amp/lib/Delayed.php', '_HumbugBoxd02f763d3c56\\Amp\\Emitter' => $vendorDir . '/amphp/amp/lib/Emitter.php', '_HumbugBoxd02f763d3c56\\Amp\\Failure' => $vendorDir . '/amphp/amp/lib/Failure.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\Placeholder' => $vendorDir . '/amphp/amp/lib/Internal/Placeholder.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\PrivateIterator' => $vendorDir . '/amphp/amp/lib/Internal/PrivateIterator.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\PrivatePromise' => $vendorDir . '/amphp/amp/lib/Internal/PrivatePromise.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\Producer' => $vendorDir . '/amphp/amp/lib/Internal/Producer.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\ResolutionQueue' => $vendorDir . '/amphp/amp/lib/Internal/ResolutionQueue.php', '_HumbugBoxd02f763d3c56\\Amp\\InvalidYieldError' => $vendorDir . '/amphp/amp/lib/InvalidYieldError.php', '_HumbugBoxd02f763d3c56\\Amp\\Iterator' => $vendorDir . '/amphp/amp/lib/Iterator.php', '_HumbugBoxd02f763d3c56\\Amp\\LazyPromise' => $vendorDir . '/amphp/amp/lib/LazyPromise.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop' => $vendorDir . '/amphp/amp/lib/Loop.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\Driver' => $vendorDir . '/amphp/amp/lib/Loop/Driver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\DriverFactory' => $vendorDir . '/amphp/amp/lib/Loop/DriverFactory.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\EvDriver' => $vendorDir . '/amphp/amp/lib/Loop/EvDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\EventDriver' => $vendorDir . '/amphp/amp/lib/Loop/EventDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\Internal\\TimerQueue' => $vendorDir . '/amphp/amp/lib/Loop/Internal/TimerQueue.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\Internal\\TimerQueueEntry' => $vendorDir . '/amphp/amp/lib/Loop/Internal/TimerQueueEntry.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\InvalidWatcherError' => $vendorDir . '/amphp/amp/lib/Loop/InvalidWatcherError.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\NativeDriver' => $vendorDir . '/amphp/amp/lib/Loop/NativeDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\TracingDriver' => $vendorDir . '/amphp/amp/lib/Loop/TracingDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\UnsupportedFeatureException' => $vendorDir . '/amphp/amp/lib/Loop/UnsupportedFeatureException.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\UvDriver' => $vendorDir . '/amphp/amp/lib/Loop/UvDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\Watcher' => $vendorDir . '/amphp/amp/lib/Loop/Watcher.php', '_HumbugBoxd02f763d3c56\\Amp\\MultiReasonException' => $vendorDir . '/amphp/amp/lib/MultiReasonException.php', '_HumbugBoxd02f763d3c56\\Amp\\NullCancellationToken' => $vendorDir . '/amphp/amp/lib/NullCancellationToken.php', '_HumbugBoxd02f763d3c56\\Amp\\Producer' => $vendorDir . '/amphp/amp/lib/Producer.php', '_HumbugBoxd02f763d3c56\\Amp\\Promise' => $vendorDir . '/amphp/amp/lib/Promise.php', '_HumbugBoxd02f763d3c56\\Amp\\Struct' => $vendorDir . '/amphp/amp/lib/Struct.php', '_HumbugBoxd02f763d3c56\\Amp\\Success' => $vendorDir . '/amphp/amp/lib/Success.php', '_HumbugBoxd02f763d3c56\\Amp\\TimeoutCancellationToken' => $vendorDir . '/amphp/amp/lib/TimeoutCancellationToken.php', '_HumbugBoxd02f763d3c56\\Amp\\TimeoutException' => $vendorDir . '/amphp/amp/lib/TimeoutException.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Comparator' => $vendorDir . '/composer/semver/src/Comparator.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\CompilingMatcher' => $vendorDir . '/composer/semver/src/CompilingMatcher.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\Bound' => $vendorDir . '/composer/semver/src/Constraint/Bound.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\Constraint' => $vendorDir . '/composer/semver/src/Constraint/Constraint.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\ConstraintInterface' => $vendorDir . '/composer/semver/src/Constraint/ConstraintInterface.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\MatchAllConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchAllConstraint.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\MatchNoneConstraint' => $vendorDir . '/composer/semver/src/Constraint/MatchNoneConstraint.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\MultiConstraint' => $vendorDir . '/composer/semver/src/Constraint/MultiConstraint.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Interval' => $vendorDir . '/composer/semver/src/Interval.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Intervals' => $vendorDir . '/composer/semver/src/Intervals.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Semver' => $vendorDir . '/composer/semver/src/Semver.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\VersionParser' => $vendorDir . '/composer/semver/src/VersionParser.php', '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\PhpConfig' => $vendorDir . '/composer/xdebug-handler/src/PhpConfig.php', '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\Process' => $vendorDir . '/composer/xdebug-handler/src/Process.php', '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\Status' => $vendorDir . '/composer/xdebug-handler/src/Status.php', '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\XdebugHandler' => $vendorDir . '/composer/xdebug-handler/src/XdebugHandler.php', '_HumbugBoxd02f763d3c56\\JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', '_HumbugBoxd02f763d3c56\\LSS\\Array2XML' => $vendorDir . '/openlss/lib-array2xml/LSS/Array2XML.php', '_HumbugBoxd02f763d3c56\\LSS\\XML2Array' => $vendorDir . '/openlss/lib-array2xml/LSS/XML2Array.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ClientCapabilities' => $vendorDir . '/felixfbecker/language-server-protocol/src/ClientCapabilities.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CodeActionContext' => $vendorDir . '/felixfbecker/language-server-protocol/src/CodeActionContext.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CodeLens' => $vendorDir . '/felixfbecker/language-server-protocol/src/CodeLens.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CodeLensOptions' => $vendorDir . '/felixfbecker/language-server-protocol/src/CodeLensOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Command' => $vendorDir . '/felixfbecker/language-server-protocol/src/Command.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionContext' => $vendorDir . '/felixfbecker/language-server-protocol/src/CompletionContext.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionItem' => $vendorDir . '/felixfbecker/language-server-protocol/src/CompletionItem.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionItemKind' => $vendorDir . '/felixfbecker/language-server-protocol/src/CompletionItemKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionList' => $vendorDir . '/felixfbecker/language-server-protocol/src/CompletionList.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionOptions' => $vendorDir . '/felixfbecker/language-server-protocol/src/CompletionOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionTriggerKind' => $vendorDir . '/felixfbecker/language-server-protocol/src/CompletionTriggerKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ContentChangeEvent' => $vendorDir . '/felixfbecker/language-server-protocol/src/ContentChangeEvent.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DependencyReference' => $vendorDir . '/felixfbecker/language-server-protocol/src/DependencyReference.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Diagnostic' => $vendorDir . '/felixfbecker/language-server-protocol/src/Diagnostic.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DiagnosticSeverity' => $vendorDir . '/felixfbecker/language-server-protocol/src/DiagnosticSeverity.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DocumentHighlight' => $vendorDir . '/felixfbecker/language-server-protocol/src/DocumentHighlight.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DocumentHighlightKind' => $vendorDir . '/felixfbecker/language-server-protocol/src/DocumentHighlightKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DocumentOnTypeFormattingOptions' => $vendorDir . '/felixfbecker/language-server-protocol/src/DocumentOnTypeFormattingOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ErrorCode' => $vendorDir . '/felixfbecker/language-server-protocol/src/ErrorCode.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\FileChangeType' => $vendorDir . '/felixfbecker/language-server-protocol/src/FileChangeType.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\FileEvent' => $vendorDir . '/felixfbecker/language-server-protocol/src/FileEvent.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\FormattingOptions' => $vendorDir . '/felixfbecker/language-server-protocol/src/FormattingOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Hover' => $vendorDir . '/felixfbecker/language-server-protocol/src/Hover.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\InitializeResult' => $vendorDir . '/felixfbecker/language-server-protocol/src/InitializeResult.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\InsertTextFormat' => $vendorDir . '/felixfbecker/language-server-protocol/src/InsertTextFormat.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Location' => $vendorDir . '/felixfbecker/language-server-protocol/src/Location.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MarkedString' => $vendorDir . '/felixfbecker/language-server-protocol/src/MarkedString.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MarkupContent' => $vendorDir . '/felixfbecker/language-server-protocol/src/MarkupContent.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MarkupKind' => $vendorDir . '/felixfbecker/language-server-protocol/src/MarkupKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MessageActionItem' => $vendorDir . '/felixfbecker/language-server-protocol/src/MessageActionItem.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MessageType' => $vendorDir . '/felixfbecker/language-server-protocol/src/MessageType.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\PackageDescriptor' => $vendorDir . '/felixfbecker/language-server-protocol/src/PackageDescriptor.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ParameterInformation' => $vendorDir . '/felixfbecker/language-server-protocol/src/ParameterInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Position' => $vendorDir . '/felixfbecker/language-server-protocol/src/Position.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Range' => $vendorDir . '/felixfbecker/language-server-protocol/src/Range.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ReferenceContext' => $vendorDir . '/felixfbecker/language-server-protocol/src/ReferenceContext.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ReferenceInformation' => $vendorDir . '/felixfbecker/language-server-protocol/src/ReferenceInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SaveOptions' => $vendorDir . '/felixfbecker/language-server-protocol/src/SaveOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ServerCapabilities' => $vendorDir . '/felixfbecker/language-server-protocol/src/ServerCapabilities.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SignatureHelp' => $vendorDir . '/felixfbecker/language-server-protocol/src/SignatureHelp.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SignatureHelpOptions' => $vendorDir . '/felixfbecker/language-server-protocol/src/SignatureHelpOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SignatureInformation' => $vendorDir . '/felixfbecker/language-server-protocol/src/SignatureInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SymbolDescriptor' => $vendorDir . '/felixfbecker/language-server-protocol/src/SymbolDescriptor.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SymbolInformation' => $vendorDir . '/felixfbecker/language-server-protocol/src/SymbolInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SymbolKind' => $vendorDir . '/felixfbecker/language-server-protocol/src/SymbolKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SymbolLocationInformation' => $vendorDir . '/felixfbecker/language-server-protocol/src/SymbolLocationInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentContentChangeEvent' => $vendorDir . '/felixfbecker/language-server-protocol/src/TextDocumentContentChangeEvent.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentIdentifier' => $vendorDir . '/felixfbecker/language-server-protocol/src/TextDocumentIdentifier.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentItem' => $vendorDir . '/felixfbecker/language-server-protocol/src/TextDocumentItem.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentSyncKind' => $vendorDir . '/felixfbecker/language-server-protocol/src/TextDocumentSyncKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentSyncOptions' => $vendorDir . '/felixfbecker/language-server-protocol/src/TextDocumentSyncOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextEdit' => $vendorDir . '/felixfbecker/language-server-protocol/src/TextEdit.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\VersionedTextDocumentIdentifier' => $vendorDir . '/felixfbecker/language-server-protocol/src/VersionedTextDocumentIdentifier.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\WorkspaceEdit' => $vendorDir . '/felixfbecker/language-server-protocol/src/WorkspaceEdit.php', '_HumbugBoxd02f763d3c56\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', '_HumbugBoxd02f763d3c56\\PackageVersions\\FallbackVersions' => $vendorDir . '/composer/package-versions-deprecated/src/PackageVersions/FallbackVersions.php', '_HumbugBoxd02f763d3c56\\PackageVersions\\Installer' => $vendorDir . '/composer/package-versions-deprecated/src/PackageVersions/Installer.php', '_HumbugBoxd02f763d3c56\\PackageVersions\\Versions' => $vendorDir . '/composer/package-versions-deprecated/src/PackageVersions/Versions.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder.php', '_HumbugBoxd02f763d3c56\\PhpParser\\BuilderFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php', '_HumbugBoxd02f763d3c56\\PhpParser\\BuilderHelpers' => $vendorDir . '/nikic/php-parser/lib/PhpParser/BuilderHelpers.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Declaration' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Interface_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Method' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Method.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Param' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Param.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Property' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Property.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\TraitUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\TraitUseAdaptation' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Trait_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Use_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Builder/Use_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Comment' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Comment.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Comment\\Doc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Comment/Doc.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ConstExprEvaluationException' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ConstExprEvaluator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Error' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Error.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ErrorHandler' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ErrorHandler\\Collecting' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ErrorHandler\\Throwing' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Internal\\DiffElem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Internal\\Differ' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/Differ.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Internal\\PrintableNewAnonClassNode' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Internal\\TokenStream' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php', '_HumbugBoxd02f763d3c56\\PhpParser\\JsonDecoder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/JsonDecoder.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\Emulative' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\CoaleseEqualTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\FlexibleDocStringEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\FnTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\NumericLiteralSeparatorEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NameContext' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NameContext.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeAbstract.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeDumper' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeDumper.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeFinder' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeFinder.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeTraverser' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeTraverser.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeTraverserInterface' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitorAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\CloningVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\FindingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\FirstFindingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\NameResolver' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\NodeConnectingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\ParentConnectingVisitor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Arg' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Arg.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Attribute' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Attribute.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\AttributeGroup' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Const_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Const_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ArrayDimFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ArrayItem' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Array_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ArrowFunction' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Assign' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Div' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignRef' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BitwiseNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BooleanNot' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Array_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Bool_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Double' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Int_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Object_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\String_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Unset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ClassConstFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Clone_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Closure' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ClosureUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ConstFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Empty_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Error' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ErrorSuppress' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Eval_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Exit_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\FuncCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Include_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Instanceof_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Isset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\List_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Match_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\MethodCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\New_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\NullsafeMethodCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\NullsafePropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PostDec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PostInc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PreDec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PreInc' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Print_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ShellExec' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\StaticCall' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Ternary' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Throw_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\UnaryMinus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\UnaryPlus' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Variable' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\YieldFrom' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Yield_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\FunctionLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Identifier' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Identifier.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\MatchArm' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/MatchArm.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Name' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Name\\FullyQualified' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Name\\Relative' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\NullableType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/NullableType.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Param' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Param.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\DNumber' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\Encapsed' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\EncapsedStringPart' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\LNumber' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\File' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\String_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Break_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Case_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Catch_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\ClassConst' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\ClassLike' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\ClassMethod' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Class_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Const_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Continue_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\DeclareDeclare' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Declare_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Do_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Echo_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\ElseIf_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Else_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Expression' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Finally_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\For_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Foreach_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Function_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Global_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Goto_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\GroupUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\HaltCompiler' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\If_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\InlineHTML' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Interface_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Label' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Namespace_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Nop' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Property' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\PropertyProperty' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Return_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\StaticVar' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Static_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Switch_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Throw_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TraitUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TraitUseAdaptation' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Trait_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TryCatch' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Unset_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\UseUse' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Use_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\While_' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\UnionType' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/UnionType.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\VarLikeIdentifier' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ParserAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ParserFactory' => $vendorDir . '/nikic/php-parser/lib/PhpParser/ParserFactory.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser\\Multiple' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Multiple.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser\\Php5' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Php5.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser\\Php7' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Php7.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser\\Tokens' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Tokens.php', '_HumbugBoxd02f763d3c56\\PhpParser\\PrettyPrinterAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php', '_HumbugBoxd02f763d3c56\\PhpParser\\PrettyPrinter\\Standard' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php', '_HumbugBoxd02f763d3c56\\Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareTrait.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\ConfigurationException' => $vendorDir . '/sebastian/diff/src/Exception/ConfigurationException.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Exception' => $vendorDir . '/sebastian/diff/src/Exception/Exception.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\InvalidArgumentException' => $vendorDir . '/sebastian/diff/src/Exception/InvalidArgumentException.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', '_HumbugBoxd02f763d3c56\\Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/FactoryCommandLoader.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Command/Command.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Command/HelpCommand.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Command/ListCommand.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Command\\LockableTrait' => $vendorDir . '/symfony/console/Command/LockableTrait.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/ConsoleEvents.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Cursor' => $vendorDir . '/symfony/console/Cursor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => $vendorDir . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Descriptor/ApplicationDescription.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Descriptor/Descriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Descriptor/DescriptorInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Descriptor/JsonDescriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Descriptor/MarkdownDescriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Descriptor/TextDescriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Descriptor/XmlDescriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => $vendorDir . '/symfony/console/EventListener/ErrorListener.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Event/ConsoleCommandEvent.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => $vendorDir . '/symfony/console/Event/ConsoleErrorEvent.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Event/ConsoleEvent.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Event/ConsoleTerminateEvent.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => $vendorDir . '/symfony/console/Exception/CommandNotFoundException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/console/Exception/ExceptionInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/console/Exception/InvalidArgumentException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/symfony/console/Exception/InvalidOptionException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/symfony/console/Exception/LogicException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\MissingInputException' => $vendorDir . '/symfony/console/Exception/MissingInputException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => $vendorDir . '/symfony/console/Exception/NamespaceNotFoundException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/symfony/console/Exception/RuntimeException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatter.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatterStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Formatter/OutputFormatter.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleStack.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\Dumper' => $vendorDir . '/symfony/console/Helper/Dumper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Helper/HelperSet.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Helper/InputAwareHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Helper/ProcessHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Helper/ProgressBar.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/symfony/console/Helper/ProgressIndicator.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Helper/QuestionHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/symfony/console/Helper/SymfonyQuestionHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Helper/Table.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/symfony/console/Helper/TableCell.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\TableRows' => $vendorDir . '/symfony/console/Helper/TableRows.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Input/InputArgument.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Input/InputAwareInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Input/InputDefinition.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Input/InputInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Input/InputOption.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => $vendorDir . '/symfony/console/Input/StreamableInputInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Input/StringInput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Logger/ConsoleLogger.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Output/BufferedOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Output/ConsoleOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Output/ConsoleOutputInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => $vendorDir . '/symfony/console/Output/ConsoleSectionOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Output/NullOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Output/Output.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Output/OutputInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Output/StreamOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\SingleCommandApplication' => $vendorDir . '/symfony/console/SingleCommandApplication.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/symfony/console/Style/OutputStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/symfony/console/Style/StyleInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/symfony/console/Style/SymfonyStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Terminal' => $vendorDir . '/symfony/console/Terminal.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Tester\\TesterTrait' => $vendorDir . '/symfony/console/Tester/TesterTrait.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\AbstractString' => $vendorDir . '/symfony/string/AbstractString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\AbstractUnicodeString' => $vendorDir . '/symfony/string/AbstractUnicodeString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\ByteString' => $vendorDir . '/symfony/string/ByteString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\CodePointString' => $vendorDir . '/symfony/string/CodePointString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/string/Exception/ExceptionInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/string/Exception/InvalidArgumentException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Exception\\RuntimeException' => $vendorDir . '/symfony/string/Exception/RuntimeException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => $vendorDir . '/symfony/string/Inflector/EnglishInflector.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => $vendorDir . '/symfony/string/Inflector/InflectorInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\LazyString' => $vendorDir . '/symfony/string/LazyString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => $vendorDir . '/symfony/string/Slugger/AsciiSlugger.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => $vendorDir . '/symfony/string/Slugger/SluggerInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\UnicodeString' => $vendorDir . '/symfony/string/UnicodeString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/symfony/polyfill-ctype/Ctype.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => $vendorDir . '/symfony/polyfill-intl-grapheme/Grapheme.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php73\\Php73' => $vendorDir . '/symfony/polyfill-php73/Php73.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php', '_HumbugBoxd02f763d3c56\\UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', '_HumbugBoxd02f763d3c56\\ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Assert\\Assert' => $vendorDir . '/webmozart/assert/src/Assert.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Assert\\Mixin' => $vendorDir . '/webmozart/assert/src/Mixin.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Glob' => $vendorDir . '/webmozart/glob/src/Glob.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Iterator\\GlobFilterIterator' => $vendorDir . '/webmozart/glob/src/Iterator/GlobFilterIterator.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Iterator\\GlobIterator' => $vendorDir . '/webmozart/glob/src/Iterator/GlobIterator.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/webmozart/glob/src/Iterator/RecursiveDirectoryIterator.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Iterator\\RegexFilterIterator' => $vendorDir . '/webmozart/glob/src/Iterator/RegexFilterIterator.php', '_HumbugBoxd02f763d3c56\\Webmozart\\PathUtil\\Path' => $vendorDir . '/webmozart/path-util/src/Path.php', '_HumbugBoxd02f763d3c56\\Webmozart\\PathUtil\\Url' => $vendorDir . '/webmozart/path-util/src/Url.php', '_HumbugBoxd02f763d3c56\\XdgBaseDir\\Xdg' => $vendorDir . '/dnoegel/php-xdg-base-dir/src/Xdg.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlockFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlockFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlockFactoryInterface' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Description' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Description.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\ExampleFinder' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Serializer' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\StandardTagFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\TagFactory' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Author' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\BaseTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Covers' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Deprecated' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Example' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\StaticMethod' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\AlignFormatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\PassthroughFormatter' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Generic' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\InvalidTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Link' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Method' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Param' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Property' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyRead' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyWrite' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Fqsen' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Reference' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Url' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Return_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\See' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Since' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Source' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TagWithType' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Throws' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Uses' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Var_' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Version' => $vendorDir . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Element' => $vendorDir . '/phpdocumentor/reflection-common/src/Element.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Exception\\PcreException' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Exception/PcreException.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\File' => $vendorDir . '/phpdocumentor/reflection-common/src/File.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Fqsen' => $vendorDir . '/phpdocumentor/reflection-common/src/Fqsen.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\FqsenResolver' => $vendorDir . '/phpdocumentor/type-resolver/src/FqsenResolver.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Location' => $vendorDir . '/phpdocumentor/reflection-common/src/Location.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Project' => $vendorDir . '/phpdocumentor/reflection-common/src/Project.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\ProjectFactory' => $vendorDir . '/phpdocumentor/reflection-common/src/ProjectFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\PseudoType' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoType.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\PseudoTypes\\False_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/False_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\PseudoTypes\\True_' => $vendorDir . '/phpdocumentor/type-resolver/src/PseudoTypes/True_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Type' => $vendorDir . '/phpdocumentor/type-resolver/src/Type.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\TypeResolver' => $vendorDir . '/phpdocumentor/type-resolver/src/TypeResolver.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\AbstractList' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/AbstractList.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\AggregatedType' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/AggregatedType.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Array_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Array_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Boolean' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Boolean.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Callable_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Callable_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\ClassString' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/ClassString.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Collection' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Collection.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Compound' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Compound.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Context' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Context.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\ContextFactory' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/ContextFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Expression' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Expression.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Float_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Float_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Integer' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Integer.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Intersection' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Intersection.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Iterable_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Iterable_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Mixed_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Mixed_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Null_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Null_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Nullable' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Nullable.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Object_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Object_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Parent_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Parent_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Resource_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Resource_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Scalar' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Scalar.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Self_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Self_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Static_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Static_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\String_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/String_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\This' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/This.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Void_' => $vendorDir . '/phpdocumentor/type-resolver/src/Types/Void_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Utils' => $vendorDir . '/phpdocumentor/reflection-docblock/src/Utils.php', ); * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\XdebugHandler; use _HumbugBoxd02f763d3c56\Psr\Log\LoggerInterface; use _HumbugBoxd02f763d3c56\Psr\Log\LogLevel; /** * @author John Stevenson * @internal */ class Status { const ENV_RESTART = 'XDEBUG_HANDLER_RESTART'; const CHECK = 'Check'; const ERROR = 'Error'; const INFO = 'Info'; const NORESTART = 'NoRestart'; const RESTART = 'Restart'; const RESTARTING = 'Restarting'; const RESTARTED = 'Restarted'; private $debug; private $envAllowXdebug; private $loaded; private $logger; private $time; /** * Constructor * * @param string $envAllowXdebug Prefixed _ALLOW_XDEBUG name * @param bool $debug Whether debug output is required */ public function __construct($envAllowXdebug, $debug) { $start = \getenv(self::ENV_RESTART); \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::setEnv(self::ENV_RESTART); $this->time = $start ? \round((\microtime(\true) - $start) * 1000) : 0; $this->envAllowXdebug = $envAllowXdebug; $this->debug = $debug && \defined('STDERR'); } /** * @param LoggerInterface $logger */ public function setLogger(\_HumbugBoxd02f763d3c56\Psr\Log\LoggerInterface $logger) { $this->logger = $logger; } /** * Calls a handler method to report a message * * @param string $op The handler constant * @param null|string $data Data required by the handler */ public function report($op, $data) { if ($this->logger || $this->debug) { \call_user_func(array($this, 'report' . $op), $data); } } /** * Outputs a status message * * @param string $text * @param string $level */ private function output($text, $level = null) { if ($this->logger) { $this->logger->log($level ?: \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::DEBUG, $text); } if ($this->debug) { \fwrite(\STDERR, \sprintf('xdebug-handler[%d] %s', \getmypid(), $text . \PHP_EOL)); } } private function reportCheck($loaded) { $this->loaded = $loaded; $this->output('Checking ' . $this->envAllowXdebug); } private function reportError($error) { $this->output(\sprintf('No restart (%s)', $error), \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::WARNING); } private function reportInfo($info) { $this->output($info); } private function reportNoRestart() { $this->output($this->getLoadedMessage()); if ($this->loaded) { $text = \sprintf('No restart (%s)', $this->getEnvAllow()); if (!\getenv($this->envAllowXdebug)) { $text .= ' Allowed by application'; } $this->output($text); } } private function reportRestart() { $this->output($this->getLoadedMessage()); \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::setEnv(self::ENV_RESTART, (string) \microtime(\true)); } private function reportRestarted() { $loaded = $this->getLoadedMessage(); $text = \sprintf('Restarted (%d ms). %s', $this->time, $loaded); $level = $this->loaded ? \_HumbugBoxd02f763d3c56\Psr\Log\LogLevel::WARNING : null; $this->output($text, $level); } private function reportRestarting($command) { $text = \sprintf('Process restarting (%s)', $this->getEnvAllow()); $this->output($text); $text = 'Running ' . $command; $this->output($text); } /** * Returns the _ALLOW_XDEBUG environment variable as name=value * * @return string */ private function getEnvAllow() { return $this->envAllowXdebug . '=' . \getenv($this->envAllowXdebug); } /** * Returns the Xdebug status and version * * @return string */ private function getLoadedMessage() { $loaded = $this->loaded ? \sprintf('loaded (%s)', $this->loaded) : 'not loaded'; return 'The Xdebug extension is ' . $loaded; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\XdebugHandler; /** * @author John Stevenson */ class PhpConfig { /** * Use the original PHP configuration * * @return array PHP cli options */ public function useOriginal() { $this->getDataAndReset(); return array(); } /** * Use standard restart settings * * @return array PHP cli options */ public function useStandard() { if ($data = $this->getDataAndReset()) { return array('-n', '-c', $data['tmpIni']); } return array(); } /** * Use environment variables to persist settings * * @return array PHP cli options */ public function usePersistent() { if ($data = $this->getDataAndReset()) { \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::setEnv('PHPRC', $data['tmpIni']); \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::setEnv('PHP_INI_SCAN_DIR', ''); } return array(); } /** * Returns restart data if available and resets the environment * * @return array|null */ private function getDataAndReset() { if ($data = \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\XdebugHandler::getRestartSettings()) { \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::setEnv('PHPRC', $data['phprc']); \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::setEnv('PHP_INI_SCAN_DIR', $data['scanDir']); } return $data; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\XdebugHandler; use _HumbugBoxd02f763d3c56\Psr\Log\LoggerInterface; /** * @author John Stevenson */ class XdebugHandler { const SUFFIX_ALLOW = '_ALLOW_XDEBUG'; const SUFFIX_INIS = '_ORIGINAL_INIS'; const RESTART_ID = 'internal'; const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS'; const DEBUG = 'XDEBUG_HANDLER_DEBUG'; /** @var string|null */ protected $tmpIni; private static $inRestart; private static $name; private static $skipped; private $cli; private $colorOption; private $debug; private $envAllowXdebug; private $envOriginalInis; private $loaded; private $persistent; private $script; /** @var Status|null */ private $statusWriter; /** * Constructor * * The $envPrefix is used to create distinct environment variables. It is * uppercased and prepended to the default base values. For example 'myapp' * would result in MYAPP_ALLOW_XDEBUG and MYAPP_ORIGINAL_INIS. * * @param string $envPrefix Value used in environment variables * @param string $colorOption Command-line long option to force color output * @throws \RuntimeException If a parameter is invalid */ public function __construct($envPrefix, $colorOption = '') { if (!\is_string($envPrefix) || empty($envPrefix) || !\is_string($colorOption)) { throw new \RuntimeException('Invalid constructor parameter'); } self::$name = \strtoupper($envPrefix); $this->envAllowXdebug = self::$name . self::SUFFIX_ALLOW; $this->envOriginalInis = self::$name . self::SUFFIX_INIS; $this->colorOption = $colorOption; if (\extension_loaded('xdebug')) { $ext = new \ReflectionExtension('xdebug'); $this->loaded = $ext->getVersion() ?: 'unknown'; } if ($this->cli = \PHP_SAPI === 'cli') { $this->debug = \getenv(self::DEBUG); } $this->statusWriter = new \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status($this->envAllowXdebug, (bool) $this->debug); } /** * Activates status message output to a PSR3 logger * * @param LoggerInterface $logger * * @return $this */ public function setLogger(\_HumbugBoxd02f763d3c56\Psr\Log\LoggerInterface $logger) { $this->statusWriter->setLogger($logger); return $this; } /** * Sets the main script location if it cannot be called from argv * * @param string $script * * @return $this */ public function setMainScript($script) { $this->script = $script; return $this; } /** * Persist the settings to keep Xdebug out of sub-processes * * @return $this */ public function setPersistent() { $this->persistent = \true; return $this; } /** * Checks if Xdebug is loaded and the process needs to be restarted * * This behaviour can be disabled by setting the MYAPP_ALLOW_XDEBUG * environment variable to 1. This variable is used internally so that * the restarted process is created only once. */ public function check() { $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::CHECK, $this->loaded); $envArgs = \explode('|', (string) \getenv($this->envAllowXdebug)); if (empty($envArgs[0]) && $this->requiresRestart((bool) $this->loaded)) { // Restart required $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::RESTART); if ($this->prepareRestart()) { $command = $this->getCommand(); $this->restart($command); } return; } if (self::RESTART_ID === $envArgs[0] && \count($envArgs) === 5) { // Restarted, so unset environment variable and use saved values $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::RESTARTED); \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::setEnv($this->envAllowXdebug); self::$inRestart = \true; if (!$this->loaded) { // Skipped version is only set if Xdebug is not loaded self::$skipped = $envArgs[1]; } $this->tryEnableSignals(); // Put restart settings in the environment $this->setEnvRestartSettings($envArgs); return; } $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::NORESTART); if ($settings = self::getRestartSettings()) { // Called with existing settings, so sync our settings $this->syncSettings($settings); } } /** * Returns an array of php.ini locations with at least one entry * * The equivalent of calling php_ini_loaded_file then php_ini_scanned_files. * The loaded ini location is the first entry and may be empty. * * @return array */ public static function getAllIniFiles() { if (!empty(self::$name)) { $env = \getenv(self::$name . self::SUFFIX_INIS); if (\false !== $env) { return \explode(\PATH_SEPARATOR, $env); } } $paths = array((string) \php_ini_loaded_file()); if ($scanned = \php_ini_scanned_files()) { $paths = \array_merge($paths, \array_map('trim', \explode(',', $scanned))); } return $paths; } /** * Returns an array of restart settings or null * * Settings will be available if the current process was restarted, or * called with the settings from an existing restart. * * @return array|null */ public static function getRestartSettings() { $envArgs = \explode('|', (string) \getenv(self::RESTART_SETTINGS)); if (\count($envArgs) !== 6 || !self::$inRestart && \php_ini_loaded_file() !== $envArgs[0]) { return; } return array('tmpIni' => $envArgs[0], 'scannedInis' => (bool) $envArgs[1], 'scanDir' => '*' === $envArgs[2] ? \false : $envArgs[2], 'phprc' => '*' === $envArgs[3] ? \false : $envArgs[3], 'inis' => \explode(\PATH_SEPARATOR, $envArgs[4]), 'skipped' => $envArgs[5]); } /** * Returns the Xdebug version that triggered a successful restart * * @return string */ public static function getSkippedVersion() { return (string) self::$skipped; } /** * Returns true if Xdebug is loaded, or as directed by an extending class * * @param bool $isLoaded Whether Xdebug is loaded * * @return bool */ protected function requiresRestart($isLoaded) { return $isLoaded; } /** * Allows an extending class to access the tmpIni * * @param string $command */ protected function restart($command) { $this->doRestart($command); } /** * Executes the restarted command then deletes the tmp ini * * @param string $command */ private function doRestart($command) { $this->tryEnableSignals(); $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::RESTARTING, $command); \passthru($command, $exitCode); $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::INFO, 'Restarted process exited ' . $exitCode); if ($this->debug === '2') { $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::INFO, 'Temp ini saved: ' . $this->tmpIni); } else { @\unlink($this->tmpIni); } exit($exitCode); } /** * Returns true if everything was written for the restart * * If any of the following fails (however unlikely) we must return false to * stop potential recursion: * - tmp ini file creation * - environment variable creation * * @return bool */ private function prepareRestart() { $error = ''; $iniFiles = self::getAllIniFiles(); $scannedInis = \count($iniFiles) > 1; $tmpDir = \sys_get_temp_dir(); if (!$this->cli) { $error = 'Unsupported SAPI: ' . \PHP_SAPI; } elseif (!\defined('PHP_BINARY')) { $error = 'PHP version is too old: ' . \PHP_VERSION; } elseif (!$this->checkConfiguration($info)) { $error = $info; } elseif (!$this->checkScanDirConfig()) { $error = 'PHP version does not report scanned inis: ' . \PHP_VERSION; } elseif (!$this->checkMainScript()) { $error = 'Unable to access main script: ' . $this->script; } elseif (!$this->writeTmpIni($iniFiles, $tmpDir, $error)) { $error = $error ?: 'Unable to create temp ini file at: ' . $tmpDir; } elseif (!$this->setEnvironment($scannedInis, $iniFiles)) { $error = 'Unable to set environment variables'; } if ($error) { $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::ERROR, $error); } return empty($error); } /** * Returns true if the tmp ini file was written * * @param array $iniFiles All ini files used in the current process * @param string $tmpDir The system temporary directory * @param string $error Set by method if ini file cannot be read * * @return bool */ private function writeTmpIni(array $iniFiles, $tmpDir, &$error) { if (!($this->tmpIni = @\tempnam($tmpDir, ''))) { return \false; } // $iniFiles has at least one item and it may be empty if (empty($iniFiles[0])) { \array_shift($iniFiles); } $content = ''; $regex = '/^\\s*(zend_extension\\s*=.*xdebug.*)$/mi'; foreach ($iniFiles as $file) { // Check for inaccessible ini files if (($data = @\file_get_contents($file)) === \false) { $error = 'Unable to read ini: ' . $file; return \false; } $content .= \preg_replace($regex, ';$1', $data) . \PHP_EOL; } // Merge loaded settings into our ini content, if it is valid if ($config = \parse_ini_string($content)) { $loaded = \ini_get_all(null, \false); $content .= $this->mergeLoadedConfig($loaded, $config); } // Work-around for https://bugs.php.net/bug.php?id=75932 $content .= 'opcache.enable_cli=0' . \PHP_EOL; return @\file_put_contents($this->tmpIni, $content); } /** * Returns the restart command line * * @return string */ private function getCommand() { $php = array(\PHP_BINARY); $args = \array_slice($_SERVER['argv'], 1); if (!$this->persistent) { // Use command-line options \array_push($php, '-n', '-c', $this->tmpIni); } if (\defined('STDOUT') && \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::supportsColor(\STDOUT)) { $args = \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::addColorOption($args, $this->colorOption); } $args = \array_merge($php, array($this->script), $args); $cmd = \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::escape(\array_shift($args), \true, \true); foreach ($args as $arg) { $cmd .= ' ' . \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::escape($arg); } return $cmd; } /** * Returns true if the restart environment variables were set * * No need to update $_SERVER since this is set in the restarted process. * * @param bool $scannedInis Whether there were scanned ini files * @param array $iniFiles All ini files used in the current process * * @return bool */ private function setEnvironment($scannedInis, array $iniFiles) { $scanDir = \getenv('PHP_INI_SCAN_DIR'); $phprc = \getenv('PHPRC'); // Make original inis available to restarted process if (!\putenv($this->envOriginalInis . '=' . \implode(\PATH_SEPARATOR, $iniFiles))) { return \false; } if ($this->persistent) { // Use the environment to persist the settings if (!\putenv('PHP_INI_SCAN_DIR=') || !\putenv('PHPRC=' . $this->tmpIni)) { return \false; } } // Flag restarted process and save values for it to use $envArgs = array(self::RESTART_ID, $this->loaded, (int) $scannedInis, \false === $scanDir ? '*' : $scanDir, \false === $phprc ? '*' : $phprc); return \putenv($this->envAllowXdebug . '=' . \implode('|', $envArgs)); } /** * Logs status messages * * @param string $op Status handler constant * @param null|string $data Optional data */ private function notify($op, $data = null) { $this->statusWriter->report($op, $data); } /** * Returns default, changed and command-line ini settings * * @param array $loadedConfig All current ini settings * @param array $iniConfig Settings from user ini files * * @return string */ private function mergeLoadedConfig(array $loadedConfig, array $iniConfig) { $content = ''; foreach ($loadedConfig as $name => $value) { // Value will either be null, string or array (HHVM only) if (!\is_string($value) || \strpos($name, 'xdebug') === 0 || $name === 'apc.mmap_file_mask') { continue; } if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) { // Double-quote escape each value $content .= $name . '="' . \addcslashes($value, '\\"') . '"' . \PHP_EOL; } } return $content; } /** * Returns true if the script name can be used * * @return bool */ private function checkMainScript() { if (null !== $this->script) { // Allow an application to set -- for standard input return \file_exists($this->script) || '--' === $this->script; } if (\file_exists($this->script = $_SERVER['argv'][0])) { return \true; } // Use a backtrace to resolve Phar and chdir issues $options = \PHP_VERSION_ID >= 50306 ? \DEBUG_BACKTRACE_IGNORE_ARGS : \false; $trace = \debug_backtrace($options); if (($main = \end($trace)) && isset($main['file'])) { return \file_exists($this->script = $main['file']); } return \false; } /** * Adds restart settings to the environment * * @param string $envArgs */ private function setEnvRestartSettings($envArgs) { $settings = array(\php_ini_loaded_file(), $envArgs[2], $envArgs[3], $envArgs[4], \getenv($this->envOriginalInis), self::$skipped); \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::setEnv(self::RESTART_SETTINGS, \implode('|', $settings)); } /** * Syncs settings and the environment if called with existing settings * * @param array $settings */ private function syncSettings(array $settings) { if (\false === \getenv($this->envOriginalInis)) { // Called by another app, so make original inis available \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Process::setEnv($this->envOriginalInis, \implode(\PATH_SEPARATOR, $settings['inis'])); } self::$skipped = $settings['skipped']; $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::INFO, 'Process called with existing restart settings'); } /** * Returns true if there are scanned inis and PHP is able to report them * * php_ini_scanned_files will fail when PHP_CONFIG_FILE_SCAN_DIR is empty. * Fixed in 7.1.13 and 7.2.1 * * @return bool */ private function checkScanDirConfig() { return !(\getenv('PHP_INI_SCAN_DIR') && !\PHP_CONFIG_FILE_SCAN_DIR && (\PHP_VERSION_ID < 70113 || \PHP_VERSION_ID === 70200)); } /** * Returns true if there are no known configuration issues * * @param string $info Set by method */ private function checkConfiguration(&$info) { if (\false !== \strpos(\ini_get('disable_functions'), 'passthru')) { $info = 'passthru function is disabled'; return \false; } if (\extension_loaded('uopz') && !\ini_get('uopz.disable')) { // uopz works at opcode level and disables exit calls if (\function_exists('uopz_allow_exit')) { @\uopz_allow_exit(\true); } else { $info = 'uopz extension is not compatible'; return \false; } } return \true; } /** * Enables async signals and control interrupts in the restarted process * * Only available on Unix PHP 7.1+ with the pcntl extension. To replicate on * Windows would require PHP 7.4+ using proc_open rather than passthru. */ private function tryEnableSignals() { if (!\function_exists('pcntl_async_signals')) { return; } \pcntl_async_signals(\true); $message = 'Async signals enabled'; if (!self::$inRestart) { // Restarting, so ignore SIGINT in parent \pcntl_signal(\SIGINT, \SIG_IGN); $message .= ' (SIGINT = SIG_IGN)'; } elseif (\is_int(\pcntl_signal_get_handler(\SIGINT))) { // Restarted, no handler set so force default action \pcntl_signal(\SIGINT, \SIG_DFL); $message .= ' (SIGINT = SIG_DFL)'; } $this->notify(\_HumbugBoxd02f763d3c56\Composer\XdebugHandler\Status::INFO, $message); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\XdebugHandler; /** * Provides utility functions to prepare a child process command-line and set * environment variables in that process. * * @author John Stevenson * @internal */ class Process { /** * Returns an array of parameters, including a color option if required * * A color option is needed because child process output is piped. * * @param array $args The script parameters * @param string $colorOption The long option to force color output * * @return array */ public static function addColorOption(array $args, $colorOption) { if (!$colorOption || \in_array($colorOption, $args) || !\preg_match('/^--([a-z]+$)|(^--[a-z]+=)/', $colorOption, $matches)) { return $args; } if (isset($matches[2])) { // Handle --color(s)= options if (\false !== ($index = \array_search($matches[2] . 'auto', $args))) { $args[$index] = $colorOption; return $args; } elseif (\preg_grep('/^' . $matches[2] . '/', $args)) { return $args; } } elseif (\in_array('--no-' . $matches[1], $args)) { return $args; } // Check for NO_COLOR variable (https://no-color.org/) if (\false !== \getenv('NO_COLOR')) { return $args; } if (\false !== ($index = \array_search('--', $args))) { // Position option before double-dash delimiter \array_splice($args, $index, 0, $colorOption); } else { $args[] = $colorOption; } return $args; } /** * Escapes a string to be used as a shell argument. * * From https://github.com/johnstevenson/winbox-args * MIT Licensed (c) John Stevenson * * @param string $arg The argument to be escaped * @param bool $meta Additionally escape cmd.exe meta characters * @param bool $module The argument is the module to invoke * * @return string The escaped argument */ public static function escape($arg, $meta = \true, $module = \false) { if (!\defined('PHP_WINDOWS_VERSION_BUILD')) { return "'" . \str_replace("'", "'\\''", $arg) . "'"; } $quote = \strpbrk($arg, " \t") !== \false || $arg === ''; $arg = \preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes); if ($meta) { $meta = $dquotes || \preg_match('/%[^%]+%/', $arg); if (!$meta) { $quote = $quote || \strpbrk($arg, '^&|<>()') !== \false; } elseif ($module && !$dquotes && $quote) { $meta = \false; } } if ($quote) { $arg = '"' . \preg_replace('/(\\\\*)$/', '$1$1', $arg) . '"'; } if ($meta) { $arg = \preg_replace('/(["^&|<>()%])/', '^$1', $arg); } return $arg; } /** * Returns true if the output stream supports colors * * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo * terminals via named pipes, so we can only check the environment. * * @param mixed $output A valid CLI output stream * * @return bool */ public static function supportsColor($output) { if ('Hyper' === \getenv('TERM_PROGRAM')) { return \true; } if (\defined('PHP_WINDOWS_VERSION_BUILD')) { return \function_exists('sapi_windows_vt100_support') && \sapi_windows_vt100_support($output) || \false !== \getenv('ANSICON') || 'ON' === \getenv('ConEmuANSI') || 'xterm' === \getenv('TERM'); } if (\function_exists('stream_isatty')) { return \stream_isatty($output); } if (\function_exists('posix_isatty')) { return \posix_isatty($output); } $stat = \fstat($output); // Check if formatted mode is S_IFCHR return $stat ? 020000 === ($stat['mode'] & 0170000) : \false; } /** * Makes putenv environment changes available in $_SERVER and $_ENV * * @param string $name * @param string|false $value A false value unsets the variable * * @return bool Whether the environment variable was set */ public static function setEnv($name, $value = \false) { $unset = \false === $value; if (!\putenv($unset ? $name : $name . '=' . $value)) { return \false; } if ($unset) { unset($_SERVER[$name]); } else { $_SERVER[$name] = $value; } // Update $_ENV if it is being used if (\false !== \stripos((string) \ini_get('variables_order'), 'E')) { if ($unset) { unset($_ENV[$name]); } else { $_ENV[$name] = $value; } } return \true; } } MIT License Copyright (c) 2017 Composer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'e8aa6e4b5a1db2f56ae794f1505391a8' => __DIR__ . '/..' . '/amphp/amp/lib/functions.php', '76cd0796156622033397994f25b0d8fc' => __DIR__ . '/..' . '/amphp/amp/lib/Internal/functions.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', '6cd5651c4fef5ed6b63e8d8b8ffbf3cc' => __DIR__ . '/..' . '/amphp/byte-stream/lib/functions.php', 'dc51568953534d6c54b08731e61104e2' => __DIR__ . '/../..' . '/src/functions.php', '8e4171839e12546525126d38dac3dafa' => __DIR__ . '/../..' . '/src/spl_object_id.php', ); public static $prefixLengthsPsr4 = array ( '_' => array ( '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\' => 48, '_HumbugBoxd02f763d3c56\\XdgBaseDir\\' => 34, '_HumbugBoxd02f763d3c56\\Webmozart\\PathUtil\\' => 42, '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\' => 38, '_HumbugBoxd02f763d3c56\\Webmozart\\Assert\\' => 40, '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php80\\' => 46, '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php73\\' => 46, '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Mbstring\\' => 49, '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Normalizer\\' => 56, '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Grapheme\\' => 54, '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Ctype\\' => 46, '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\' => 49, '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\' => 48, '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\' => 49, '_HumbugBoxd02f763d3c56\\Psr\\Log\\' => 31, '_HumbugBoxd02f763d3c56\\Psr\\Container\\' => 37, '_HumbugBoxd02f763d3c56\\PhpParser\\' => 33, '_HumbugBoxd02f763d3c56\\PackageVersions\\' => 39, '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\' => 46, '_HumbugBoxd02f763d3c56\\LSS\\' => 27, '_HumbugBoxd02f763d3c56\\JsonMapper\\' => 34, '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\' => 46, '_HumbugBoxd02f763d3c56\\Composer\\Semver\\' => 39, '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\' => 38, '_HumbugBoxd02f763d3c56\\Amp\\' => 27, '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\' => 39, ), 'P' => array ( 'Psalm\\' => 6, ), ); public static $prefixDirsPsr4 = array ( '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\' => array ( 0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src', 1 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', 2 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', ), '_HumbugBoxd02f763d3c56\\XdgBaseDir\\' => array ( 0 => __DIR__ . '/..' . '/dnoegel/php-xdg-base-dir/src', ), '_HumbugBoxd02f763d3c56\\Webmozart\\PathUtil\\' => array ( 0 => __DIR__ . '/..' . '/webmozart/path-util/src', ), '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\' => array ( 0 => __DIR__ . '/..' . '/webmozart/glob/src', ), '_HumbugBoxd02f763d3c56\\Webmozart\\Assert\\' => array ( 0 => __DIR__ . '/..' . '/webmozart/assert/src', ), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php80\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', ), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php73\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', ), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Mbstring\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', ), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Normalizer\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer', ), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Grapheme\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme', ), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Ctype\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', ), '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\' => array ( 0 => __DIR__ . '/..' . '/symfony/service-contracts', ), '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\' => array ( 0 => __DIR__ . '/..' . '/symfony/string', ), '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\' => array ( 0 => __DIR__ . '/..' . '/symfony/console', ), '_HumbugBoxd02f763d3c56\\Psr\\Log\\' => array ( 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', ), '_HumbugBoxd02f763d3c56\\Psr\\Container\\' => array ( 0 => __DIR__ . '/..' . '/psr/container/src', ), '_HumbugBoxd02f763d3c56\\PhpParser\\' => array ( 0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser', ), '_HumbugBoxd02f763d3c56\\PackageVersions\\' => array ( 0 => __DIR__ . '/..' . '/composer/package-versions-deprecated/src/PackageVersions', ), '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\' => array ( 0 => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src', ), '_HumbugBoxd02f763d3c56\\LSS\\' => array ( 0 => __DIR__ . '/..' . '/openlss/lib-array2xml/LSS', ), '_HumbugBoxd02f763d3c56\\JsonMapper\\' => array ( 0 => __DIR__ . '/..' . '/netresearch/jsonmapper/src/JsonMapper', ), '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\' => array ( 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src', ), '_HumbugBoxd02f763d3c56\\Composer\\Semver\\' => array ( 0 => __DIR__ . '/..' . '/composer/semver/src', ), '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\' => array ( 0 => __DIR__ . '/..' . '/amphp/byte-stream/lib', ), '_HumbugBoxd02f763d3c56\\Amp\\' => array ( 0 => __DIR__ . '/..' . '/amphp/amp/lib', ), '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\' => array ( 0 => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib', ), 'Psalm\\' => array ( 0 => __DIR__ . '/../..' . '/src/Psalm', ), ); public static $classMap = array ( 'Psalm\\Aliases' => __DIR__ . '/../..' . '/src/Psalm/Aliases.php', 'Psalm\\CodeLocation' => __DIR__ . '/../..' . '/src/Psalm/CodeLocation.php', 'Psalm\\CodeLocation\\DocblockTypeLocation' => __DIR__ . '/../..' . '/src/Psalm/CodeLocation/DocblockTypeLocation.php', 'Psalm\\CodeLocation\\ParseErrorLocation' => __DIR__ . '/../..' . '/src/Psalm/CodeLocation/ParseErrorLocation.php', 'Psalm\\CodeLocation\\Raw' => __DIR__ . '/../..' . '/src/Psalm/CodeLocation/Raw.php', 'Psalm\\Codebase' => __DIR__ . '/../..' . '/src/Psalm/Codebase.php', 'Psalm\\Config' => __DIR__ . '/../..' . '/src/Psalm/Config.php', 'Psalm\\Config\\Creator' => __DIR__ . '/../..' . '/src/Psalm/Config/Creator.php', 'Psalm\\Config\\ErrorLevelFileFilter' => __DIR__ . '/../..' . '/src/Psalm/Config/ErrorLevelFileFilter.php', 'Psalm\\Config\\FileFilter' => __DIR__ . '/../..' . '/src/Psalm/Config/FileFilter.php', 'Psalm\\Config\\IssueHandler' => __DIR__ . '/../..' . '/src/Psalm/Config/IssueHandler.php', 'Psalm\\Config\\ProjectFileFilter' => __DIR__ . '/../..' . '/src/Psalm/Config/ProjectFileFilter.php', 'Psalm\\Config\\TaintAnalysisFileFilter' => __DIR__ . '/../..' . '/src/Psalm/Config/TaintAnalysisFileFilter.php', 'Psalm\\Context' => __DIR__ . '/../..' . '/src/Psalm/Context.php', 'Psalm\\DocComment' => __DIR__ . '/../..' . '/src/Psalm/DocComment.php', 'Psalm\\ErrorBaseline' => __DIR__ . '/../..' . '/src/Psalm/ErrorBaseline.php', 'Psalm\\Exception\\CircularReferenceException' => __DIR__ . '/../..' . '/src/Psalm/Exception/CircularReferenceException.php', 'Psalm\\Exception\\CodeException' => __DIR__ . '/../..' . '/src/Psalm/Exception/CodeException.php', 'Psalm\\Exception\\ComplicatedExpressionException' => __DIR__ . '/../..' . '/src/Psalm/Exception/ComplicatedExpressionException.php', 'Psalm\\Exception\\ConfigCreationException' => __DIR__ . '/../..' . '/src/Psalm/Exception/ConfigCreationException.php', 'Psalm\\Exception\\ConfigException' => __DIR__ . '/../..' . '/src/Psalm/Exception/ConfigException.php', 'Psalm\\Exception\\DocblockParseException' => __DIR__ . '/../..' . '/src/Psalm/Exception/DocblockParseException.php', 'Psalm\\Exception\\FileIncludeException' => __DIR__ . '/../..' . '/src/Psalm/Exception/FileIncludeException.php', 'Psalm\\Exception\\IncorrectDocblockException' => __DIR__ . '/../..' . '/src/Psalm/Exception/IncorrectDocblockException.php', 'Psalm\\Exception\\InvalidClasslikeOverrideException' => __DIR__ . '/../..' . '/src/Psalm/Exception/InvalidClasslikeOverrideException.php', 'Psalm\\Exception\\InvalidMethodOverrideException' => __DIR__ . '/../..' . '/src/Psalm/Exception/InvalidMethodOverrideException.php', 'Psalm\\Exception\\RefactorException' => __DIR__ . '/../..' . '/src/Psalm/Exception/RefactorException.php', 'Psalm\\Exception\\ScopeAnalysisException' => __DIR__ . '/../..' . '/src/Psalm/Exception/ScopeAnalysisException.php', 'Psalm\\Exception\\TypeParseTreeException' => __DIR__ . '/../..' . '/src/Psalm/Exception/TypeParseTreeException.php', 'Psalm\\Exception\\UnanalyzedFileException' => __DIR__ . '/../..' . '/src/Psalm/Exception/UnanalyzedFileException.php', 'Psalm\\Exception\\UnpopulatedClasslikeException' => __DIR__ . '/../..' . '/src/Psalm/Exception/UnpopulatedClasslikeException.php', 'Psalm\\Exception\\UnpreparedAnalysisException' => __DIR__ . '/../..' . '/src/Psalm/Exception/UnpreparedAnalysisException.php', 'Psalm\\Exception\\UnsupportedIssueToFixException' => __DIR__ . '/../..' . '/src/Psalm/Exception/UnsupportedIssueToFixException.php', 'Psalm\\FileBasedPluginAdapter' => __DIR__ . '/../..' . '/src/Psalm/FileBasedPluginAdapter.php', 'Psalm\\FileManipulation' => __DIR__ . '/../..' . '/src/Psalm/FileManipulation.php', 'Psalm\\FileSource' => __DIR__ . '/../..' . '/src/Psalm/FileSource.php', 'Psalm\\Internal\\Analyzer\\AlgebraAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/AlgebraAnalyzer.php', 'Psalm\\Internal\\Analyzer\\CanAlias' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/CanAlias.php', 'Psalm\\Internal\\Analyzer\\ClassAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/ClassAnalyzer.php', 'Psalm\\Internal\\Analyzer\\ClassLikeAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\ClosureAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/ClosureAnalyzer.php', 'Psalm\\Internal\\Analyzer\\CommentAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/CommentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\DataFlowNodeData' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/DataFlowNodeData.php', 'Psalm\\Internal\\Analyzer\\FileAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/FileAnalyzer.php', 'Psalm\\Internal\\Analyzer\\FunctionAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/FunctionAnalyzer.php', 'Psalm\\Internal\\Analyzer\\FunctionLikeAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\FunctionLike\\ReturnTypeAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\FunctionLike\\ReturnTypeCollector' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeCollector.php', 'Psalm\\Internal\\Analyzer\\InterfaceAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/InterfaceAnalyzer.php', 'Psalm\\Internal\\Analyzer\\IssueData' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/IssueData.php', 'Psalm\\Internal\\Analyzer\\MethodAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/MethodAnalyzer.php', 'Psalm\\Internal\\Analyzer\\MethodComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/MethodComparator.php', 'Psalm\\Internal\\Analyzer\\NamespaceAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php', 'Psalm\\Internal\\Analyzer\\ProjectAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php', 'Psalm\\Internal\\Analyzer\\ScopeAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/ScopeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\SourceAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/SourceAnalyzer.php', 'Psalm\\Internal\\Analyzer\\StatementsAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\DoAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Block/DoAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\ForAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\ForeachAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\IfAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Block/IfAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\LoopAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\SwitchAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\SwitchCaseAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Block/SwitchCaseAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\TryAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Block\\WhileAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\BreakAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/BreakAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\ContinueAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/ContinueAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\EchoAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/EchoAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\ExpressionAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\ArrayAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/ArrayAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\AssertionFinder' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\AssignmentAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Assignment\\ArrayAssignmentAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Assignment\\InstancePropertyAssignmentAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/InstancePropertyAssignmentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Assignment\\StaticPropertyAssignmentAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/StaticPropertyAssignmentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOpAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\AndAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/AndAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\CoalesceAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/CoalesceAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\ConcatAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/ConcatAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\NonComparisonOpAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/NonComparisonOpAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\NonDivArithmeticOpAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/NonDivArithmeticOpAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BinaryOp\\OrAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOp/OrAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BitwiseNotAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/BitwiseNotAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\BooleanNotAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/BooleanNotAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\CallAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ArgumentAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ArgumentMapPopulator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentMapPopulator.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ArgumentsAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ArrayFunctionArgumentsAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\ClassTemplateParamCollector' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ClassTemplateParamCollector.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\FunctionCallAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\MethodCallAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\AtomicCallContext' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicCallContext.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\AtomicMethodCallAnalysisResult' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalysisResult.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\AtomicMethodCallAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/AtomicMethodCallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MethodCallProhibitionAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodCallProhibitionAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MethodCallPurityAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodCallPurityAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MethodCallReturnTypeFetcher' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodCallReturnTypeFetcher.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MethodVisibilityAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MethodVisibilityAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\Method\\MissingMethodCallHandler' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/Method/MissingMethodCallHandler.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\NewAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Call\\StaticCallAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\CastAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/CastAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\CloneAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/CloneAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\EmptyAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/EmptyAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\EncapsulatedStringAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/EncapsulatedStringAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\EvalAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/EvalAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\ExitAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/ExitAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\ExpressionIdentifier' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/ExpressionIdentifier.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\ArrayFetchAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\AtomicPropertyFetchAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/AtomicPropertyFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\ClassConstFetchAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ClassConstFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\ConstFetchAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\InstancePropertyFetchAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/InstancePropertyFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\StaticPropertyFetchAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/StaticPropertyFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\Fetch\\VariableFetchAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\IncDecExpressionAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/IncDecExpressionAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\IncludeAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\InstanceofAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/InstanceofAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\IssetAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/IssetAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\MagicConstAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/MagicConstAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\MatchAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\NullsafeAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/NullsafeAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\PrintAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/PrintAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\SimpleTypeInferer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/SimpleTypeInferer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\TernaryAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\UnaryPlusMinusAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/UnaryPlusMinusAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\YieldAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/YieldAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\Expression\\YieldFromAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/Expression/YieldFromAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\GlobalAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/GlobalAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\ReturnAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\StaticAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/StaticAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\ThrowAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/ThrowAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\UnsetAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/UnsetAnalyzer.php', 'Psalm\\Internal\\Analyzer\\Statements\\UnusedAssignmentRemover' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/Statements/UnusedAssignmentRemover.php', 'Psalm\\Internal\\Analyzer\\TraitAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/TraitAnalyzer.php', 'Psalm\\Internal\\Analyzer\\TypeAnalyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Analyzer/TypeAnalyzer.php', 'Psalm\\Internal\\Clause' => __DIR__ . '/../..' . '/src/Psalm/Internal/Clause.php', 'Psalm\\Internal\\Codebase\\Analyzer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/Analyzer.php', 'Psalm\\Internal\\Codebase\\ClassLikes' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/ClassLikes.php', 'Psalm\\Internal\\Codebase\\ConstantTypeResolver' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/ConstantTypeResolver.php', 'Psalm\\Internal\\Codebase\\DataFlowGraph' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/DataFlowGraph.php', 'Psalm\\Internal\\Codebase\\Functions' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/Functions.php', 'Psalm\\Internal\\Codebase\\InternalCallMapHandler' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/InternalCallMapHandler.php', 'Psalm\\Internal\\Codebase\\Methods' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/Methods.php', 'Psalm\\Internal\\Codebase\\Populator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/Populator.php', 'Psalm\\Internal\\Codebase\\Properties' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/Properties.php', 'Psalm\\Internal\\Codebase\\PropertyMap' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/PropertyMap.php', 'Psalm\\Internal\\Codebase\\ReferenceMapGenerator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/ReferenceMapGenerator.php', 'Psalm\\Internal\\Codebase\\Reflection' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/Reflection.php', 'Psalm\\Internal\\Codebase\\Scanner' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/Scanner.php', 'Psalm\\Internal\\Codebase\\TaintFlowGraph' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/TaintFlowGraph.php', 'Psalm\\Internal\\Codebase\\VariableUseGraph' => __DIR__ . '/../..' . '/src/Psalm/Internal/Codebase/VariableUseGraph.php', 'Psalm\\Internal\\Composer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Composer.php', 'Psalm\\Internal\\DataFlow\\DataFlowNode' => __DIR__ . '/../..' . '/src/Psalm/Internal/DataFlow/DataFlowNode.php', 'Psalm\\Internal\\DataFlow\\Path' => __DIR__ . '/../..' . '/src/Psalm/Internal/DataFlow/Path.php', 'Psalm\\Internal\\DataFlow\\TaintSink' => __DIR__ . '/../..' . '/src/Psalm/Internal/DataFlow/TaintSink.php', 'Psalm\\Internal\\DataFlow\\TaintSource' => __DIR__ . '/../..' . '/src/Psalm/Internal/DataFlow/TaintSource.php', 'Psalm\\Internal\\Diff\\AstDiffer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Diff/AstDiffer.php', 'Psalm\\Internal\\Diff\\ClassStatementsDiffer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Diff/ClassStatementsDiffer.php', 'Psalm\\Internal\\Diff\\DiffElem' => __DIR__ . '/../..' . '/src/Psalm/Internal/Diff/DiffElem.php', 'Psalm\\Internal\\Diff\\FileDiffer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Diff/FileDiffer.php', 'Psalm\\Internal\\Diff\\FileStatementsDiffer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Diff/FileStatementsDiffer.php', 'Psalm\\Internal\\Diff\\NamespaceStatementsDiffer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Diff/NamespaceStatementsDiffer.php', 'Psalm\\Internal\\ExecutionEnvironment\\BuildInfoCollector' => __DIR__ . '/../..' . '/src/Psalm/Internal/ExecutionEnvironment/BuildInfoCollector.php', 'Psalm\\Internal\\ExecutionEnvironment\\GitInfoCollector' => __DIR__ . '/../..' . '/src/Psalm/Internal/ExecutionEnvironment/GitInfoCollector.php', 'Psalm\\Internal\\ExecutionEnvironment\\SystemCommandExecutor' => __DIR__ . '/../..' . '/src/Psalm/Internal/ExecutionEnvironment/SystemCommandExecutor.php', 'Psalm\\Internal\\FileManipulation\\ClassDocblockManipulator' => __DIR__ . '/../..' . '/src/Psalm/Internal/FileManipulation/ClassDocblockManipulator.php', 'Psalm\\Internal\\FileManipulation\\CodeMigration' => __DIR__ . '/../..' . '/src/Psalm/Internal/FileManipulation/CodeMigration.php', 'Psalm\\Internal\\FileManipulation\\FileManipulationBuffer' => __DIR__ . '/../..' . '/src/Psalm/Internal/FileManipulation/FileManipulationBuffer.php', 'Psalm\\Internal\\FileManipulation\\FunctionDocblockManipulator' => __DIR__ . '/../..' . '/src/Psalm/Internal/FileManipulation/FunctionDocblockManipulator.php', 'Psalm\\Internal\\FileManipulation\\PropertyDocblockManipulator' => __DIR__ . '/../..' . '/src/Psalm/Internal/FileManipulation/PropertyDocblockManipulator.php', 'Psalm\\Internal\\Fork\\ForkMessage' => __DIR__ . '/../..' . '/src/Psalm/Internal/Fork/ForkMessage.php', 'Psalm\\Internal\\Fork\\ForkProcessDoneMessage' => __DIR__ . '/../..' . '/src/Psalm/Internal/Fork/ForkProcessDoneMessage.php', 'Psalm\\Internal\\Fork\\ForkProcessErrorMessage' => __DIR__ . '/../..' . '/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php', 'Psalm\\Internal\\Fork\\ForkTaskDoneMessage' => __DIR__ . '/../..' . '/src/Psalm/Internal/Fork/ForkTaskDoneMessage.php', 'Psalm\\Internal\\Fork\\Pool' => __DIR__ . '/../..' . '/src/Psalm/Internal/Fork/Pool.php', 'Psalm\\Internal\\Fork\\PsalmRestarter' => __DIR__ . '/../..' . '/src/Psalm/Internal/Fork/PsalmRestarter.php', 'Psalm\\Internal\\IncludeCollector' => __DIR__ . '/../..' . '/src/Psalm/Internal/IncludeCollector.php', 'Psalm\\Internal\\Json\\Json' => __DIR__ . '/../..' . '/src/Psalm/Internal/Json/Json.php', 'Psalm\\Internal\\LanguageServer\\ClientHandler' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/ClientHandler.php', 'Psalm\\Internal\\LanguageServer\\Client\\TextDocument' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/Client/TextDocument.php', 'Psalm\\Internal\\LanguageServer\\EmitterInterface' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/EmitterInterface.php', 'Psalm\\Internal\\LanguageServer\\EmitterTrait' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/EmitterTrait.php', 'Psalm\\Internal\\LanguageServer\\IdGenerator' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/IdGenerator.php', 'Psalm\\Internal\\LanguageServer\\LanguageClient' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/LanguageClient.php', 'Psalm\\Internal\\LanguageServer\\LanguageServer' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/LanguageServer.php', 'Psalm\\Internal\\LanguageServer\\Message' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/Message.php', 'Psalm\\Internal\\LanguageServer\\ProtocolReader' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/ProtocolReader.php', 'Psalm\\Internal\\LanguageServer\\ProtocolStreamReader' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/ProtocolStreamReader.php', 'Psalm\\Internal\\LanguageServer\\ProtocolStreamWriter' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/ProtocolStreamWriter.php', 'Psalm\\Internal\\LanguageServer\\ProtocolWriter' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/ProtocolWriter.php', 'Psalm\\Internal\\LanguageServer\\Server\\TextDocument' => __DIR__ . '/../..' . '/src/Psalm/Internal/LanguageServer/Server/TextDocument.php', 'Psalm\\Internal\\MethodIdentifier' => __DIR__ . '/../..' . '/src/Psalm/Internal/MethodIdentifier.php', 'Psalm\\Internal\\PhpTraverser\\CustomTraverser' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpTraverser/CustomTraverser.php', 'Psalm\\Internal\\PhpVisitor\\AssignmentMapVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php', 'Psalm\\Internal\\PhpVisitor\\CheckTrivialExprVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/CheckTrivialExprVisitor.php', 'Psalm\\Internal\\PhpVisitor\\CloningVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/CloningVisitor.php', 'Psalm\\Internal\\PhpVisitor\\ConditionCloningVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/ConditionCloningVisitor.php', 'Psalm\\Internal\\PhpVisitor\\NodeCleanerVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/NodeCleanerVisitor.php', 'Psalm\\Internal\\PhpVisitor\\NodeCounterVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/NodeCounterVisitor.php', 'Psalm\\Internal\\PhpVisitor\\OffsetShifterVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/OffsetShifterVisitor.php', 'Psalm\\Internal\\PhpVisitor\\ParamReplacementVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/ParamReplacementVisitor.php', 'Psalm\\Internal\\PhpVisitor\\PartialParserVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/PartialParserVisitor.php', 'Psalm\\Internal\\PhpVisitor\\ReflectorVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php', 'Psalm\\Internal\\PhpVisitor\\ShortClosureVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/ShortClosureVisitor.php', 'Psalm\\Internal\\PhpVisitor\\SimpleNameResolver' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/SimpleNameResolver.php', 'Psalm\\Internal\\PhpVisitor\\TraitFinder' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/TraitFinder.php', 'Psalm\\Internal\\PhpVisitor\\TypeMappingVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/PhpVisitor/TypeMappingVisitor.php', 'Psalm\\Internal\\PluginManager\\Command\\DisableCommand' => __DIR__ . '/../..' . '/src/Psalm/Internal/PluginManager/Command/DisableCommand.php', 'Psalm\\Internal\\PluginManager\\Command\\EnableCommand' => __DIR__ . '/../..' . '/src/Psalm/Internal/PluginManager/Command/EnableCommand.php', 'Psalm\\Internal\\PluginManager\\Command\\ShowCommand' => __DIR__ . '/../..' . '/src/Psalm/Internal/PluginManager/Command/ShowCommand.php', 'Psalm\\Internal\\PluginManager\\ComposerLock' => __DIR__ . '/../..' . '/src/Psalm/Internal/PluginManager/ComposerLock.php', 'Psalm\\Internal\\PluginManager\\ConfigFile' => __DIR__ . '/../..' . '/src/Psalm/Internal/PluginManager/ConfigFile.php', 'Psalm\\Internal\\PluginManager\\PluginList' => __DIR__ . '/../..' . '/src/Psalm/Internal/PluginManager/PluginList.php', 'Psalm\\Internal\\PluginManager\\PluginListFactory' => __DIR__ . '/../..' . '/src/Psalm/Internal/PluginManager/PluginListFactory.php', 'Psalm\\Internal\\Provider\\ClassLikeStorageCacheProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php', 'Psalm\\Internal\\Provider\\ClassLikeStorageProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php', 'Psalm\\Internal\\Provider\\FileProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/FileProvider.php', 'Psalm\\Internal\\Provider\\FileReferenceCacheProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/FileReferenceCacheProvider.php', 'Psalm\\Internal\\Provider\\FileReferenceProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/FileReferenceProvider.php', 'Psalm\\Internal\\Provider\\FileStorageCacheProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/FileStorageCacheProvider.php', 'Psalm\\Internal\\Provider\\FileStorageProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/FileStorageProvider.php', 'Psalm\\Internal\\Provider\\FunctionExistenceProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/FunctionExistenceProvider.php', 'Psalm\\Internal\\Provider\\FunctionParamsProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/FunctionParamsProvider.php', 'Psalm\\Internal\\Provider\\FunctionReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/FunctionReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\MethodExistenceProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/MethodExistenceProvider.php', 'Psalm\\Internal\\Provider\\MethodParamsProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/MethodParamsProvider.php', 'Psalm\\Internal\\Provider\\MethodReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/MethodReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\MethodVisibilityProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/MethodVisibilityProvider.php', 'Psalm\\Internal\\Provider\\NodeDataProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/NodeDataProvider.php', 'Psalm\\Internal\\Provider\\ParserCacheProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ParserCacheProvider.php', 'Psalm\\Internal\\Provider\\ProjectCacheProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ProjectCacheProvider.php', 'Psalm\\Internal\\Provider\\PropertyExistenceProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/PropertyExistenceProvider.php', 'Psalm\\Internal\\Provider\\PropertyTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/PropertyTypeProvider.php', 'Psalm\\Internal\\Provider\\PropertyVisibilityProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/PropertyVisibilityProvider.php', 'Psalm\\Internal\\Provider\\Providers' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/Providers.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayChunkReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayChunkReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayColumnReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayColumnReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayFillReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayFilterReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFilterReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayMapReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayMergeReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMergeReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayPadReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPadReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayPointerAdjustmentReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPointerAdjustmentReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayPopReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPopReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayRandReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayRandReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayReduceReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReduceReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayReverseReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReverseReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArraySliceReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArraySliceReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayUniqueReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayUniqueReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ArrayValuesReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayValuesReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ClosureFromCallableReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ClosureFromCallableReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\DomNodeAppendChild' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/DomNodeAppendChild.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ExplodeReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ExplodeReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\FilterVarReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/FilterVarReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\FirstArgStringReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/FirstArgStringReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\GetClassMethodsReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/GetClassMethodsReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\GetObjectVarsReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/GetObjectVarsReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\HexdecReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/HexdecReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\IteratorToArrayReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/IteratorToArrayReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\MktimeReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/MktimeReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\ParseUrlReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/ParseUrlReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\PdoStatementReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\PdoStatementSetFetchMode' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementSetFetchMode.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\SimpleXmlElementAsXml' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/SimpleXmlElementAsXml.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\StrReplaceReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\ReturnTypeProvider\\VersionCompareReturnTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/ReturnTypeProvider/VersionCompareReturnTypeProvider.php', 'Psalm\\Internal\\Provider\\StatementsProvider' => __DIR__ . '/../..' . '/src/Psalm/Internal/Provider/StatementsProvider.php', 'Psalm\\Internal\\ReferenceConstraint' => __DIR__ . '/../..' . '/src/Psalm/Internal/ReferenceConstraint.php', 'Psalm\\Internal\\RuntimeCaches' => __DIR__ . '/../..' . '/src/Psalm/Internal/RuntimeCaches.php', 'Psalm\\Internal\\Scanner\\ClassLikeDocblockComment' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/ClassLikeDocblockComment.php', 'Psalm\\Internal\\Scanner\\DocblockParser' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/DocblockParser.php', 'Psalm\\Internal\\Scanner\\FileScanner' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/FileScanner.php', 'Psalm\\Internal\\Scanner\\FunctionDocblockComment' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/FunctionDocblockComment.php', 'Psalm\\Internal\\Scanner\\ParsedDocblock' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/ParsedDocblock.php', 'Psalm\\Internal\\Scanner\\PhpStormMetaScanner' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/PhpStormMetaScanner.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstantComponent' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstantComponent.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\ArrayOffsetFetch' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayOffsetFetch.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\ArrayValue' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/ArrayValue.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\ClassConstant' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/ClassConstant.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\Constant' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/Constant.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\KeyValuePair' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/KeyValuePair.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\ScalarValue' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/ScalarValue.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedAdditionOp' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedAdditionOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedBinaryOp' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBinaryOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedBitwiseOr' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedBitwiseOr.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedConcatOp' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedConcatOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedDivisionOp' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedDivisionOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedMultiplicationOp' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedMultiplicationOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedSubtractionOp' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedSubtractionOp.php', 'Psalm\\Internal\\Scanner\\UnresolvedConstant\\UnresolvedTernary' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/UnresolvedConstant/UnresolvedTernary.php', 'Psalm\\Internal\\Scanner\\VarDocblockComment' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scanner/VarDocblockComment.php', 'Psalm\\Internal\\Scope\\CaseScope' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scope/CaseScope.php', 'Psalm\\Internal\\Scope\\FinallyScope' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scope/FinallyScope.php', 'Psalm\\Internal\\Scope\\IfConditionalScope' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scope/IfConditionalScope.php', 'Psalm\\Internal\\Scope\\IfScope' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scope/IfScope.php', 'Psalm\\Internal\\Scope\\LoopScope' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scope/LoopScope.php', 'Psalm\\Internal\\Scope\\SwitchScope' => __DIR__ . '/../..' . '/src/Psalm/Internal/Scope/SwitchScope.php', 'Psalm\\Internal\\Stubs\\Generator\\ClassLikeStubGenerator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Stubs/Generator/ClassLikeStubGenerator.php', 'Psalm\\Internal\\Stubs\\Generator\\StubsGenerator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Stubs/Generator/StubsGenerator.php', 'Psalm\\Internal\\TypeVisitor\\ContainsClassLikeVisitor' => __DIR__ . '/../..' . '/src/Psalm/Internal/TypeVisitor/ContainsClassLikeVisitor.php', 'Psalm\\Internal\\TypeVisitor\\FromDocblockSetter' => __DIR__ . '/../..' . '/src/Psalm/Internal/TypeVisitor/FromDocblockSetter.php', 'Psalm\\Internal\\TypeVisitor\\TemplateTypeCollector' => __DIR__ . '/../..' . '/src/Psalm/Internal/TypeVisitor/TemplateTypeCollector.php', 'Psalm\\Internal\\TypeVisitor\\TypeChecker' => __DIR__ . '/../..' . '/src/Psalm/Internal/TypeVisitor/TypeChecker.php', 'Psalm\\Internal\\TypeVisitor\\TypeScanner' => __DIR__ . '/../..' . '/src/Psalm/Internal/TypeVisitor/TypeScanner.php', 'Psalm\\Internal\\Type\\ArrayType' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ArrayType.php', 'Psalm\\Internal\\Type\\AssertionReconciler' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/AssertionReconciler.php', 'Psalm\\Internal\\Type\\Comparator\\ArrayTypeComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/ArrayTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\AtomicTypeComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\CallableTypeComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\ClassStringComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/ClassStringComparator.php', 'Psalm\\Internal\\Type\\Comparator\\GenericTypeComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/GenericTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\KeyedArrayComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/KeyedArrayComparator.php', 'Psalm\\Internal\\Type\\Comparator\\ObjectComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/ObjectComparator.php', 'Psalm\\Internal\\Type\\Comparator\\ScalarTypeComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/ScalarTypeComparator.php', 'Psalm\\Internal\\Type\\Comparator\\TypeComparisonResult' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/TypeComparisonResult.php', 'Psalm\\Internal\\Type\\Comparator\\UnionTypeComparator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/Comparator/UnionTypeComparator.php', 'Psalm\\Internal\\Type\\NegatedAssertionReconciler' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/NegatedAssertionReconciler.php', 'Psalm\\Internal\\Type\\ParseTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree.php', 'Psalm\\Internal\\Type\\ParseTreeCreator' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTreeCreator.php', 'Psalm\\Internal\\Type\\ParseTree\\CallableParamTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/CallableParamTree.php', 'Psalm\\Internal\\Type\\ParseTree\\CallableTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/CallableTree.php', 'Psalm\\Internal\\Type\\ParseTree\\CallableWithReturnTypeTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/CallableWithReturnTypeTree.php', 'Psalm\\Internal\\Type\\ParseTree\\ConditionalTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/ConditionalTree.php', 'Psalm\\Internal\\Type\\ParseTree\\EncapsulationTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/EncapsulationTree.php', 'Psalm\\Internal\\Type\\ParseTree\\GenericTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/GenericTree.php', 'Psalm\\Internal\\Type\\ParseTree\\IndexedAccessTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/IndexedAccessTree.php', 'Psalm\\Internal\\Type\\ParseTree\\IntersectionTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/IntersectionTree.php', 'Psalm\\Internal\\Type\\ParseTree\\KeyedArrayPropertyTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/KeyedArrayPropertyTree.php', 'Psalm\\Internal\\Type\\ParseTree\\KeyedArrayTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/KeyedArrayTree.php', 'Psalm\\Internal\\Type\\ParseTree\\MethodParamTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/MethodParamTree.php', 'Psalm\\Internal\\Type\\ParseTree\\MethodTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/MethodTree.php', 'Psalm\\Internal\\Type\\ParseTree\\MethodWithReturnTypeTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/MethodWithReturnTypeTree.php', 'Psalm\\Internal\\Type\\ParseTree\\NullableTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/NullableTree.php', 'Psalm\\Internal\\Type\\ParseTree\\Root' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/Root.php', 'Psalm\\Internal\\Type\\ParseTree\\TemplateAsTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/TemplateAsTree.php', 'Psalm\\Internal\\Type\\ParseTree\\TemplateIsTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/TemplateIsTree.php', 'Psalm\\Internal\\Type\\ParseTree\\UnionTree' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/UnionTree.php', 'Psalm\\Internal\\Type\\ParseTree\\Value' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/ParseTree/Value.php', 'Psalm\\Internal\\Type\\SimpleAssertionReconciler' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/SimpleAssertionReconciler.php', 'Psalm\\Internal\\Type\\SimpleNegatedAssertionReconciler' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php', 'Psalm\\Internal\\Type\\TemplateResult' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/TemplateResult.php', 'Psalm\\Internal\\Type\\TypeAlias' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/TypeAlias.php', 'Psalm\\Internal\\Type\\TypeAlias\\ClassTypeAlias' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/TypeAlias/ClassTypeAlias.php', 'Psalm\\Internal\\Type\\TypeAlias\\InlineTypeAlias' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/TypeAlias/InlineTypeAlias.php', 'Psalm\\Internal\\Type\\TypeAlias\\LinkableTypeAlias' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/TypeAlias/LinkableTypeAlias.php', 'Psalm\\Internal\\Type\\TypeCombination' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/TypeCombination.php', 'Psalm\\Internal\\Type\\TypeExpander' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/TypeExpander.php', 'Psalm\\Internal\\Type\\TypeParser' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/TypeParser.php', 'Psalm\\Internal\\Type\\TypeTokenizer' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/TypeTokenizer.php', 'Psalm\\Internal\\Type\\UnionTemplateHandler' => __DIR__ . '/../..' . '/src/Psalm/Internal/Type/UnionTemplateHandler.php', 'Psalm\\IssueBuffer' => __DIR__ . '/../..' . '/src/Psalm/IssueBuffer.php', 'Psalm\\Issue\\AbstractInstantiation' => __DIR__ . '/../..' . '/src/Psalm/Issue/AbstractInstantiation.php', 'Psalm\\Issue\\AbstractMethodCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/AbstractMethodCall.php', 'Psalm\\Issue\\ArgumentIssue' => __DIR__ . '/../..' . '/src/Psalm/Issue/ArgumentIssue.php', 'Psalm\\Issue\\ArgumentTypeCoercion' => __DIR__ . '/../..' . '/src/Psalm/Issue/ArgumentTypeCoercion.php', 'Psalm\\Issue\\AssignmentToVoid' => __DIR__ . '/../..' . '/src/Psalm/Issue/AssignmentToVoid.php', 'Psalm\\Issue\\CircularReference' => __DIR__ . '/../..' . '/src/Psalm/Issue/CircularReference.php', 'Psalm\\Issue\\ClassIssue' => __DIR__ . '/../..' . '/src/Psalm/Issue/ClassIssue.php', 'Psalm\\Issue\\CodeIssue' => __DIR__ . '/../..' . '/src/Psalm/Issue/CodeIssue.php', 'Psalm\\Issue\\ConflictingReferenceConstraint' => __DIR__ . '/../..' . '/src/Psalm/Issue/ConflictingReferenceConstraint.php', 'Psalm\\Issue\\ConstructorSignatureMismatch' => __DIR__ . '/../..' . '/src/Psalm/Issue/ConstructorSignatureMismatch.php', 'Psalm\\Issue\\ContinueOutsideLoop' => __DIR__ . '/../..' . '/src/Psalm/Issue/ContinueOutsideLoop.php', 'Psalm\\Issue\\DeprecatedClass' => __DIR__ . '/../..' . '/src/Psalm/Issue/DeprecatedClass.php', 'Psalm\\Issue\\DeprecatedConstant' => __DIR__ . '/../..' . '/src/Psalm/Issue/DeprecatedConstant.php', 'Psalm\\Issue\\DeprecatedFunction' => __DIR__ . '/../..' . '/src/Psalm/Issue/DeprecatedFunction.php', 'Psalm\\Issue\\DeprecatedInterface' => __DIR__ . '/../..' . '/src/Psalm/Issue/DeprecatedInterface.php', 'Psalm\\Issue\\DeprecatedMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/DeprecatedMethod.php', 'Psalm\\Issue\\DeprecatedProperty' => __DIR__ . '/../..' . '/src/Psalm/Issue/DeprecatedProperty.php', 'Psalm\\Issue\\DeprecatedTrait' => __DIR__ . '/../..' . '/src/Psalm/Issue/DeprecatedTrait.php', 'Psalm\\Issue\\DocblockTypeContradiction' => __DIR__ . '/../..' . '/src/Psalm/Issue/DocblockTypeContradiction.php', 'Psalm\\Issue\\DuplicateArrayKey' => __DIR__ . '/../..' . '/src/Psalm/Issue/DuplicateArrayKey.php', 'Psalm\\Issue\\DuplicateClass' => __DIR__ . '/../..' . '/src/Psalm/Issue/DuplicateClass.php', 'Psalm\\Issue\\DuplicateFunction' => __DIR__ . '/../..' . '/src/Psalm/Issue/DuplicateFunction.php', 'Psalm\\Issue\\DuplicateMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/DuplicateMethod.php', 'Psalm\\Issue\\DuplicateParam' => __DIR__ . '/../..' . '/src/Psalm/Issue/DuplicateParam.php', 'Psalm\\Issue\\EmptyArrayAccess' => __DIR__ . '/../..' . '/src/Psalm/Issue/EmptyArrayAccess.php', 'Psalm\\Issue\\ExtensionRequirementViolation' => __DIR__ . '/../..' . '/src/Psalm/Issue/ExtensionRequirementViolation.php', 'Psalm\\Issue\\FalsableReturnStatement' => __DIR__ . '/../..' . '/src/Psalm/Issue/FalsableReturnStatement.php', 'Psalm\\Issue\\FalseOperand' => __DIR__ . '/../..' . '/src/Psalm/Issue/FalseOperand.php', 'Psalm\\Issue\\ForbiddenCode' => __DIR__ . '/../..' . '/src/Psalm/Issue/ForbiddenCode.php', 'Psalm\\Issue\\ForbiddenEcho' => __DIR__ . '/../..' . '/src/Psalm/Issue/ForbiddenEcho.php', 'Psalm\\Issue\\FunctionIssue' => __DIR__ . '/../..' . '/src/Psalm/Issue/FunctionIssue.php', 'Psalm\\Issue\\ImplementationRequirementViolation' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImplementationRequirementViolation.php', 'Psalm\\Issue\\ImplementedParamTypeMismatch' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImplementedParamTypeMismatch.php', 'Psalm\\Issue\\ImplementedReturnTypeMismatch' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImplementedReturnTypeMismatch.php', 'Psalm\\Issue\\ImplicitToStringCast' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImplicitToStringCast.php', 'Psalm\\Issue\\ImpureByReferenceAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImpureByReferenceAssignment.php', 'Psalm\\Issue\\ImpureFunctionCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImpureFunctionCall.php', 'Psalm\\Issue\\ImpureMethodCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImpureMethodCall.php', 'Psalm\\Issue\\ImpurePropertyAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImpurePropertyAssignment.php', 'Psalm\\Issue\\ImpurePropertyFetch' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImpurePropertyFetch.php', 'Psalm\\Issue\\ImpureStaticProperty' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImpureStaticProperty.php', 'Psalm\\Issue\\ImpureStaticVariable' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImpureStaticVariable.php', 'Psalm\\Issue\\ImpureVariable' => __DIR__ . '/../..' . '/src/Psalm/Issue/ImpureVariable.php', 'Psalm\\Issue\\InaccessibleClassConstant' => __DIR__ . '/../..' . '/src/Psalm/Issue/InaccessibleClassConstant.php', 'Psalm\\Issue\\InaccessibleMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/InaccessibleMethod.php', 'Psalm\\Issue\\InaccessibleProperty' => __DIR__ . '/../..' . '/src/Psalm/Issue/InaccessibleProperty.php', 'Psalm\\Issue\\InterfaceInstantiation' => __DIR__ . '/../..' . '/src/Psalm/Issue/InterfaceInstantiation.php', 'Psalm\\Issue\\InternalClass' => __DIR__ . '/../..' . '/src/Psalm/Issue/InternalClass.php', 'Psalm\\Issue\\InternalMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/InternalMethod.php', 'Psalm\\Issue\\InternalProperty' => __DIR__ . '/../..' . '/src/Psalm/Issue/InternalProperty.php', 'Psalm\\Issue\\InvalidArgument' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidArgument.php', 'Psalm\\Issue\\InvalidArrayAccess' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidArrayAccess.php', 'Psalm\\Issue\\InvalidArrayAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidArrayAssignment.php', 'Psalm\\Issue\\InvalidArrayOffset' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidArrayOffset.php', 'Psalm\\Issue\\InvalidCast' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidCast.php', 'Psalm\\Issue\\InvalidCatch' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidCatch.php', 'Psalm\\Issue\\InvalidClass' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidClass.php', 'Psalm\\Issue\\InvalidClone' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidClone.php', 'Psalm\\Issue\\InvalidDocblock' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidDocblock.php', 'Psalm\\Issue\\InvalidDocblockParamName' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidDocblockParamName.php', 'Psalm\\Issue\\InvalidExtendClass' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidExtendClass.php', 'Psalm\\Issue\\InvalidFalsableReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidFalsableReturnType.php', 'Psalm\\Issue\\InvalidFunctionCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidFunctionCall.php', 'Psalm\\Issue\\InvalidGlobal' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidGlobal.php', 'Psalm\\Issue\\InvalidIterator' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidIterator.php', 'Psalm\\Issue\\InvalidLiteralArgument' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidLiteralArgument.php', 'Psalm\\Issue\\InvalidMethodCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidMethodCall.php', 'Psalm\\Issue\\InvalidNamedArgument' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidNamedArgument.php', 'Psalm\\Issue\\InvalidNullableReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidNullableReturnType.php', 'Psalm\\Issue\\InvalidOperand' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidOperand.php', 'Psalm\\Issue\\InvalidParamDefault' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidParamDefault.php', 'Psalm\\Issue\\InvalidParent' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidParent.php', 'Psalm\\Issue\\InvalidPassByReference' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidPassByReference.php', 'Psalm\\Issue\\InvalidPropertyAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidPropertyAssignment.php', 'Psalm\\Issue\\InvalidPropertyAssignmentValue' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidPropertyAssignmentValue.php', 'Psalm\\Issue\\InvalidPropertyFetch' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidPropertyFetch.php', 'Psalm\\Issue\\InvalidReturnStatement' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidReturnStatement.php', 'Psalm\\Issue\\InvalidReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidReturnType.php', 'Psalm\\Issue\\InvalidScalarArgument' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidScalarArgument.php', 'Psalm\\Issue\\InvalidScope' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidScope.php', 'Psalm\\Issue\\InvalidStaticInvocation' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidStaticInvocation.php', 'Psalm\\Issue\\InvalidStringClass' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidStringClass.php', 'Psalm\\Issue\\InvalidTemplateParam' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidTemplateParam.php', 'Psalm\\Issue\\InvalidThrow' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidThrow.php', 'Psalm\\Issue\\InvalidToString' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidToString.php', 'Psalm\\Issue\\InvalidTypeImport' => __DIR__ . '/../..' . '/src/Psalm/Issue/InvalidTypeImport.php', 'Psalm\\Issue\\LessSpecificImplementedReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/LessSpecificImplementedReturnType.php', 'Psalm\\Issue\\LessSpecificReturnStatement' => __DIR__ . '/../..' . '/src/Psalm/Issue/LessSpecificReturnStatement.php', 'Psalm\\Issue\\LessSpecificReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/LessSpecificReturnType.php', 'Psalm\\Issue\\LoopInvalidation' => __DIR__ . '/../..' . '/src/Psalm/Issue/LoopInvalidation.php', 'Psalm\\Issue\\MethodIssue' => __DIR__ . '/../..' . '/src/Psalm/Issue/MethodIssue.php', 'Psalm\\Issue\\MethodSignatureMismatch' => __DIR__ . '/../..' . '/src/Psalm/Issue/MethodSignatureMismatch.php', 'Psalm\\Issue\\MethodSignatureMustOmitReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MethodSignatureMustOmitReturnType.php', 'Psalm\\Issue\\MismatchingDocblockParamType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MismatchingDocblockParamType.php', 'Psalm\\Issue\\MismatchingDocblockReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MismatchingDocblockReturnType.php', 'Psalm\\Issue\\MissingClosureParamType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingClosureParamType.php', 'Psalm\\Issue\\MissingClosureReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingClosureReturnType.php', 'Psalm\\Issue\\MissingConstructor' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingConstructor.php', 'Psalm\\Issue\\MissingDependency' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingDependency.php', 'Psalm\\Issue\\MissingDocblockType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingDocblockType.php', 'Psalm\\Issue\\MissingFile' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingFile.php', 'Psalm\\Issue\\MissingImmutableAnnotation' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingImmutableAnnotation.php', 'Psalm\\Issue\\MissingParamType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingParamType.php', 'Psalm\\Issue\\MissingPropertyType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingPropertyType.php', 'Psalm\\Issue\\MissingReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingReturnType.php', 'Psalm\\Issue\\MissingTemplateParam' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingTemplateParam.php', 'Psalm\\Issue\\MissingThrowsDocblock' => __DIR__ . '/../..' . '/src/Psalm/Issue/MissingThrowsDocblock.php', 'Psalm\\Issue\\MixedArgument' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedArgument.php', 'Psalm\\Issue\\MixedArgumentTypeCoercion' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedArgumentTypeCoercion.php', 'Psalm\\Issue\\MixedArrayAccess' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedArrayAccess.php', 'Psalm\\Issue\\MixedArrayAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedArrayAssignment.php', 'Psalm\\Issue\\MixedArrayOffset' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedArrayOffset.php', 'Psalm\\Issue\\MixedArrayTypeCoercion' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedArrayTypeCoercion.php', 'Psalm\\Issue\\MixedAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedAssignment.php', 'Psalm\\Issue\\MixedClone' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedClone.php', 'Psalm\\Issue\\MixedFunctionCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedFunctionCall.php', 'Psalm\\Issue\\MixedInferredReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedInferredReturnType.php', 'Psalm\\Issue\\MixedMethodCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedMethodCall.php', 'Psalm\\Issue\\MixedOperand' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedOperand.php', 'Psalm\\Issue\\MixedPropertyAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedPropertyAssignment.php', 'Psalm\\Issue\\MixedPropertyFetch' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedPropertyFetch.php', 'Psalm\\Issue\\MixedPropertyTypeCoercion' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedPropertyTypeCoercion.php', 'Psalm\\Issue\\MixedReturnStatement' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedReturnStatement.php', 'Psalm\\Issue\\MixedReturnTypeCoercion' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedReturnTypeCoercion.php', 'Psalm\\Issue\\MixedStringOffsetAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/MixedStringOffsetAssignment.php', 'Psalm\\Issue\\MoreSpecificImplementedParamType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MoreSpecificImplementedParamType.php', 'Psalm\\Issue\\MoreSpecificReturnType' => __DIR__ . '/../..' . '/src/Psalm/Issue/MoreSpecificReturnType.php', 'Psalm\\Issue\\MutableDependency' => __DIR__ . '/../..' . '/src/Psalm/Issue/MutableDependency.php', 'Psalm\\Issue\\NoInterfaceProperties' => __DIR__ . '/../..' . '/src/Psalm/Issue/NoInterfaceProperties.php', 'Psalm\\Issue\\NoValue' => __DIR__ . '/../..' . '/src/Psalm/Issue/NoValue.php', 'Psalm\\Issue\\NonStaticSelfCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/NonStaticSelfCall.php', 'Psalm\\Issue\\NullArgument' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullArgument.php', 'Psalm\\Issue\\NullArrayAccess' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullArrayAccess.php', 'Psalm\\Issue\\NullArrayOffset' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullArrayOffset.php', 'Psalm\\Issue\\NullFunctionCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullFunctionCall.php', 'Psalm\\Issue\\NullIterator' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullIterator.php', 'Psalm\\Issue\\NullOperand' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullOperand.php', 'Psalm\\Issue\\NullPropertyAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullPropertyAssignment.php', 'Psalm\\Issue\\NullPropertyFetch' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullPropertyFetch.php', 'Psalm\\Issue\\NullReference' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullReference.php', 'Psalm\\Issue\\NullableReturnStatement' => __DIR__ . '/../..' . '/src/Psalm/Issue/NullableReturnStatement.php', 'Psalm\\Issue\\OverriddenMethodAccess' => __DIR__ . '/../..' . '/src/Psalm/Issue/OverriddenMethodAccess.php', 'Psalm\\Issue\\OverriddenPropertyAccess' => __DIR__ . '/../..' . '/src/Psalm/Issue/OverriddenPropertyAccess.php', 'Psalm\\Issue\\ParadoxicalCondition' => __DIR__ . '/../..' . '/src/Psalm/Issue/ParadoxicalCondition.php', 'Psalm\\Issue\\ParamNameMismatch' => __DIR__ . '/../..' . '/src/Psalm/Issue/ParamNameMismatch.php', 'Psalm\\Issue\\ParentNotFound' => __DIR__ . '/../..' . '/src/Psalm/Issue/ParentNotFound.php', 'Psalm\\Issue\\ParseError' => __DIR__ . '/../..' . '/src/Psalm/Issue/ParseError.php', 'Psalm\\Issue\\PluginIssue' => __DIR__ . '/../..' . '/src/Psalm/Issue/PluginIssue.php', 'Psalm\\Issue\\PossibleRawObjectIteration' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossibleRawObjectIteration.php', 'Psalm\\Issue\\PossiblyFalseArgument' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyFalseArgument.php', 'Psalm\\Issue\\PossiblyFalseIterator' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyFalseIterator.php', 'Psalm\\Issue\\PossiblyFalseOperand' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyFalseOperand.php', 'Psalm\\Issue\\PossiblyFalsePropertyAssignmentValue' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyFalsePropertyAssignmentValue.php', 'Psalm\\Issue\\PossiblyFalseReference' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyFalseReference.php', 'Psalm\\Issue\\PossiblyInvalidArgument' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidArgument.php', 'Psalm\\Issue\\PossiblyInvalidArrayAccess' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidArrayAccess.php', 'Psalm\\Issue\\PossiblyInvalidArrayAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidArrayAssignment.php', 'Psalm\\Issue\\PossiblyInvalidArrayOffset' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidArrayOffset.php', 'Psalm\\Issue\\PossiblyInvalidCast' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidCast.php', 'Psalm\\Issue\\PossiblyInvalidClone' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidClone.php', 'Psalm\\Issue\\PossiblyInvalidFunctionCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidFunctionCall.php', 'Psalm\\Issue\\PossiblyInvalidIterator' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidIterator.php', 'Psalm\\Issue\\PossiblyInvalidMethodCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidMethodCall.php', 'Psalm\\Issue\\PossiblyInvalidOperand' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidOperand.php', 'Psalm\\Issue\\PossiblyInvalidPropertyAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidPropertyAssignment.php', 'Psalm\\Issue\\PossiblyInvalidPropertyAssignmentValue' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidPropertyAssignmentValue.php', 'Psalm\\Issue\\PossiblyInvalidPropertyFetch' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyInvalidPropertyFetch.php', 'Psalm\\Issue\\PossiblyNullArgument' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullArgument.php', 'Psalm\\Issue\\PossiblyNullArrayAccess' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullArrayAccess.php', 'Psalm\\Issue\\PossiblyNullArrayAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullArrayAssignment.php', 'Psalm\\Issue\\PossiblyNullArrayOffset' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullArrayOffset.php', 'Psalm\\Issue\\PossiblyNullFunctionCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullFunctionCall.php', 'Psalm\\Issue\\PossiblyNullIterator' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullIterator.php', 'Psalm\\Issue\\PossiblyNullOperand' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullOperand.php', 'Psalm\\Issue\\PossiblyNullPropertyAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullPropertyAssignment.php', 'Psalm\\Issue\\PossiblyNullPropertyAssignmentValue' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullPropertyAssignmentValue.php', 'Psalm\\Issue\\PossiblyNullPropertyFetch' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullPropertyFetch.php', 'Psalm\\Issue\\PossiblyNullReference' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyNullReference.php', 'Psalm\\Issue\\PossiblyUndefinedArrayOffset' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyUndefinedArrayOffset.php', 'Psalm\\Issue\\PossiblyUndefinedGlobalVariable' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyUndefinedGlobalVariable.php', 'Psalm\\Issue\\PossiblyUndefinedIntArrayOffset' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyUndefinedIntArrayOffset.php', 'Psalm\\Issue\\PossiblyUndefinedMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyUndefinedMethod.php', 'Psalm\\Issue\\PossiblyUndefinedStringArrayOffset' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyUndefinedStringArrayOffset.php', 'Psalm\\Issue\\PossiblyUndefinedVariable' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyUndefinedVariable.php', 'Psalm\\Issue\\PossiblyUnusedMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyUnusedMethod.php', 'Psalm\\Issue\\PossiblyUnusedParam' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyUnusedParam.php', 'Psalm\\Issue\\PossiblyUnusedProperty' => __DIR__ . '/../..' . '/src/Psalm/Issue/PossiblyUnusedProperty.php', 'Psalm\\Issue\\PropertyIssue' => __DIR__ . '/../..' . '/src/Psalm/Issue/PropertyIssue.php', 'Psalm\\Issue\\PropertyNotSetInConstructor' => __DIR__ . '/../..' . '/src/Psalm/Issue/PropertyNotSetInConstructor.php', 'Psalm\\Issue\\PropertyTypeCoercion' => __DIR__ . '/../..' . '/src/Psalm/Issue/PropertyTypeCoercion.php', 'Psalm\\Issue\\PsalmInternalError' => __DIR__ . '/../..' . '/src/Psalm/Issue/PsalmInternalError.php', 'Psalm\\Issue\\RawObjectIteration' => __DIR__ . '/../..' . '/src/Psalm/Issue/RawObjectIteration.php', 'Psalm\\Issue\\RedundantCondition' => __DIR__ . '/../..' . '/src/Psalm/Issue/RedundantCondition.php', 'Psalm\\Issue\\RedundantConditionGivenDocblockType' => __DIR__ . '/../..' . '/src/Psalm/Issue/RedundantConditionGivenDocblockType.php', 'Psalm\\Issue\\RedundantIdentityWithTrue' => __DIR__ . '/../..' . '/src/Psalm/Issue/RedundantIdentityWithTrue.php', 'Psalm\\Issue\\ReferenceConstraintViolation' => __DIR__ . '/../..' . '/src/Psalm/Issue/ReferenceConstraintViolation.php', 'Psalm\\Issue\\ReservedWord' => __DIR__ . '/../..' . '/src/Psalm/Issue/ReservedWord.php', 'Psalm\\Issue\\StringIncrement' => __DIR__ . '/../..' . '/src/Psalm/Issue/StringIncrement.php', 'Psalm\\Issue\\TaintedInput' => __DIR__ . '/../..' . '/src/Psalm/Issue/TaintedInput.php', 'Psalm\\Issue\\TooFewArguments' => __DIR__ . '/../..' . '/src/Psalm/Issue/TooFewArguments.php', 'Psalm\\Issue\\TooManyArguments' => __DIR__ . '/../..' . '/src/Psalm/Issue/TooManyArguments.php', 'Psalm\\Issue\\TooManyTemplateParams' => __DIR__ . '/../..' . '/src/Psalm/Issue/TooManyTemplateParams.php', 'Psalm\\Issue\\Trace' => __DIR__ . '/../..' . '/src/Psalm/Issue/Trace.php', 'Psalm\\Issue\\TraitMethodSignatureMismatch' => __DIR__ . '/../..' . '/src/Psalm/Issue/TraitMethodSignatureMismatch.php', 'Psalm\\Issue\\TypeDoesNotContainNull' => __DIR__ . '/../..' . '/src/Psalm/Issue/TypeDoesNotContainNull.php', 'Psalm\\Issue\\TypeDoesNotContainType' => __DIR__ . '/../..' . '/src/Psalm/Issue/TypeDoesNotContainType.php', 'Psalm\\Issue\\UncaughtThrowInGlobalScope' => __DIR__ . '/../..' . '/src/Psalm/Issue/UncaughtThrowInGlobalScope.php', 'Psalm\\Issue\\UndefinedClass' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedClass.php', 'Psalm\\Issue\\UndefinedConstant' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedConstant.php', 'Psalm\\Issue\\UndefinedDocblockClass' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedDocblockClass.php', 'Psalm\\Issue\\UndefinedFunction' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedFunction.php', 'Psalm\\Issue\\UndefinedGlobalVariable' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedGlobalVariable.php', 'Psalm\\Issue\\UndefinedInterface' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedInterface.php', 'Psalm\\Issue\\UndefinedInterfaceMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedInterfaceMethod.php', 'Psalm\\Issue\\UndefinedMagicMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedMagicMethod.php', 'Psalm\\Issue\\UndefinedMagicPropertyAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedMagicPropertyAssignment.php', 'Psalm\\Issue\\UndefinedMagicPropertyFetch' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedMagicPropertyFetch.php', 'Psalm\\Issue\\UndefinedMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedMethod.php', 'Psalm\\Issue\\UndefinedPropertyAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedPropertyAssignment.php', 'Psalm\\Issue\\UndefinedPropertyFetch' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedPropertyFetch.php', 'Psalm\\Issue\\UndefinedThisPropertyAssignment' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedThisPropertyAssignment.php', 'Psalm\\Issue\\UndefinedThisPropertyFetch' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedThisPropertyFetch.php', 'Psalm\\Issue\\UndefinedTrace' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedTrace.php', 'Psalm\\Issue\\UndefinedTrait' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedTrait.php', 'Psalm\\Issue\\UndefinedVariable' => __DIR__ . '/../..' . '/src/Psalm/Issue/UndefinedVariable.php', 'Psalm\\Issue\\UnevaluatedCode' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnevaluatedCode.php', 'Psalm\\Issue\\UnhandledMatchCondition' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnhandledMatchCondition.php', 'Psalm\\Issue\\UnimplementedAbstractMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnimplementedAbstractMethod.php', 'Psalm\\Issue\\UnimplementedInterfaceMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnimplementedInterfaceMethod.php', 'Psalm\\Issue\\UninitializedProperty' => __DIR__ . '/../..' . '/src/Psalm/Issue/UninitializedProperty.php', 'Psalm\\Issue\\UnnecessaryVarAnnotation' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnnecessaryVarAnnotation.php', 'Psalm\\Issue\\UnrecognizedExpression' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnrecognizedExpression.php', 'Psalm\\Issue\\UnrecognizedStatement' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnrecognizedStatement.php', 'Psalm\\Issue\\UnresolvableInclude' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnresolvableInclude.php', 'Psalm\\Issue\\UnsafeInstantiation' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnsafeInstantiation.php', 'Psalm\\Issue\\UnusedClass' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnusedClass.php', 'Psalm\\Issue\\UnusedClosureParam' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnusedClosureParam.php', 'Psalm\\Issue\\UnusedFunctionCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnusedFunctionCall.php', 'Psalm\\Issue\\UnusedMethod' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnusedMethod.php', 'Psalm\\Issue\\UnusedMethodCall' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnusedMethodCall.php', 'Psalm\\Issue\\UnusedParam' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnusedParam.php', 'Psalm\\Issue\\UnusedProperty' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnusedProperty.php', 'Psalm\\Issue\\UnusedPsalmSuppress' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnusedPsalmSuppress.php', 'Psalm\\Issue\\UnusedVariable' => __DIR__ . '/../..' . '/src/Psalm/Issue/UnusedVariable.php', 'Psalm\\Issue\\VariableIssue' => __DIR__ . '/../..' . '/src/Psalm/Issue/VariableIssue.php', 'Psalm\\NodeTypeProvider' => __DIR__ . '/../..' . '/src/Psalm/NodeTypeProvider.php', 'Psalm\\PluginRegistrationSocket' => __DIR__ . '/../..' . '/src/Psalm/PluginRegistrationSocket.php', 'Psalm\\Plugin\\Hook\\AfterAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterClassLikeAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterClassLikeAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterClassLikeExistenceCheckInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterClassLikeExistenceCheckInterface.php', 'Psalm\\Plugin\\Hook\\AfterClassLikeVisitInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterClassLikeVisitInterface.php', 'Psalm\\Plugin\\Hook\\AfterCodebasePopulatedInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterCodebasePopulatedInterface.php', 'Psalm\\Plugin\\Hook\\AfterEveryFunctionCallAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterEveryFunctionCallAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterExpressionAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterExpressionAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterFileAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterFileAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterFunctionCallAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterFunctionCallAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterFunctionLikeAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterFunctionLikeAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterMethodCallAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterMethodCallAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\AfterStatementAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/AfterStatementAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\BeforeFileAnalysisInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/BeforeFileAnalysisInterface.php', 'Psalm\\Plugin\\Hook\\FunctionExistenceProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/FunctionExistenceProviderInterface.php', 'Psalm\\Plugin\\Hook\\FunctionParamsProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/FunctionParamsProviderInterface.php', 'Psalm\\Plugin\\Hook\\FunctionReturnTypeProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/FunctionReturnTypeProviderInterface.php', 'Psalm\\Plugin\\Hook\\MethodExistenceProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/MethodExistenceProviderInterface.php', 'Psalm\\Plugin\\Hook\\MethodParamsProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/MethodParamsProviderInterface.php', 'Psalm\\Plugin\\Hook\\MethodReturnTypeProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/MethodReturnTypeProviderInterface.php', 'Psalm\\Plugin\\Hook\\MethodVisibilityProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/MethodVisibilityProviderInterface.php', 'Psalm\\Plugin\\Hook\\PropertyExistenceProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/PropertyExistenceProviderInterface.php', 'Psalm\\Plugin\\Hook\\PropertyTypeProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/PropertyTypeProviderInterface.php', 'Psalm\\Plugin\\Hook\\PropertyVisibilityProviderInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/PropertyVisibilityProviderInterface.php', 'Psalm\\Plugin\\Hook\\StringInterpreterInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Hook/StringInterpreterInterface.php', 'Psalm\\Plugin\\PluginEntryPointInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/PluginEntryPointInterface.php', 'Psalm\\Plugin\\RegistrationInterface' => __DIR__ . '/../..' . '/src/Psalm/Plugin/RegistrationInterface.php', 'Psalm\\Plugin\\Shepherd' => __DIR__ . '/../..' . '/src/Psalm/Plugin/Shepherd.php', 'Psalm\\Progress\\DebugProgress' => __DIR__ . '/../..' . '/src/Psalm/Progress/DebugProgress.php', 'Psalm\\Progress\\DefaultProgress' => __DIR__ . '/../..' . '/src/Psalm/Progress/DefaultProgress.php', 'Psalm\\Progress\\LongProgress' => __DIR__ . '/../..' . '/src/Psalm/Progress/LongProgress.php', 'Psalm\\Progress\\Progress' => __DIR__ . '/../..' . '/src/Psalm/Progress/Progress.php', 'Psalm\\Progress\\VoidProgress' => __DIR__ . '/../..' . '/src/Psalm/Progress/VoidProgress.php', 'Psalm\\Report' => __DIR__ . '/../..' . '/src/Psalm/Report.php', 'Psalm\\Report\\CheckstyleReport' => __DIR__ . '/../..' . '/src/Psalm/Report/CheckstyleReport.php', 'Psalm\\Report\\CompactReport' => __DIR__ . '/../..' . '/src/Psalm/Report/CompactReport.php', 'Psalm\\Report\\ConsoleReport' => __DIR__ . '/../..' . '/src/Psalm/Report/ConsoleReport.php', 'Psalm\\Report\\EmacsReport' => __DIR__ . '/../..' . '/src/Psalm/Report/EmacsReport.php', 'Psalm\\Report\\GithubActionsReport' => __DIR__ . '/../..' . '/src/Psalm/Report/GithubActionsReport.php', 'Psalm\\Report\\JsonReport' => __DIR__ . '/../..' . '/src/Psalm/Report/JsonReport.php', 'Psalm\\Report\\JsonSummaryReport' => __DIR__ . '/../..' . '/src/Psalm/Report/JsonSummaryReport.php', 'Psalm\\Report\\JunitReport' => __DIR__ . '/../..' . '/src/Psalm/Report/JunitReport.php', 'Psalm\\Report\\PhpStormReport' => __DIR__ . '/../..' . '/src/Psalm/Report/PhpStormReport.php', 'Psalm\\Report\\PylintReport' => __DIR__ . '/../..' . '/src/Psalm/Report/PylintReport.php', 'Psalm\\Report\\ReportOptions' => __DIR__ . '/../..' . '/src/Psalm/Report/ReportOptions.php', 'Psalm\\Report\\SonarqubeReport' => __DIR__ . '/../..' . '/src/Psalm/Report/SonarqubeReport.php', 'Psalm\\Report\\TextReport' => __DIR__ . '/../..' . '/src/Psalm/Report/TextReport.php', 'Psalm\\Report\\XmlReport' => __DIR__ . '/../..' . '/src/Psalm/Report/XmlReport.php', 'Psalm\\SourceControl\\Git\\CommitInfo' => __DIR__ . '/../..' . '/src/Psalm/SourceControl/Git/CommitInfo.php', 'Psalm\\SourceControl\\Git\\GitInfo' => __DIR__ . '/../..' . '/src/Psalm/SourceControl/Git/GitInfo.php', 'Psalm\\SourceControl\\Git\\RemoteInfo' => __DIR__ . '/../..' . '/src/Psalm/SourceControl/Git/RemoteInfo.php', 'Psalm\\SourceControl\\SourceControlInfo' => __DIR__ . '/../..' . '/src/Psalm/SourceControl/SourceControlInfo.php', 'Psalm\\StatementsSource' => __DIR__ . '/../..' . '/src/Psalm/StatementsSource.php', 'Psalm\\Storage\\Assertion' => __DIR__ . '/../..' . '/src/Psalm/Storage/Assertion.php', 'Psalm\\Storage\\ClassConstantStorage' => __DIR__ . '/../..' . '/src/Psalm/Storage/ClassConstantStorage.php', 'Psalm\\Storage\\ClassLikeStorage' => __DIR__ . '/../..' . '/src/Psalm/Storage/ClassLikeStorage.php', 'Psalm\\Storage\\CustomMetadataTrait' => __DIR__ . '/../..' . '/src/Psalm/Storage/CustomMetadataTrait.php', 'Psalm\\Storage\\FileStorage' => __DIR__ . '/../..' . '/src/Psalm/Storage/FileStorage.php', 'Psalm\\Storage\\FunctionLikeParameter' => __DIR__ . '/../..' . '/src/Psalm/Storage/FunctionLikeParameter.php', 'Psalm\\Storage\\FunctionLikeStorage' => __DIR__ . '/../..' . '/src/Psalm/Storage/FunctionLikeStorage.php', 'Psalm\\Storage\\FunctionStorage' => __DIR__ . '/../..' . '/src/Psalm/Storage/FunctionStorage.php', 'Psalm\\Storage\\MethodStorage' => __DIR__ . '/../..' . '/src/Psalm/Storage/MethodStorage.php', 'Psalm\\Storage\\PropertyStorage' => __DIR__ . '/../..' . '/src/Psalm/Storage/PropertyStorage.php', 'Psalm\\Type' => __DIR__ . '/../..' . '/src/Psalm/Type.php', 'Psalm\\Type\\Algebra' => __DIR__ . '/../..' . '/src/Psalm/Type/Algebra.php', 'Psalm\\Type\\Atomic' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic.php', 'Psalm\\Type\\Atomic\\CallableTrait' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/CallableTrait.php', 'Psalm\\Type\\Atomic\\GenericTrait' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/GenericTrait.php', 'Psalm\\Type\\Atomic\\HasIntersectionTrait' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/HasIntersectionTrait.php', 'Psalm\\Type\\Atomic\\Scalar' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/Scalar.php', 'Psalm\\Type\\Atomic\\TAnonymousClassInstance' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TAnonymousClassInstance.php', 'Psalm\\Type\\Atomic\\TArray' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TArray.php', 'Psalm\\Type\\Atomic\\TArrayKey' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TArrayKey.php', 'Psalm\\Type\\Atomic\\TAssertionFalsy' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TAssertionFalsy.php', 'Psalm\\Type\\Atomic\\TBool' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TBool.php', 'Psalm\\Type\\Atomic\\TCallable' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TCallable.php', 'Psalm\\Type\\Atomic\\TCallableArray' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TCallableArray.php', 'Psalm\\Type\\Atomic\\TCallableKeyedArray' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TCallableKeyedArray.php', 'Psalm\\Type\\Atomic\\TCallableList' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TCallableList.php', 'Psalm\\Type\\Atomic\\TCallableObject' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TCallableObject.php', 'Psalm\\Type\\Atomic\\TCallableString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TCallableString.php', 'Psalm\\Type\\Atomic\\TClassString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TClassString.php', 'Psalm\\Type\\Atomic\\TClassStringMap' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TClassStringMap.php', 'Psalm\\Type\\Atomic\\TClosedResource' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TClosedResource.php', 'Psalm\\Type\\Atomic\\TClosure' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TClosure.php', 'Psalm\\Type\\Atomic\\TConditional' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TConditional.php', 'Psalm\\Type\\Atomic\\TDependentGetClass' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TDependentGetClass.php', 'Psalm\\Type\\Atomic\\TDependentGetDebugType' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TDependentGetDebugType.php', 'Psalm\\Type\\Atomic\\TDependentGetType' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TDependentGetType.php', 'Psalm\\Type\\Atomic\\TEmpty' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TEmpty.php', 'Psalm\\Type\\Atomic\\TEmptyMixed' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TEmptyMixed.php', 'Psalm\\Type\\Atomic\\TEmptyNumeric' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TEmptyNumeric.php', 'Psalm\\Type\\Atomic\\TEmptyScalar' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TEmptyScalar.php', 'Psalm\\Type\\Atomic\\TFalse' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TFalse.php', 'Psalm\\Type\\Atomic\\TFloat' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TFloat.php', 'Psalm\\Type\\Atomic\\TGenericObject' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TGenericObject.php', 'Psalm\\Type\\Atomic\\THtmlEscapedString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/THtmlEscapedString.php', 'Psalm\\Type\\Atomic\\TInt' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TInt.php', 'Psalm\\Type\\Atomic\\TIterable' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TIterable.php', 'Psalm\\Type\\Atomic\\TKeyOfClassConstant' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TKeyOfClassConstant.php', 'Psalm\\Type\\Atomic\\TKeyedArray' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TKeyedArray.php', 'Psalm\\Type\\Atomic\\TList' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TList.php', 'Psalm\\Type\\Atomic\\TLiteralClassString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TLiteralClassString.php', 'Psalm\\Type\\Atomic\\TLiteralFloat' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TLiteralFloat.php', 'Psalm\\Type\\Atomic\\TLiteralInt' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TLiteralInt.php', 'Psalm\\Type\\Atomic\\TLiteralString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TLiteralString.php', 'Psalm\\Type\\Atomic\\TLowercaseString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TLowercaseString.php', 'Psalm\\Type\\Atomic\\TMixed' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TMixed.php', 'Psalm\\Type\\Atomic\\TNamedObject' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNamedObject.php', 'Psalm\\Type\\Atomic\\TNever' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNever.php', 'Psalm\\Type\\Atomic\\TNonEmptyArray' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNonEmptyArray.php', 'Psalm\\Type\\Atomic\\TNonEmptyList' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNonEmptyList.php', 'Psalm\\Type\\Atomic\\TNonEmptyLowercaseString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNonEmptyLowercaseString.php', 'Psalm\\Type\\Atomic\\TNonEmptyMixed' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNonEmptyMixed.php', 'Psalm\\Type\\Atomic\\TNonEmptyScalar' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNonEmptyScalar.php', 'Psalm\\Type\\Atomic\\TNonEmptyString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNonEmptyString.php', 'Psalm\\Type\\Atomic\\TNull' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNull.php', 'Psalm\\Type\\Atomic\\TNumeric' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNumeric.php', 'Psalm\\Type\\Atomic\\TNumericString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TNumericString.php', 'Psalm\\Type\\Atomic\\TObject' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TObject.php', 'Psalm\\Type\\Atomic\\TObjectWithProperties' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TObjectWithProperties.php', 'Psalm\\Type\\Atomic\\TPositiveInt' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TPositiveInt.php', 'Psalm\\Type\\Atomic\\TResource' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TResource.php', 'Psalm\\Type\\Atomic\\TScalar' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TScalar.php', 'Psalm\\Type\\Atomic\\TScalarClassConstant' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TScalarClassConstant.php', 'Psalm\\Type\\Atomic\\TSingleLetter' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TSingleLetter.php', 'Psalm\\Type\\Atomic\\TString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TString.php', 'Psalm\\Type\\Atomic\\TTemplateIndexedAccess' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TTemplateIndexedAccess.php', 'Psalm\\Type\\Atomic\\TTemplateKeyOf' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TTemplateKeyOf.php', 'Psalm\\Type\\Atomic\\TTemplateParam' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TTemplateParam.php', 'Psalm\\Type\\Atomic\\TTemplateParamClass' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TTemplateParamClass.php', 'Psalm\\Type\\Atomic\\TTraitString' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TTraitString.php', 'Psalm\\Type\\Atomic\\TTrue' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TTrue.php', 'Psalm\\Type\\Atomic\\TTypeAlias' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TTypeAlias.php', 'Psalm\\Type\\Atomic\\TValueOfClassConstant' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TValueOfClassConstant.php', 'Psalm\\Type\\Atomic\\TVoid' => __DIR__ . '/../..' . '/src/Psalm/Type/Atomic/TVoid.php', 'Psalm\\Type\\NodeVisitor' => __DIR__ . '/../..' . '/src/Psalm/Type/NodeVisitor.php', 'Psalm\\Type\\Reconciler' => __DIR__ . '/../..' . '/src/Psalm/Type/Reconciler.php', 'Psalm\\Type\\TaintKind' => __DIR__ . '/../..' . '/src/Psalm/Type/TaintKind.php', 'Psalm\\Type\\TaintKindGroup' => __DIR__ . '/../..' . '/src/Psalm/Type/TaintKindGroup.php', 'Psalm\\Type\\TypeNode' => __DIR__ . '/../..' . '/src/Psalm/Type/TypeNode.php', 'Psalm\\Type\\Union' => __DIR__ . '/../..' . '/src/Psalm/Type/Union.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Dispatcher' => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib/Dispatcher.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Error' => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib/Error.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\ErrorCode' => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib/ErrorCode.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\ErrorResponse' => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib/ErrorResponse.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Message' => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib/Message.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Notification' => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib/Notification.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Request' => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib/Request.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\Response' => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib/Response.php', '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\SuccessResponse' => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib/SuccessResponse.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Base64\\Base64DecodingInputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/Base64/Base64DecodingInputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Base64\\Base64DecodingOutputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Base64\\Base64EncodingInputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/Base64/Base64EncodingInputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Base64\\Base64EncodingOutputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ClosedException' => __DIR__ . '/..' . '/amphp/byte-stream/lib/ClosedException.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\InMemoryStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/InMemoryStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\InputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/InputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\InputStreamChain' => __DIR__ . '/..' . '/amphp/byte-stream/lib/InputStreamChain.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\IteratorStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/IteratorStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\LineReader' => __DIR__ . '/..' . '/amphp/byte-stream/lib/LineReader.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Message' => __DIR__ . '/..' . '/amphp/byte-stream/lib/Message.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\OutputBuffer' => __DIR__ . '/..' . '/amphp/byte-stream/lib/OutputBuffer.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\OutputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/OutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\Payload' => __DIR__ . '/..' . '/amphp/byte-stream/lib/Payload.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\PendingReadError' => __DIR__ . '/..' . '/amphp/byte-stream/lib/PendingReadError.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ResourceInputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/ResourceInputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ResourceOutputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/ResourceOutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\StreamException' => __DIR__ . '/..' . '/amphp/byte-stream/lib/StreamException.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ZlibInputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/ZlibInputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\ZlibOutputStream' => __DIR__ . '/..' . '/amphp/byte-stream/lib/ZlibOutputStream.php', '_HumbugBoxd02f763d3c56\\Amp\\CallableMaker' => __DIR__ . '/..' . '/amphp/amp/lib/CallableMaker.php', '_HumbugBoxd02f763d3c56\\Amp\\CancellationToken' => __DIR__ . '/..' . '/amphp/amp/lib/CancellationToken.php', '_HumbugBoxd02f763d3c56\\Amp\\CancellationTokenSource' => __DIR__ . '/..' . '/amphp/amp/lib/CancellationTokenSource.php', '_HumbugBoxd02f763d3c56\\Amp\\CancelledException' => __DIR__ . '/..' . '/amphp/amp/lib/CancelledException.php', '_HumbugBoxd02f763d3c56\\Amp\\CombinedCancellationToken' => __DIR__ . '/..' . '/amphp/amp/lib/CombinedCancellationToken.php', '_HumbugBoxd02f763d3c56\\Amp\\Coroutine' => __DIR__ . '/..' . '/amphp/amp/lib/Coroutine.php', '_HumbugBoxd02f763d3c56\\Amp\\Deferred' => __DIR__ . '/..' . '/amphp/amp/lib/Deferred.php', '_HumbugBoxd02f763d3c56\\Amp\\Delayed' => __DIR__ . '/..' . '/amphp/amp/lib/Delayed.php', '_HumbugBoxd02f763d3c56\\Amp\\Emitter' => __DIR__ . '/..' . '/amphp/amp/lib/Emitter.php', '_HumbugBoxd02f763d3c56\\Amp\\Failure' => __DIR__ . '/..' . '/amphp/amp/lib/Failure.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\Placeholder' => __DIR__ . '/..' . '/amphp/amp/lib/Internal/Placeholder.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\PrivateIterator' => __DIR__ . '/..' . '/amphp/amp/lib/Internal/PrivateIterator.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\PrivatePromise' => __DIR__ . '/..' . '/amphp/amp/lib/Internal/PrivatePromise.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\Producer' => __DIR__ . '/..' . '/amphp/amp/lib/Internal/Producer.php', '_HumbugBoxd02f763d3c56\\Amp\\Internal\\ResolutionQueue' => __DIR__ . '/..' . '/amphp/amp/lib/Internal/ResolutionQueue.php', '_HumbugBoxd02f763d3c56\\Amp\\InvalidYieldError' => __DIR__ . '/..' . '/amphp/amp/lib/InvalidYieldError.php', '_HumbugBoxd02f763d3c56\\Amp\\Iterator' => __DIR__ . '/..' . '/amphp/amp/lib/Iterator.php', '_HumbugBoxd02f763d3c56\\Amp\\LazyPromise' => __DIR__ . '/..' . '/amphp/amp/lib/LazyPromise.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop' => __DIR__ . '/..' . '/amphp/amp/lib/Loop.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\Driver' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/Driver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\DriverFactory' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/DriverFactory.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\EvDriver' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/EvDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\EventDriver' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/EventDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\Internal\\TimerQueue' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/Internal/TimerQueue.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\Internal\\TimerQueueEntry' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/Internal/TimerQueueEntry.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\InvalidWatcherError' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/InvalidWatcherError.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\NativeDriver' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/NativeDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\TracingDriver' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/TracingDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\UnsupportedFeatureException' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/UnsupportedFeatureException.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\UvDriver' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/UvDriver.php', '_HumbugBoxd02f763d3c56\\Amp\\Loop\\Watcher' => __DIR__ . '/..' . '/amphp/amp/lib/Loop/Watcher.php', '_HumbugBoxd02f763d3c56\\Amp\\MultiReasonException' => __DIR__ . '/..' . '/amphp/amp/lib/MultiReasonException.php', '_HumbugBoxd02f763d3c56\\Amp\\NullCancellationToken' => __DIR__ . '/..' . '/amphp/amp/lib/NullCancellationToken.php', '_HumbugBoxd02f763d3c56\\Amp\\Producer' => __DIR__ . '/..' . '/amphp/amp/lib/Producer.php', '_HumbugBoxd02f763d3c56\\Amp\\Promise' => __DIR__ . '/..' . '/amphp/amp/lib/Promise.php', '_HumbugBoxd02f763d3c56\\Amp\\Struct' => __DIR__ . '/..' . '/amphp/amp/lib/Struct.php', '_HumbugBoxd02f763d3c56\\Amp\\Success' => __DIR__ . '/..' . '/amphp/amp/lib/Success.php', '_HumbugBoxd02f763d3c56\\Amp\\TimeoutCancellationToken' => __DIR__ . '/..' . '/amphp/amp/lib/TimeoutCancellationToken.php', '_HumbugBoxd02f763d3c56\\Amp\\TimeoutException' => __DIR__ . '/..' . '/amphp/amp/lib/TimeoutException.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Comparator' => __DIR__ . '/..' . '/composer/semver/src/Comparator.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\CompilingMatcher' => __DIR__ . '/..' . '/composer/semver/src/CompilingMatcher.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\Bound' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Bound.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\Constraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Constraint.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\ConstraintInterface' => __DIR__ . '/..' . '/composer/semver/src/Constraint/ConstraintInterface.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\MatchAllConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchAllConstraint.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\MatchNoneConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MatchNoneConstraint.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Constraint\\MultiConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MultiConstraint.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Interval' => __DIR__ . '/..' . '/composer/semver/src/Interval.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Intervals' => __DIR__ . '/..' . '/composer/semver/src/Intervals.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\Semver' => __DIR__ . '/..' . '/composer/semver/src/Semver.php', '_HumbugBoxd02f763d3c56\\Composer\\Semver\\VersionParser' => __DIR__ . '/..' . '/composer/semver/src/VersionParser.php', '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\PhpConfig' => __DIR__ . '/..' . '/composer/xdebug-handler/src/PhpConfig.php', '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\Process' => __DIR__ . '/..' . '/composer/xdebug-handler/src/Process.php', '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\Status' => __DIR__ . '/..' . '/composer/xdebug-handler/src/Status.php', '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\XdebugHandler' => __DIR__ . '/..' . '/composer/xdebug-handler/src/XdebugHandler.php', '_HumbugBoxd02f763d3c56\\JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', '_HumbugBoxd02f763d3c56\\LSS\\Array2XML' => __DIR__ . '/..' . '/openlss/lib-array2xml/LSS/Array2XML.php', '_HumbugBoxd02f763d3c56\\LSS\\XML2Array' => __DIR__ . '/..' . '/openlss/lib-array2xml/LSS/XML2Array.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ClientCapabilities' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/ClientCapabilities.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CodeActionContext' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/CodeActionContext.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CodeLens' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/CodeLens.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CodeLensOptions' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/CodeLensOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Command' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/Command.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionContext' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/CompletionContext.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionItem' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/CompletionItem.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionItemKind' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/CompletionItemKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionList' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/CompletionList.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionOptions' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/CompletionOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\CompletionTriggerKind' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/CompletionTriggerKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ContentChangeEvent' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/ContentChangeEvent.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DependencyReference' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/DependencyReference.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Diagnostic' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/Diagnostic.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DiagnosticSeverity' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/DiagnosticSeverity.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DocumentHighlight' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/DocumentHighlight.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DocumentHighlightKind' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/DocumentHighlightKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\DocumentOnTypeFormattingOptions' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/DocumentOnTypeFormattingOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ErrorCode' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/ErrorCode.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\FileChangeType' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/FileChangeType.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\FileEvent' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/FileEvent.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\FormattingOptions' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/FormattingOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Hover' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/Hover.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\InitializeResult' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/InitializeResult.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\InsertTextFormat' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/InsertTextFormat.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Location' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/Location.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MarkedString' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/MarkedString.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MarkupContent' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/MarkupContent.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MarkupKind' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/MarkupKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MessageActionItem' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/MessageActionItem.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\MessageType' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/MessageType.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\PackageDescriptor' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/PackageDescriptor.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ParameterInformation' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/ParameterInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Position' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/Position.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\Range' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/Range.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ReferenceContext' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/ReferenceContext.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ReferenceInformation' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/ReferenceInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SaveOptions' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/SaveOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\ServerCapabilities' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/ServerCapabilities.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SignatureHelp' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/SignatureHelp.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SignatureHelpOptions' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/SignatureHelpOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SignatureInformation' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/SignatureInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SymbolDescriptor' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/SymbolDescriptor.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SymbolInformation' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/SymbolInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SymbolKind' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/SymbolKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\SymbolLocationInformation' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/SymbolLocationInformation.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentContentChangeEvent' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/TextDocumentContentChangeEvent.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentIdentifier' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/TextDocumentIdentifier.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentItem' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/TextDocumentItem.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentSyncKind' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/TextDocumentSyncKind.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextDocumentSyncOptions' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/TextDocumentSyncOptions.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\TextEdit' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/TextEdit.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\VersionedTextDocumentIdentifier' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/VersionedTextDocumentIdentifier.php', '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\WorkspaceEdit' => __DIR__ . '/..' . '/felixfbecker/language-server-protocol/src/WorkspaceEdit.php', '_HumbugBoxd02f763d3c56\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', '_HumbugBoxd02f763d3c56\\PackageVersions\\FallbackVersions' => __DIR__ . '/..' . '/composer/package-versions-deprecated/src/PackageVersions/FallbackVersions.php', '_HumbugBoxd02f763d3c56\\PackageVersions\\Installer' => __DIR__ . '/..' . '/composer/package-versions-deprecated/src/PackageVersions/Installer.php', '_HumbugBoxd02f763d3c56\\PackageVersions\\Versions' => __DIR__ . '/..' . '/composer/package-versions-deprecated/src/PackageVersions/Versions.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder.php', '_HumbugBoxd02f763d3c56\\PhpParser\\BuilderFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderFactory.php', '_HumbugBoxd02f763d3c56\\PhpParser\\BuilderHelpers' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/BuilderHelpers.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Class_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Declaration' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Declaration.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Function_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Interface_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Interface_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Method' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Method.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Param' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Param.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Property' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Property.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\TraitUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\TraitUseAdaptation' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Trait_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Builder\\Use_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Builder/Use_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Comment' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Comment.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Comment\\Doc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Comment/Doc.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ConstExprEvaluationException' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ConstExprEvaluator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Error' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Error.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ErrorHandler' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ErrorHandler\\Collecting' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ErrorHandler\\Throwing' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Internal\\DiffElem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Internal\\Differ' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/Differ.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Internal\\PrintableNewAnonClassNode' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Internal\\TokenStream' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php', '_HumbugBoxd02f763d3c56\\PhpParser\\JsonDecoder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/JsonDecoder.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\Emulative' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\CoaleseEqualTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\FlexibleDocStringEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\FnTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\NumericLiteralSeparatorEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NameContext' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NameContext.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeAbstract.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeDumper' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeDumper.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeFinder' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeFinder.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeTraverser' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeTraverser.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeTraverserInterface' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitorAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\CloningVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\FindingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\FirstFindingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\NameResolver' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\NodeConnectingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\NodeVisitor\\ParentConnectingVisitor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Arg' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Arg.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Attribute' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Attribute.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\AttributeGroup' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Const_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Const_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ArrayDimFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ArrayItem' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Array_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ArrowFunction' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Assign' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Div' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\AssignRef' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BitwiseNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\BooleanNot' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Array_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Bool_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Double' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Int_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Object_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\String_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Cast\\Unset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ClassConstFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Clone_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Closure' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ClosureUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ConstFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Empty_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Error' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ErrorSuppress' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Eval_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Exit_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\FuncCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Include_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Instanceof_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Isset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\List_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Match_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\MethodCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\New_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\NullsafeMethodCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\NullsafePropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PostDec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PostInc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PreDec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PreInc' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Print_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\PropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\ShellExec' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\StaticCall' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Ternary' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Throw_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\UnaryMinus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\UnaryPlus' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Variable' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\YieldFrom' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Expr\\Yield_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\FunctionLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Identifier' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Identifier.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\MatchArm' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/MatchArm.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Name' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Name\\FullyQualified' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Name\\Relative' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\NullableType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/NullableType.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Param' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Param.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\DNumber' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\Encapsed' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\EncapsedStringPart' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\LNumber' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\File' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Scalar\\String_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Break_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Case_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Catch_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\ClassConst' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\ClassLike' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\ClassMethod' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Class_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Const_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Continue_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\DeclareDeclare' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Declare_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Do_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Echo_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\ElseIf_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Else_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Expression' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Finally_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\For_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Foreach_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Function_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Global_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Goto_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\GroupUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\HaltCompiler' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\If_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\InlineHTML' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Interface_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Label' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Namespace_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Nop' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Property' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\PropertyProperty' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Return_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\StaticVar' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Static_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Switch_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Throw_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TraitUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TraitUseAdaptation' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Trait_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\TryCatch' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Unset_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\UseUse' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\Use_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\Stmt\\While_' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\UnionType' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/UnionType.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Node\\VarLikeIdentifier' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ParserAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserAbstract.php', '_HumbugBoxd02f763d3c56\\PhpParser\\ParserFactory' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/ParserFactory.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser\\Multiple' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Multiple.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser\\Php5' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Php5.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser\\Php7' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Php7.php', '_HumbugBoxd02f763d3c56\\PhpParser\\Parser\\Tokens' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Tokens.php', '_HumbugBoxd02f763d3c56\\PhpParser\\PrettyPrinterAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php', '_HumbugBoxd02f763d3c56\\PhpParser\\PrettyPrinter\\Standard' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php', '_HumbugBoxd02f763d3c56\\Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerExceptionInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareTrait.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php', '_HumbugBoxd02f763d3c56\\Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Chunk' => __DIR__ . '/..' . '/sebastian/diff/src/Chunk.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\ConfigurationException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/ConfigurationException.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Diff' => __DIR__ . '/..' . '/sebastian/diff/src/Diff.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Differ' => __DIR__ . '/..' . '/sebastian/diff/src/Differ.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Exception' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/Exception.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/InvalidArgumentException.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Line' => __DIR__ . '/..' . '/sebastian/diff/src/Line.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\Parser' => __DIR__ . '/..' . '/sebastian/diff/src/Parser.php', '_HumbugBoxd02f763d3c56\\SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', '_HumbugBoxd02f763d3c56\\Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/FactoryCommandLoader.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/symfony/console/Command/Command.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/symfony/console/Command/HelpCommand.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/symfony/console/Command/ListCommand.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Command\\LockableTrait' => __DIR__ . '/..' . '/symfony/console/Command/LockableTrait.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/symfony/console/ConsoleEvents.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Cursor' => __DIR__ . '/..' . '/symfony/console/Cursor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => __DIR__ . '/..' . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/symfony/console/Descriptor/ApplicationDescription.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/Descriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/symfony/console/Descriptor/DescriptorInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/JsonDescriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/MarkdownDescriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/TextDescriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/XmlDescriptor.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/console/EventListener/ErrorListener.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleCommandEvent.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleErrorEvent.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleEvent.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleTerminateEvent.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/CommandNotFoundException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/console/Exception/ExceptionInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidArgumentException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidOptionException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/console/Exception/LogicException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\MissingInputException' => __DIR__ . '/..' . '/symfony/console/Exception/MissingInputException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/NamespaceNotFoundException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/console/Exception/RuntimeException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatter.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatterStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatter.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleStack.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\Dumper' => __DIR__ . '/..' . '/symfony/console/Helper/Dumper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\HelperSet' => __DIR__ . '/..' . '/symfony/console/Helper/HelperSet.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/symfony/console/Helper/InputAwareHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProcessHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressBar.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressIndicator.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/QuestionHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/SymfonyQuestionHelper.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/symfony/console/Helper/Table.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/symfony/console/Helper/TableCell.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\TableRows' => __DIR__ . '/..' . '/symfony/console/Helper/TableRows.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/symfony/console/Input/InputArgument.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputAwareInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/symfony/console/Input/InputDefinition.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/symfony/console/Input/InputOption.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => __DIR__ . '/..' . '/symfony/console/Input/StreamableInputInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/symfony/console/Input/StringInput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/symfony/console/Logger/ConsoleLogger.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/symfony/console/Output/BufferedOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutputInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleSectionOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\NullOutput' => __DIR__ . '/..' . '/symfony/console/Output/NullOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/symfony/console/Output/Output.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/OutputInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/symfony/console/Output/StreamOutput.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\SingleCommandApplication' => __DIR__ . '/..' . '/symfony/console/SingleCommandApplication.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/symfony/console/Style/OutputStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/symfony/console/Style/StyleInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/symfony/console/Style/SymfonyStyle.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Terminal' => __DIR__ . '/..' . '/symfony/console/Terminal.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\Tester\\TesterTrait' => __DIR__ . '/..' . '/symfony/console/Tester/TesterTrait.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\AbstractString' => __DIR__ . '/..' . '/symfony/string/AbstractString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\AbstractUnicodeString' => __DIR__ . '/..' . '/symfony/string/AbstractUnicodeString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\ByteString' => __DIR__ . '/..' . '/symfony/string/ByteString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\CodePointString' => __DIR__ . '/..' . '/symfony/string/CodePointString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/string/Exception/ExceptionInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/string/Exception/InvalidArgumentException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/string/Exception/RuntimeException.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/EnglishInflector.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => __DIR__ . '/..' . '/symfony/string/Inflector/InflectorInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\LazyString' => __DIR__ . '/..' . '/symfony/string/LazyString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => __DIR__ . '/..' . '/symfony/string/Slugger/AsciiSlugger.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => __DIR__ . '/..' . '/symfony/string/Slugger/SluggerInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\UnicodeString' => __DIR__ . '/..' . '/symfony/string/UnicodeString.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php', '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/symfony/polyfill-ctype/Ctype.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/Grapheme.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php73\\Php73' => __DIR__ . '/..' . '/symfony/polyfill-php73/Php73.php', '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php', '_HumbugBoxd02f763d3c56\\UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', '_HumbugBoxd02f763d3c56\\ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Assert\\Assert' => __DIR__ . '/..' . '/webmozart/assert/src/Assert.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Assert\\Mixin' => __DIR__ . '/..' . '/webmozart/assert/src/Mixin.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Glob' => __DIR__ . '/..' . '/webmozart/glob/src/Glob.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Iterator\\GlobFilterIterator' => __DIR__ . '/..' . '/webmozart/glob/src/Iterator/GlobFilterIterator.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Iterator\\GlobIterator' => __DIR__ . '/..' . '/webmozart/glob/src/Iterator/GlobIterator.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Iterator\\RecursiveDirectoryIterator' => __DIR__ . '/..' . '/webmozart/glob/src/Iterator/RecursiveDirectoryIterator.php', '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\Iterator\\RegexFilterIterator' => __DIR__ . '/..' . '/webmozart/glob/src/Iterator/RegexFilterIterator.php', '_HumbugBoxd02f763d3c56\\Webmozart\\PathUtil\\Path' => __DIR__ . '/..' . '/webmozart/path-util/src/Path.php', '_HumbugBoxd02f763d3c56\\Webmozart\\PathUtil\\Url' => __DIR__ . '/..' . '/webmozart/path-util/src/Url.php', '_HumbugBoxd02f763d3c56\\XdgBaseDir\\Xdg' => __DIR__ . '/..' . '/dnoegel/php-xdg-base-dir/src/Xdg.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlockFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlockFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlockFactoryInterface' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Description' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Description.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\ExampleFinder' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Serializer' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\StandardTagFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\TagFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Author' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\BaseTag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Covers' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Deprecated' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Example' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Factory\\StaticMethod' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\AlignFormatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Formatter\\PassthroughFormatter' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Generic' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\InvalidTag' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Link' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Method' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Param' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Property' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyRead' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\PropertyWrite' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Fqsen' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Reference' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Reference\\Url' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Return_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\See' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Since' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Source' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\TagWithType' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Throws' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Uses' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Var_' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\DocBlock\\Tags\\Version' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Element' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Element.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Exception\\PcreException' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Exception/PcreException.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\File' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/File.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Fqsen' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Fqsen.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\FqsenResolver' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/FqsenResolver.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Location' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Location.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Project' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/Project.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\ProjectFactory' => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src/ProjectFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\PseudoType' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoType.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\PseudoTypes\\False_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/False_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\PseudoTypes\\True_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/PseudoTypes/True_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Type' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Type.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\TypeResolver' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/TypeResolver.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\AbstractList' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/AbstractList.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\AggregatedType' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/AggregatedType.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Array_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Array_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Boolean' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Boolean.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Callable_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Callable_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\ClassString' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/ClassString.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Collection' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Collection.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Compound' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Compound.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Context' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Context.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\ContextFactory' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/ContextFactory.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Expression' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Expression.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Float_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Float_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Integer' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Integer.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Intersection' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Intersection.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Iterable_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Iterable_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Mixed_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Mixed_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Null_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Null_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Nullable' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Nullable.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Object_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Object_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Parent_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Parent_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Resource_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Resource_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Scalar' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Scalar.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Self_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Self_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Static_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Static_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\String_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/String_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\This' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/This.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Types\\Void_' => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src/Types/Void_.php', '_HumbugBoxd02f763d3c56\\phpDocumentor\\Reflection\\Utils' => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src/Utils.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInit8efb600fd249dcbe30d3ad40e17221ec::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit8efb600fd249dcbe30d3ad40e17221ec::$prefixDirsPsr4; $loader->classMap = ComposerStaticInit8efb600fd249dcbe30d3ad40e17221ec::$classMap; }, null, ClassLoader::class); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Autoload; /** * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. * * $loader = new \Composer\Autoload\ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * // activate the autoloader * $loader->register(); * * // to enable searching the include path (eg. for PEAR packages) * $loader->setUseIncludePath(true); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * This class is loosely based on the Symfony UniversalClassLoader. * * @author Fabien Potencier * @author Jordi Boggiano * @see http://www.php-fig.org/psr/psr-0/ * @see http://www.php-fig.org/psr/psr-4/ */ class ClassLoader { // PSR-4 private $prefixLengthsPsr4 = array(); private $prefixDirsPsr4 = array(); private $fallbackDirsPsr4 = array(); // PSR-0 private $prefixesPsr0 = array(); private $fallbackDirsPsr0 = array(); private $useIncludePath = false; private $classMap = array(); private $classMapAuthoritative = false; private $missingClasses = array(); private $apcuPrefix; public function getPrefixes() { if (!empty($this->prefixesPsr0)) { return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); } return array(); } public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } public function getFallbackDirs() { return $this->fallbackDirsPsr0; } public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } public function getClassMap() { return $this->classMap; } /** * @param array $classMap Class to filename map */ public function addClassMap(array $classMap) { if ($this->classMap) { $this->classMap = array_merge($this->classMap, $classMap); } else { $this->classMap = $classMap; } } /** * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * * @param string $prefix The prefix * @param array|string $paths The PSR-0 root directories * @param bool $prepend Whether to prepend the directories */ public function add($prefix, $paths, $prepend = false) { if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( (array) $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, (array) $paths ); } return; } $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { $this->prefixesPsr0[$first][$prefix] = (array) $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( (array) $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], (array) $paths ); } } /** * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException */ public function addPsr4($prefix, $paths, $prepend = false) { if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( (array) $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, (array) $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { // Register directories for a new namespace. $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixDirsPsr4[$prefix] = (array) $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( (array) $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], (array) $paths ); } } /** * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * * @param string $prefix The prefix * @param array|string $paths The PSR-0 base directories */ public function set($prefix, $paths) { if (!$prefix) { $this->fallbackDirsPsr0 = (array) $paths; } else { $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; } } /** * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException */ public function setPsr4($prefix, $paths) { if (!$prefix) { $this->fallbackDirsPsr4 = (array) $paths; } else { $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixDirsPsr4[$prefix] = (array) $paths; } } /** * Turns on searching the include path for class files. * * @param bool $useIncludePath */ public function setUseIncludePath($useIncludePath) { $this->useIncludePath = $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return bool */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Turns off searching the prefix and fallback directories for classes * that have not been registered with the class map. * * @param bool $classMapAuthoritative */ public function setClassMapAuthoritative($classMapAuthoritative) { $this->classMapAuthoritative = $classMapAuthoritative; } /** * Should class lookup fail if not found in the current class map? * * @return bool */ public function isClassMapAuthoritative() { return $this->classMapAuthoritative; } /** * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix */ public function setApcuPrefix($apcuPrefix) { $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** * The APCu prefix in use, or null if APCu caching is not enabled. * * @return string|null */ public function getApcuPrefix() { return $this->apcuPrefix; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * @return bool|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { includeFile($file); return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|false The path if found, false otherwise */ public function findFile($class) { // class map lookup if (isset($this->classMap[$class])) { return $this->classMap[$class]; } if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { return false; } if (null !== $this->apcuPrefix) { $file = apcu_fetch($this->apcuPrefix.$class, $hit); if ($hit) { return $file; } } $file = $this->findFileWithExtension($class, '.php'); // Search for Hack files if we are running on HHVM if (false === $file && defined('HHVM_VERSION')) { $file = $this->findFileWithExtension($class, '.hh'); } if (null !== $this->apcuPrefix) { apcu_add($this->apcuPrefix.$class, $file); } if (false === $file) { // Remember that this class does not exist. $this->missingClasses[$class] = true; } return $file; } private function findFileWithExtension($class, $ext) { // PSR-4 lookup $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; $first = $class[0]; if (isset($this->prefixLengthsPsr4[$first])) { $subPath = $class; while (false !== $lastPos = strrpos($subPath, '\\')) { $subPath = substr($subPath, 0, $lastPos); $search = $subPath . '\\'; if (isset($this->prefixDirsPsr4[$search])) { $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { if (file_exists($file = $dir . $pathEnd)) { return $file; } } } } } // PSR-4 fallback dirs foreach ($this->fallbackDirsPsr4 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { return $file; } } // PSR-0 lookup if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); } else { // PEAR-like class name $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; } if (isset($this->prefixesPsr0[$first])) { foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos($class, $prefix)) { foreach ($dirs as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } } } } // PSR-0 fallback dirs foreach ($this->fallbackDirsPsr0 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } // PSR-0 include paths. if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { return $file; } return false; } } /** * Scope isolated include. * * Prevents access to $this/self from included files. */ function includeFile($file) { include $file; } array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'), '_HumbugBoxd02f763d3c56\\XdgBaseDir\\' => array($vendorDir . '/dnoegel/php-xdg-base-dir/src'), '_HumbugBoxd02f763d3c56\\Webmozart\\PathUtil\\' => array($vendorDir . '/webmozart/path-util/src'), '_HumbugBoxd02f763d3c56\\Webmozart\\Glob\\' => array($vendorDir . '/webmozart/glob/src'), '_HumbugBoxd02f763d3c56\\Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'), '_HumbugBoxd02f763d3c56\\Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), '_HumbugBoxd02f763d3c56\\Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), '_HumbugBoxd02f763d3c56\\Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), '_HumbugBoxd02f763d3c56\\Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), '_HumbugBoxd02f763d3c56\\Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), '_HumbugBoxd02f763d3c56\\Psr\\Container\\' => array($vendorDir . '/psr/container/src'), '_HumbugBoxd02f763d3c56\\PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), '_HumbugBoxd02f763d3c56\\PackageVersions\\' => array($vendorDir . '/composer/package-versions-deprecated/src/PackageVersions'), '_HumbugBoxd02f763d3c56\\LanguageServerProtocol\\' => array($vendorDir . '/felixfbecker/language-server-protocol/src'), '_HumbugBoxd02f763d3c56\\LSS\\' => array($vendorDir . '/openlss/lib-array2xml/LSS'), '_HumbugBoxd02f763d3c56\\JsonMapper\\' => array($vendorDir . '/netresearch/jsonmapper/src/JsonMapper'), '_HumbugBoxd02f763d3c56\\Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'), '_HumbugBoxd02f763d3c56\\Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'), '_HumbugBoxd02f763d3c56\\Amp\\ByteStream\\' => array($vendorDir . '/amphp/byte-stream/lib'), '_HumbugBoxd02f763d3c56\\Amp\\' => array($vendorDir . '/amphp/amp/lib'), '_HumbugBoxd02f763d3c56\\AdvancedJsonRpc\\' => array($vendorDir . '/felixfbecker/advanced-json-rpc/lib'), 'Psalm\\' => array($baseDir . '/src/Psalm'), ); $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'e8aa6e4b5a1db2f56ae794f1505391a8' => $vendorDir . '/amphp/amp/lib/functions.php', '76cd0796156622033397994f25b0d8fc' => $vendorDir . '/amphp/amp/lib/Internal/functions.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', '6cd5651c4fef5ed6b63e8d8b8ffbf3cc' => $vendorDir . '/amphp/byte-stream/lib/functions.php', 'dc51568953534d6c54b08731e61104e2' => $baseDir . '/src/functions.php', '8e4171839e12546525126d38dac3dafa' => $baseDir . '/src/spl_object_id.php', ); Copyright (c) Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ private static function getVersions(array $packageData) : \Generator { foreach ($packageData as $package) { (yield $package['name'] => $package['version'] . '@' . ($package['source']['reference'] ?? $package['dist']['reference'] ?? '')); } (yield self::ROOT_PACKAGE_NAME => self::ROOT_PACKAGE_NAME); } } * @internal */ const VERSIONS = %s; private function __construct() { } /** * @psalm-pure * * @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not * cause any side effects here. */ public static function rootPackageName() : string { if (!class_exists(InstalledVersions::class, false) || !InstalledVersions::getRawData()) { return self::ROOT_PACKAGE_NAME; } return InstalledVersions::getRootPackage()['name']; } /** * @throws OutOfBoundsException If a version cannot be located. * * @psalm-param key-of $packageName * @psalm-pure * * @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not * cause any side effects here. */ public static function getVersion(string $packageName): string { if (class_exists(InstalledVersions::class, false) && InstalledVersions::getRawData()) { return InstalledVersions::getPrettyVersion($packageName) . '@' . InstalledVersions::getReference($packageName); } if (isset(self::VERSIONS[$packageName])) { return self::VERSIONS[$packageName]; } throw new OutOfBoundsException( 'Required package "' . $packageName . '" is not installed: check your ./vendor/composer/installed.json and/or ./composer.lock files' ); } } PHP; public function activate(\_HumbugBoxd02f763d3c56\Composer\Composer $composer, \_HumbugBoxd02f763d3c56\Composer\IO\IOInterface $io) { // Nothing to do here, as all features are provided through event listeners } public function deactivate(\_HumbugBoxd02f763d3c56\Composer\Composer $composer, \_HumbugBoxd02f763d3c56\Composer\IO\IOInterface $io) { // Nothing to do here, as all features are provided through event listeners } public function uninstall(\_HumbugBoxd02f763d3c56\Composer\Composer $composer, \_HumbugBoxd02f763d3c56\Composer\IO\IOInterface $io) { // Nothing to do here, as all features are provided through event listeners } /** * {@inheritDoc} */ public static function getSubscribedEvents() : array { return [\_HumbugBoxd02f763d3c56\Composer\Script\ScriptEvents::POST_AUTOLOAD_DUMP => 'dumpVersionsClass']; } /** * @throws RuntimeException */ public static function dumpVersionsClass(\_HumbugBoxd02f763d3c56\Composer\Script\Event $composerEvent) { $composer = $composerEvent->getComposer(); $rootPackage = $composer->getPackage(); $versions = \iterator_to_array(self::getVersions($composer->getLocker(), $rootPackage)); if (!\array_key_exists('composer/package-versions-deprecated', $versions)) { //plugin must be globally installed - we only want to generate versions for projects which specifically //require composer/package-versions-deprecated return; } $versionClass = self::generateVersionsClass($rootPackage->getName(), $versions); self::writeVersionClassToFile($versionClass, $composer, $composerEvent->getIO()); } /** * @param string[] $versions */ private static function generateVersionsClass(string $rootPackageName, array $versions) : string { return \sprintf( self::$generatedClassTemplate, 'fin' . 'al ' . 'cla' . 'ss ' . 'Versions', // note: workaround for regex-based code parsers :-( $rootPackageName, \var_export($versions, \true) ); } /** * @throws RuntimeException */ private static function writeVersionClassToFile(string $versionClassSource, \_HumbugBoxd02f763d3c56\Composer\Composer $composer, \_HumbugBoxd02f763d3c56\Composer\IO\IOInterface $io) { $installPath = self::locateRootPackageInstallPath($composer->getConfig(), $composer->getPackage()) . '/src/PackageVersions/Versions.php'; $installDir = \dirname($installPath); if (!\file_exists($installDir)) { $io->write('composer/package-versions-deprecated: Package not found (probably scheduled for removal); generation of version class skipped.'); return; } if (!\is_writable($installDir)) { $io->write(\sprintf('composer/package-versions-deprecated: %s is not writable; generation of version class skipped.', $installDir)); return; } $io->write('composer/package-versions-deprecated: Generating version class...'); $installPathTmp = $installPath . '_' . \uniqid('tmp', \true); \file_put_contents($installPathTmp, $versionClassSource); \chmod($installPathTmp, 0664); \rename($installPathTmp, $installPath); $io->write('composer/package-versions-deprecated: ...done generating version class'); } /** * @throws RuntimeException */ private static function locateRootPackageInstallPath(\_HumbugBoxd02f763d3c56\Composer\Config $composerConfig, \_HumbugBoxd02f763d3c56\Composer\Package\RootPackageInterface $rootPackage) : string { if (self::getRootPackageAlias($rootPackage)->getName() === 'composer/package-versions-deprecated') { return \dirname($composerConfig->get('vendor-dir')); } return $composerConfig->get('vendor-dir') . '/composer/package-versions-deprecated'; } private static function getRootPackageAlias(\_HumbugBoxd02f763d3c56\Composer\Package\RootPackageInterface $rootPackage) : \_HumbugBoxd02f763d3c56\Composer\Package\PackageInterface { $package = $rootPackage; while ($package instanceof \_HumbugBoxd02f763d3c56\Composer\Package\AliasPackage) { $package = $package->getAliasOf(); } return $package; } /** * @return Generator&string[] * * @psalm-return Generator */ private static function getVersions(\_HumbugBoxd02f763d3c56\Composer\Package\Locker $locker, \_HumbugBoxd02f763d3c56\Composer\Package\RootPackageInterface $rootPackage) : \Generator { $lockData = $locker->getLockData(); $lockData['packages-dev'] = $lockData['packages-dev'] ?? []; foreach (\array_merge($lockData['packages'], $lockData['packages-dev']) as $package) { (yield $package['name'] => $package['version'] . '@' . ($package['source']['reference'] ?? $package['dist']['reference'] ?? '')); } foreach ($rootPackage->getReplaces() as $replace) { $version = $replace->getPrettyConstraint(); if ($version === 'self.version') { $version = $rootPackage->getPrettyVersion(); } (yield $replace->getTarget() => $version . '@' . $rootPackage->getSourceReference()); } (yield $rootPackage->getName() => $rootPackage->getPrettyVersion() . '@' . $rootPackage->getSourceReference()); } } * @internal */ const VERSIONS = array('amphp/amp' => 'v2.5.0@f220a51458bf4dd0dedebb171ac3457813c72bbc', 'amphp/byte-stream' => 'v1.8.0@f0c20cf598a958ba2aa8c6e5a71c697d652c7088', 'composer/package-versions-deprecated' => '1.11.99@c8c9aa8a14cc3d3bec86d0a8c3fa52ea79936855', 'composer/semver' => '3.2.2@4089fddb67bcf6bf860d91b979e95be303835002', 'composer/xdebug-handler' => '1.4.3@ebd27a9866ae8254e873866f795491f02418c5a5', 'dnoegel/php-xdg-base-dir' => 'v0.1.1@8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd', 'felixfbecker/advanced-json-rpc' => 'v3.1.1@0ed363f8de17d284d479ec813c9ad3f6834b5c40', 'felixfbecker/language-server-protocol' => 'v1.4.0@378801f6139bb74ac215d81cca1272af61df9a9f', 'netresearch/jsonmapper' => 'v2.1.0@e0f1e33a71587aca81be5cffbb9746510e1fe04e', 'nikic/php-parser' => 'v4.10.2@658f1be311a230e0907f5dfe0213742aff0596de', 'openlss/lib-array2xml' => '1.0.0@a91f18a8dfc69ffabe5f9b068bc39bb202c81d90', 'phpdocumentor/reflection-common' => '2.2.0@1d01c49d4ed62f25aa84a747ad35d5a16924662b', 'phpdocumentor/reflection-docblock' => '5.2.2@069a785b2141f5bcf49f3e353548dc1cce6df556', 'phpdocumentor/type-resolver' => '1.4.0@6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0', 'psr/container' => '1.0.0@b7ce3b176482dbbc1245ebf52b181af44c2cf55f', 'psr/log' => '1.1.3@0f73288fd15629204f9d42b7055f72dacbe811fc', 'sebastian/diff' => '4.0.3@ffc949a1a2aae270ea064453d7535b82e4c32092', 'symfony/console' => 'v5.1.7@ae789a8a2ad189ce7e8216942cdb9b77319f5eb8', 'symfony/polyfill-ctype' => 'v1.18.1@1c302646f6efc070cd46856e600e5e0684d6b454', 'symfony/polyfill-intl-grapheme' => 'v1.18.1@b740103edbdcc39602239ee8860f0f45a8eb9aa5', 'symfony/polyfill-intl-normalizer' => 'v1.18.1@37078a8dd4a2a1e9ab0231af7c6cb671b2ed5a7e', 'symfony/polyfill-mbstring' => 'v1.18.1@a6977d63bf9a0ad4c65cd352709e230876f9904a', 'symfony/polyfill-php73' => 'v1.18.1@fffa1a52a023e782cdcc221d781fe1ec8f87fcca', 'symfony/polyfill-php80' => 'v1.18.1@d87d5766cbf48d72388a9f6b85f280c8ad51f981', 'symfony/service-contracts' => 'v2.2.0@d15da7ba4957ffb8f1747218be9e1a121fd298a1', 'symfony/string' => 'v5.1.7@4a9afe9d07bac506f75bcee8ed3ce76da5a9343e', 'webmozart/assert' => '1.9.1@bafc69caeb4d49c39fd0779086c03a3738cbb389', 'webmozart/glob' => '4.1.0@3cbf63d4973cf9d780b93d2da8eec7e4a9e63bbe', 'webmozart/path-util' => '2.3.0@d939f7edc24c9a1bb9c0dee5cb05d8e859490725', 'bamarni/composer-bin-plugin' => '1.4.1@9329fb0fbe29e0e1b2db8f4639a193e4f5406225', 'brianium/habitat' => 'v1.0.0@d0979e3bb379cbc78ecb42b3ac171bc2b7e06d96', 'brianium/paratest' => '4.2.0@88e4d87421279457c765abf5db54e1de71f31845', 'doctrine/instantiator' => '1.3.1@f350df0268e904597e3bd9c4685c53e0e333feea', 'myclabs/deep-copy' => '1.10.1@969b211f9a51aa1f6c01d1d2aef56d3bd91598e5', 'phar-io/manifest' => '2.0.1@85265efd3af7ba3ca4b2a2c34dbfc5788dd29133', 'phar-io/version' => '3.0.2@c6bb6825def89e0a32220f88337f8ceaf1975fa0', 'phpmyadmin/sql-parser' => '5.1.0@33e531b0dddbbf75a55c830b2186ae7287e99a58', 'phpspec/prophecy' => '1.12.1@8ce87516be71aae9b956f81906aaf0338e0d8a2d', 'phpspec/prophecy-phpunit' => 'v2.0.1@2d7a9df55f257d2cba9b1d0c0963a54960657177', 'phpstan/phpdoc-parser' => '0.3.5@8c4ef2aefd9788238897b678a985e1d5c8df6db4', 'phpunit/php-code-coverage' => '9.2.0@53a4b737e83be724efd2bc4e7b929b9a30c48972', 'phpunit/php-file-iterator' => '3.0.5@aa4be8575f26070b100fccb67faabb28f21f66f8', 'phpunit/php-invoker' => '3.1.1@5a10147d0aaf65b58940a0b72f71c9ac0423cc67', 'phpunit/php-text-template' => '2.0.3@18c887016e60e52477e54534956d7b47bc52cd84', 'phpunit/php-timer' => '5.0.2@c9ff14f493699e2f6adee9fd06a0245b276643b7', 'phpunit/phpunit' => '9.4.2@3866b2eeeed21b1b099c4bc0b7a1690ac6fd5baa', 'psalm/plugin-phpunit' => '0.13.0@e006914489f3e445f5cb786ea6f3df89ea30129b', 'sebastian/cli-parser' => '1.0.1@442e7c7e687e42adc03470c7b668bc4b2402c0b2', 'sebastian/code-unit' => '1.0.7@59236be62b1bb9919e6d7f60b0b832dc05cef9ab', 'sebastian/code-unit-reverse-lookup' => '2.0.3@ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5', 'sebastian/comparator' => '4.0.5@7a8ff306445707539c1a6397372a982a1ec55120', 'sebastian/complexity' => '2.0.1@ba8cc2da0c0bfbc813d03b56406734030c7f1eff', 'sebastian/environment' => '5.1.3@388b6ced16caa751030f6a69e588299fa09200ac', 'sebastian/exporter' => '4.0.3@d89cc98761b8cb5a1a235a6b703ae50d34080e65', 'sebastian/global-state' => '5.0.1@ea779cb749a478b22a2564ac41cd7bda79c78dc7', 'sebastian/lines-of-code' => '1.0.1@6514b8f21906b8b46f520d1fbd17a4523fa59a54', 'sebastian/object-enumerator' => '4.0.3@f6f5957013d84725427d361507e13513702888a4', 'sebastian/object-reflector' => '2.0.3@d9d0ab3b12acb1768bc1e0a89b23c90d2043cbe5', 'sebastian/recursion-context' => '4.0.3@ed8c9cd355089134bc9cba421b5cfdd58f0eaef7', 'sebastian/resource-operations' => '3.0.3@0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8', 'sebastian/type' => '2.3.0@fa592377f3923946cb90bf1f6a71ba2e5f229909', 'sebastian/version' => '3.0.2@c6c1022351a901512170118436c764e473f6de8c', 'slevomat/coding-standard' => '5.0.4@287ac3347c47918c0bf5e10335e36197ea10894c', 'squizlabs/php_codesniffer' => '3.5.6@e97627871a7eab2f70e59166072a6b767d5834e0', 'symfony/process' => 'v4.4.15@9b887acc522935f77555ae8813495958c7771ba7', 'theseer/tokenizer' => '1.2.0@75a63c33a8577608444246075ea0af0d052e452a', 'weirdan/prophecy-shim' => '2.0.2@385837ffb01e3fae638ad6187bda817953dbad24', 'vimeo/psalm' => '4.0.1@b1e2e30026936ef8d5bf6a354d1c3959b6231f44'); private function __construct() { } /** * @psalm-pure * * @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not * cause any side effects here. */ public static function rootPackageName() : string { if (!\class_exists(\_HumbugBoxd02f763d3c56\Composer\InstalledVersions::class, \false) || !\_HumbugBoxd02f763d3c56\Composer\InstalledVersions::getRawData()) { return self::ROOT_PACKAGE_NAME; } return \_HumbugBoxd02f763d3c56\Composer\InstalledVersions::getRootPackage()['name']; } /** * @throws OutOfBoundsException If a version cannot be located. * * @psalm-param key-of $packageName * @psalm-pure * * @psalm-suppress ImpureMethodCall we know that {@see InstalledVersions} interaction does not * cause any side effects here. */ public static function getVersion(string $packageName) : string { if (\class_exists(\_HumbugBoxd02f763d3c56\Composer\InstalledVersions::class, \false) && \_HumbugBoxd02f763d3c56\Composer\InstalledVersions::getRawData()) { return \_HumbugBoxd02f763d3c56\Composer\InstalledVersions::getPrettyVersion($packageName) . '@' . \_HumbugBoxd02f763d3c56\Composer\InstalledVersions::getReference($packageName); } if (isset(self::VERSIONS[$packageName])) { return self::VERSIONS[$packageName]; } throw new \OutOfBoundsException('Required package "' . $packageName . '" is not installed: check your ./vendor/composer/installed.json and/or ./composer.lock files'); } } Copyright (c) 2016 Marco Pivetta Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { require_once __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInit8efb600fd249dcbe30d3ad40e17221ec::getInitializer($loader)); } else { $classMap = require __DIR__ . '/autoload_classmap.php'; if ($classMap) { $loader->addClassMap($classMap); } } $loader->setClassMapAuthoritative(true); $loader->register(true); if ($useStaticLoader) { $includeFiles = Composer\Autoload\ComposerStaticInit8efb600fd249dcbe30d3ad40e17221ec::$files; } else { $includeFiles = require __DIR__ . '/autoload_files.php'; } foreach ($includeFiles as $fileIdentifier => $file) { composerRequire8efb600fd249dcbe30d3ad40e17221ec($fileIdentifier, $file); } return $loader; } } function composerRequire8efb600fd249dcbe30d3ad40e17221ec($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { require $file; $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchAllConstraint; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchNoneConstraint; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint; /** * Helper class generating intervals from constraints * * This contains utilities for: * * - compacting an existing constraint which can be used to combine several into one * by creating a MultiConstraint out of the many constraints you have. * * - checking whether one subset is a subset of another. * * Note: You should call clear to free memoization memory usage when you are done using this class */ class Intervals { /** * @phpstan-var array */ private static $intervalsCache = array(); /** * @phpstan-var array */ private static $opSortOrder = array('>=' => -3, '<' => -2, '>' => 2, '<=' => 3); /** * Clears the memoization cache once you are done * * @return void */ public static function clear() { self::$intervalsCache = array(); } /** * Checks whether $candidate is a subset of $constraint * * @return bool */ public static function isSubsetOf(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $candidate, \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $constraint) { if ($constraint instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchAllConstraint) { return \true; } if ($candidate instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchNoneConstraint || $constraint instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchNoneConstraint) { return \false; } $intersectionIntervals = self::get(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint(array($candidate, $constraint), \true)); $candidateIntervals = self::get($candidate); if (\count($intersectionIntervals['numeric']) !== \count($candidateIntervals['numeric'])) { return \false; } foreach ($intersectionIntervals['numeric'] as $index => $interval) { if (!isset($candidateIntervals['numeric'][$index])) { return \false; } if ((string) $candidateIntervals['numeric'][$index]->getStart() !== (string) $interval->getStart()) { return \false; } if ((string) $candidateIntervals['numeric'][$index]->getEnd() !== (string) $interval->getEnd()) { return \false; } } if ($intersectionIntervals['branches']['exclude'] !== $candidateIntervals['branches']['exclude']) { return \false; } if (\count($intersectionIntervals['branches']['names']) !== \count($candidateIntervals['branches']['names'])) { return \false; } foreach ($intersectionIntervals['branches']['names'] as $index => $name) { if ($name !== $candidateIntervals['branches']['names'][$index]) { return \false; } } return \true; } /** * Checks whether $a and $b have any intersection, equivalent to $a->matches($b) * * @return bool */ public static function haveIntersections(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $a, \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $b) { if ($a instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchAllConstraint || $b instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchAllConstraint) { return \true; } if ($a instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchNoneConstraint || $b instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchNoneConstraint) { return \false; } $intersectionIntervals = self::generateIntervals(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint(array($a, $b), \true), \true); return \count($intersectionIntervals['numeric']) > 0 || $intersectionIntervals['branches']['exclude'] || \count($intersectionIntervals['branches']['names']) > 0; } /** * Attempts to optimize a MultiConstraint * * When merging MultiConstraints together they can get very large, this will * compact it by looking at the real intervals covered by all the constraints * and then creates a new constraint containing only the smallest amount of rules * to match the same intervals. * * @return ConstraintInterface */ public static function compactConstraint(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $constraint) { if (!$constraint instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint) { return $constraint; } $intervals = self::generateIntervals($constraint); $constraints = array(); $hasNumericMatchAll = \false; if (\count($intervals['numeric']) === 1 && (string) $intervals['numeric'][0]->getStart() === (string) \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::fromZero() && (string) $intervals['numeric'][0]->getEnd() === (string) \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::untilPositiveInfinity()) { $constraints[] = $intervals['numeric'][0]->getStart(); $hasNumericMatchAll = \true; } else { $unEqualConstraints = array(); for ($i = 0, $count = \count($intervals['numeric']); $i < $count; $i++) { $interval = $intervals['numeric'][$i]; // if current interval ends with < N and next interval begins with > N we can swap this out for != N // but this needs to happen as a conjunctive expression together with the start of the current interval // and end of next interval, so [>=M, N, [>=M, !=N, getEnd()->getOperator() === '<' && $i + 1 < $count) { $nextInterval = $intervals['numeric'][$i + 1]; if ($interval->getEnd()->getVersion() === $nextInterval->getStart()->getVersion() && $nextInterval->getStart()->getOperator() === '>') { // only add a start if we didn't already do so, can be skipped if we're looking at second // interval in [>=M, N, P, =M, !=N] already and we only want to add !=P right now if (\count($unEqualConstraints) === 0 && (string) $interval->getStart() !== (string) \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::fromZero()) { $unEqualConstraints[] = $interval->getStart(); } $unEqualConstraints[] = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('!=', $interval->getEnd()->getVersion()); continue; } } if (\count($unEqualConstraints) > 0) { // this is where the end of the following interval of a != constraint is added as explained above if ((string) $interval->getEnd() !== (string) \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::untilPositiveInfinity()) { $unEqualConstraints[] = $interval->getEnd(); } // count is 1 if entire constraint is just one != expression if (\count($unEqualConstraints) > 1) { $constraints[] = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint($unEqualConstraints, \true); } else { $constraints[] = $unEqualConstraints[0]; } $unEqualConstraints = array(); continue; } // convert back >= x - <= x intervals to == x if ($interval->getStart()->getVersion() === $interval->getEnd()->getVersion() && $interval->getStart()->getOperator() === '>=' && $interval->getEnd()->getOperator() === '<=') { $constraints[] = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('==', $interval->getStart()->getVersion()); continue; } if ((string) $interval->getStart() === (string) \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::fromZero()) { $constraints[] = $interval->getEnd(); } elseif ((string) $interval->getEnd() === (string) \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::untilPositiveInfinity()) { $constraints[] = $interval->getStart(); } else { $constraints[] = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint(array($interval->getStart(), $interval->getEnd()), \true); } } } $devConstraints = array(); if (0 === \count($intervals['branches']['names'])) { if ($intervals['branches']['exclude']) { if ($hasNumericMatchAll) { return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchAllConstraint(); } // otherwise constraint should contain a != operator and already cover this } } else { foreach ($intervals['branches']['names'] as $branchName) { if ($intervals['branches']['exclude']) { $devConstraints[] = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('!=', $branchName); } else { $devConstraints[] = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('==', $branchName); } } // excluded branches, e.g. != dev-foo are conjunctive with the interval, so // > 2.0 != dev-foo must return a conjunctive constraint if ($intervals['branches']['exclude']) { if (\count($constraints) > 1) { return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint(\array_merge(array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint($constraints, \false)), $devConstraints), \true); } if (\count($constraints) === 1 && (string) $constraints[0] === (string) \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::fromZero()) { if (\count($devConstraints) > 1) { return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint($devConstraints, \true); } return $devConstraints[0]; } return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint(\array_merge($constraints, $devConstraints), \true); } // otherwise devConstraints contains a list of == operators for branches which are disjunctive with the // rest of the constraint $constraints = \array_merge($constraints, $devConstraints); } if (\count($constraints) > 1) { return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint($constraints, \false); } if (\count($constraints) === 1) { return $constraints[0]; } return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchNoneConstraint(); } /** * Creates an array of numeric intervals and branch constraints representing a given constraint * * if the returned numeric array is empty it means the constraint matches nothing in the numeric range (0 - +inf) * if the returned branches array is empty it means no dev-* versions are matched * if a constraint matches all possible dev-* versions, branches will contain Interval::anyDev() * * @return array * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} */ public static function get(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $constraint) { $key = (string) $constraint; if (!isset(self::$intervalsCache[$key])) { self::$intervalsCache[$key] = self::generateIntervals($constraint); } return self::$intervalsCache[$key]; } /** * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} */ private static function generateIntervals(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $constraint, $stopOnFirstValidInterval = \false) { if ($constraint instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchAllConstraint) { return array('numeric' => array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Interval(\_HumbugBoxd02f763d3c56\Composer\Semver\Interval::fromZero(), \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::untilPositiveInfinity())), 'branches' => \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::anyDev()); } if ($constraint instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchNoneConstraint) { return array('numeric' => array(), 'branches' => array('names' => array(), 'exclude' => \false)); } if ($constraint instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint) { return self::generateSingleConstraintIntervals($constraint); } if (!$constraint instanceof \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint) { throw new \UnexpectedValueException('The constraint passed in should be an MatchAllConstraint, Constraint or MultiConstraint instance, got ' . \get_class($constraint) . '.'); } $constraints = $constraint->getConstraints(); $numericGroups = array(); $constraintBranches = array(); foreach ($constraints as $c) { $res = self::get($c); $numericGroups[] = $res['numeric']; $constraintBranches[] = $res['branches']; } if ($constraint->isDisjunctive()) { $branches = \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::noDev(); foreach ($constraintBranches as $b) { if ($b['exclude']) { if ($branches['exclude']) { // disjunctive constraint, so only exclude what's excluded in all constraints // !=a,!=b || !=b,!=c => !=b $branches['names'] = \array_intersect($branches['names'], $b['names']); } else { // disjunctive constraint so exclude all names which are not explicitly included in the alternative // (==b || ==c) || !=a,!=b => !=a $branches['exclude'] = \true; $branches['names'] = \array_diff($b['names'], $branches['names']); } } else { if ($branches['exclude']) { // disjunctive constraint so exclude all names which are not explicitly included in the alternative // !=a,!=b || (==b || ==c) => !=a $branches['names'] = \array_diff($branches['names'], $b['names']); } else { // disjunctive constraint, so just add all the other branches // (==a || ==b) || ==c => ==a || ==b || ==c $branches['names'] = \array_merge($branches['names'], $b['names']); } } } } else { $branches = \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::anyDev(); foreach ($constraintBranches as $b) { if ($b['exclude']) { if ($branches['exclude']) { // conjunctive, so just add all branch names to be excluded // !=a && !=b => !=a,!=b $branches['names'] = \array_merge($branches['names'], $b['names']); } else { // conjunctive, so only keep included names which are not excluded // (==a||==c) && !=a,!=b => ==c $branches['names'] = \array_diff($branches['names'], $b['names']); } } else { if ($branches['exclude']) { // conjunctive, so only keep included names which are not excluded // !=a,!=b && (==a||==c) => ==c $branches['names'] = \array_diff($b['names'], $branches['names']); $branches['exclude'] = \false; } else { // conjunctive, so only keep names that are included in both // (==a||==b) && (==a||==c) => ==a $branches['names'] = \array_intersect($branches['names'], $b['names']); } } } } $branches['names'] = \array_unique($branches['names']); if (\count($numericGroups) === 1) { return array('numeric' => $numericGroups[0], 'branches' => $branches); } $borders = array(); foreach ($numericGroups as $group) { foreach ($group as $interval) { $borders[] = array('version' => $interval->getStart()->getVersion(), 'operator' => $interval->getStart()->getOperator(), 'side' => 'start'); $borders[] = array('version' => $interval->getEnd()->getVersion(), 'operator' => $interval->getEnd()->getOperator(), 'side' => 'end'); } } $opSortOrder = self::$opSortOrder; \usort($borders, function ($a, $b) use($opSortOrder) { $order = \version_compare($a['version'], $b['version']); if ($order === 0) { return $opSortOrder[$a['operator']] - $opSortOrder[$b['operator']]; } return $order; }); $activeIntervals = 0; $intervals = array(); $index = 0; $activationThreshold = $constraint->isConjunctive() ? \count($numericGroups) : 1; $active = \false; $start = null; foreach ($borders as $border) { if ($border['side'] === 'start') { $activeIntervals++; } else { $activeIntervals--; } if (!$active && $activeIntervals >= $activationThreshold) { $start = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint($border['operator'], $border['version']); $active = \true; } if ($active && $activeIntervals < $activationThreshold) { $active = \false; // filter out invalid intervals like > x - <= x, or >= x - < x if (\version_compare($start->getVersion(), $border['version'], '=') && ($start->getOperator() === '>' && $border['operator'] === '<=' || $start->getOperator() === '>=' && $border['operator'] === '<')) { unset($intervals[$index]); } else { $intervals[$index] = new \_HumbugBoxd02f763d3c56\Composer\Semver\Interval($start, new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint($border['operator'], $border['version'])); $index++; if ($stopOnFirstValidInterval) { break; } } $start = null; } } return array('numeric' => $intervals, 'branches' => $branches); } /** * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}}} */ private static function generateSingleConstraintIntervals(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint $constraint) { $op = $constraint->getOperator(); // handle branch constraints first if (\strpos($constraint->getVersion(), 'dev-') === 0) { $intervals = array(); $branches = array('names' => array(), 'exclude' => \false); // != dev-foo means any numeric version may match, we treat >/< like != they are not really defined for branches if ($op === '!=') { $intervals[] = new \_HumbugBoxd02f763d3c56\Composer\Semver\Interval(\_HumbugBoxd02f763d3c56\Composer\Semver\Interval::fromZero(), \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::untilPositiveInfinity()); $branches = array('names' => array($constraint->getVersion()), 'exclude' => \true); } elseif ($op === '==') { $branches['names'][] = $constraint->getVersion(); } return array('numeric' => $intervals, 'branches' => $branches); } if ($op[0] === '>') { // > & >= return array('numeric' => array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Interval($constraint, \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::untilPositiveInfinity())), 'branches' => \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::noDev()); } if ($op[0] === '<') { // < & <= return array('numeric' => array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Interval(\_HumbugBoxd02f763d3c56\Composer\Semver\Interval::fromZero(), $constraint)), 'branches' => \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::noDev()); } if ($op === '!=') { // convert !=x to intervals of 0 - x - +inf + dev* return array('numeric' => array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Interval(\_HumbugBoxd02f763d3c56\Composer\Semver\Interval::fromZero(), new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('<', $constraint->getVersion())), new \_HumbugBoxd02f763d3c56\Composer\Semver\Interval(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('>', $constraint->getVersion()), \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::untilPositiveInfinity())), 'branches' => \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::anyDev()); } // convert ==x to an interval of >=x - <=x return array('numeric' => array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Interval(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('>=', $constraint->getVersion()), new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('<=', $constraint->getVersion()))), 'branches' => \_HumbugBoxd02f763d3c56\Composer\Semver\Interval::noDev()); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchAllConstraint; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint; /** * Version parser. * * @author Jordi Boggiano */ class VersionParser { /** * Regex to match pre-release data (sort of). * * Due to backwards compatibility: * - Instead of enforcing hyphen, an underscore, dot or nothing at all are also accepted. * - Only stabilities as recognized by Composer are allowed to precede a numerical identifier. * - Numerical-only pre-release identifiers are not supported, see tests. * * |--------------| * [major].[minor].[patch] -[pre-release] +[build-metadata] * * @var string */ private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\\d+)*+)?)?([.-]?dev)?'; /** @var string */ private static $stabilitiesRegex = 'stable|RC|beta|alpha|dev'; /** * Returns the stability of a version. * * @param string $version * * @return string */ public static function parseStability($version) { $version = \preg_replace('{#.+$}', '', $version); if (\strpos($version, 'dev-') === 0 || '-dev' === \substr($version, -4)) { return 'dev'; } \preg_match('{' . self::$modifierRegex . '(?:\\+.*)?$}i', \strtolower($version), $match); if (!empty($match[3])) { return 'dev'; } if (!empty($match[1])) { if ('beta' === $match[1] || 'b' === $match[1]) { return 'beta'; } if ('alpha' === $match[1] || 'a' === $match[1]) { return 'alpha'; } if ('rc' === $match[1]) { return 'RC'; } } return 'stable'; } /** * @param string $stability * * @return string */ public static function normalizeStability($stability) { $stability = \strtolower($stability); return $stability === 'rc' ? 'RC' : $stability; } /** * Normalizes a version string to be able to perform comparisons on it. * * @param string $version * @param string $fullVersion optional complete version string to give more context * * @throws \UnexpectedValueException * * @return string */ public function normalize($version, $fullVersion = null) { $version = \trim($version); $origVersion = $version; if (null === $fullVersion) { $fullVersion = $version; } // strip off aliasing if (\preg_match('{^([^,\\s]++) ++as ++([^,\\s]++)$}', $version, $match)) { $version = $match[1]; } // strip off stability flag if (\preg_match('{@(?:' . self::$stabilitiesRegex . ')$}i', $version, $match)) { $version = \substr($version, 0, \strlen($version) - \strlen($match[0])); } // normalize master/trunk/default branches to dev-name for BC with 1.x as these used to be valid constraints if (\in_array($version, array('master', 'trunk', 'default'), \true)) { $version = 'dev-' . $version; } // if requirement is branch-like, use full name if (\stripos($version, 'dev-') === 0) { return 'dev-' . \substr($version, 4); } // strip off build metadata if (\preg_match('{^([^,\\s+]++)\\+[^\\s]++$}', $version, $match)) { $version = $match[1]; } // match classical versioning if (\preg_match('{^v?(\\d{1,5})(\\.\\d++)?(\\.\\d++)?(\\.\\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) { $version = $matches[1] . (!empty($matches[2]) ? $matches[2] : '.0') . (!empty($matches[3]) ? $matches[3] : '.0') . (!empty($matches[4]) ? $matches[4] : '.0'); $index = 5; // match date(time) based versioning } elseif (\preg_match('{^v?(\\d{4}(?:[.:-]?\\d{2}){1,6}(?:[.:-]?\\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) { $version = \preg_replace('{\\D}', '.', $matches[1]); $index = 2; } // add version modifiers if a version was matched if (isset($index)) { if (!empty($matches[$index])) { if ('stable' === $matches[$index]) { return $version; } $version .= '-' . $this->expandStability($matches[$index]) . (isset($matches[$index + 1]) && '' !== $matches[$index + 1] ? \ltrim($matches[$index + 1], '.-') : ''); } if (!empty($matches[$index + 2])) { $version .= '-dev'; } return $version; } // match dev branches if (\preg_match('{(.*?)[.-]?dev$}i', $version, $match)) { try { $normalized = $this->normalizeBranch($match[1]); // a branch ending with -dev is only valid if it is numeric // if it gets prefixed with dev- it means the branch name should // have had a dev- prefix already when passed to normalize if (\strpos($normalized, 'dev-') === \false) { return $normalized; } } catch (\Exception $e) { } } $extraMessage = ''; if (\preg_match('{ +as +' . \preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))?$}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version'; } elseif (\preg_match('{^' . \preg_quote($version) . '(?:@(?:' . self::$stabilitiesRegex . '))? +as +}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-'; } throw new \UnexpectedValueException('Invalid version string "' . $origVersion . '"' . $extraMessage); } /** * Extract numeric prefix from alias, if it is in numeric format, suitable for version comparison. * * @param string $branch Branch name (e.g. 2.1.x-dev) * * @return string|false Numeric prefix if present (e.g. 2.1.) or false */ public function parseNumericAliasPrefix($branch) { if (\preg_match('{^(?P(\\d++\\.)*\\d++)(?:\\.x)?-dev$}i', $branch, $matches)) { return $matches['version'] . '.'; } return \false; } /** * Normalizes a branch name to be able to perform comparisons on it. * * @param string $name * * @return string */ public function normalizeBranch($name) { $name = \trim($name); if (\preg_match('{^v?(\\d++)(\\.(?:\\d++|[xX*]))?(\\.(?:\\d++|[xX*]))?(\\.(?:\\d++|[xX*]))?$}i', $name, $matches)) { $version = ''; for ($i = 1; $i < 5; ++$i) { $version .= isset($matches[$i]) ? \str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x'; } return \str_replace('x', '9999999', $version) . '-dev'; } return 'dev-' . $name; } /** * Normalizes a default branch name (i.e. master on git) to 9999999-dev. * * @param string $name * * @return string */ public function normalizeDefaultBranch($name) { if ($name === 'dev-master' || $name === 'dev-default' || $name === 'dev-trunk') { return '9999999-dev'; } return $name; } /** * Parses a constraint string into MultiConstraint and/or Constraint objects. * * @param string $constraints * * @return ConstraintInterface */ public function parseConstraints($constraints) { $prettyConstraint = $constraints; $orConstraints = \preg_split('{\\s*\\|\\|?\\s*}', \trim($constraints)); $orGroups = array(); foreach ($orConstraints as $constraints) { $andConstraints = \preg_split('{(?< ,]) *(? 1) { $constraintObjects = array(); foreach ($andConstraints as $constraint) { foreach ($this->parseConstraint($constraint) as $parsedConstraint) { $constraintObjects[] = $parsedConstraint; } } } else { $constraintObjects = $this->parseConstraint($andConstraints[0]); } if (1 === \count($constraintObjects)) { $constraint = $constraintObjects[0]; } else { $constraint = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint($constraintObjects); } $orGroups[] = $constraint; } $constraint = \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint::create($orGroups, \false); $constraint->setPrettyString($prettyConstraint); return $constraint; } /** * @param string $constraint * * @throws \UnexpectedValueException * * @return array */ private function parseConstraint($constraint) { // strip off aliasing if (\preg_match('{^([^,\\s]++) ++as ++([^,\\s]++)$}', $constraint, $match)) { $constraint = $match[1]; } // strip @stability flags, and keep it for later use if (\preg_match('{^([^,\\s]*?)@(' . self::$stabilitiesRegex . ')$}i', $constraint, $match)) { $constraint = '' !== $match[1] ? $match[1] : '*'; if ($match[2] !== 'stable') { $stabilityModifier = $match[2]; } } // get rid of #refs as those are used by composer only if (\preg_match('{^(dev-[^,\\s@]+?|[^,\\s@]+?\\.x-dev)#.+$}i', $constraint, $match)) { $constraint = $match[1]; } if (\preg_match('{^(v)?[xX*](\\.[xX*])*$}i', $constraint, $match)) { if (!empty($match[1]) || !empty($match[2])) { return array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('>=', '0.0.0.0-dev')); } return array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchAllConstraint()); } $versionRegex = 'v?(\\d++)(?:\\.(\\d++))?(?:\\.(\\d++))?(?:\\.(\\d++))?(?:' . self::$modifierRegex . '|\\.([xX*][.-]?dev))(?:\\+[^\\s]+)?'; // Tilde Range // // Like wildcard constraints, unsuffixed tilde constraints say that they must be greater than the previous // version, to ensure that unstable instances of the current version are allowed. However, if a stability // suffix is added to the constraint, then a >= match on the current version is used instead. if (\preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) { if (\strpos($constraint, '~>') === 0) { throw new \UnexpectedValueException('Could not parse version constraint ' . $constraint . ': ' . 'Invalid operator "~>", you probably meant to use the "~" operator'); } // Work out which position in the version we are operating at if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) { $position = 4; } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } // when matching 2.x-dev or 3.0.x-dev we have to shift the second or third number, despite no second/third number matching above if (!empty($matches[8])) { $position++; } // Calculate the stability suffix $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(\substr($constraint . $stabilitySuffix, 1)); $lowerBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('>=', $lowVersion); // For upper bound, we increment the position of one more significance, // but highPosition = 0 would be illegal $highPosition = \max(1, $position - 1); $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev'; $upperBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('<', $highVersion); return array($lowerBound, $upperBound); } // Caret Range // // Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple. // In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for // versions 0.X >=0.1.0, and no updates for versions 0.0.X if (\preg_match('{^\\^' . $versionRegex . '($)}i', $constraint, $matches)) { // Work out which position in the version we are operating at if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) { $position = 1; } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) { $position = 2; } else { $position = 3; } // Calculate the stability suffix $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(\substr($constraint . $stabilitySuffix, 1)); $lowerBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('>=', $lowVersion); // For upper bound, we increment the position of one more significance, // but highPosition = 0 would be illegal $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; $upperBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('<', $highVersion); return array($lowerBound, $upperBound); } // X Range // // Any of X, x, or * may be used to "stand in" for one of the numeric values in the [major, minor, patch] tuple. // A partial version range is treated as an X-Range, so the special character is in fact optional. if (\preg_match('{^v?(\\d++)(?:\\.(\\d++))?(?:\\.(\\d++))?(?:\\.[xX*])++$}', $constraint, $matches)) { if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev'; $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; if ($lowVersion === '0.0.0.0-dev') { return array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('<', $highVersion)); } return array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('>=', $lowVersion), new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('<', $highVersion)); } // Hyphen Range // // Specifies an inclusive set. If a partial version is provided as the first version in the inclusive range, // then the missing pieces are replaced with zeroes. If a partial version is provided as the second version in // the inclusive range, then all versions that start with the supplied parts of the tuple are accepted, but // nothing that would be greater than the provided tuple parts. if (\preg_match('{^(?P' . $versionRegex . ') +- +(?P' . $versionRegex . ')($)}i', $constraint, $matches)) { // Calculate the stability suffix $lowStabilitySuffix = ''; if (empty($matches[6]) && empty($matches[8]) && empty($matches[9])) { $lowStabilitySuffix = '-dev'; } $lowVersion = $this->normalize($matches['from']); $lowerBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('>=', $lowVersion . $lowStabilitySuffix); $empty = function ($x) { return $x === 0 || $x === '0' ? \false : empty($x); }; if (!$empty($matches[12]) && !$empty($matches[13]) || !empty($matches[15]) || !empty($matches[17]) || !empty($matches[18])) { $highVersion = $this->normalize($matches['to']); $upperBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('<=', $highVersion); } else { $highMatch = array('', $matches[11], $matches[12], $matches[13], $matches[14]); // validate to version $this->normalize($matches['to']); $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[12]) ? 1 : 2, 1) . '-dev'; $upperBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('<', $highVersion); } return array($lowerBound, $upperBound); } // Basic Comparators if (\preg_match('{^(<>|!=|>=?|<=?|==?)?\\s*(.*)}', $constraint, $matches)) { try { try { $version = $this->normalize($matches[2]); } catch (\UnexpectedValueException $e) { // recover from an invalid constraint like foobar-dev which should be dev-foobar // except if the constraint uses a known operator, in which case it must be a parse error if (\substr($matches[2], -4) === '-dev' && \preg_match('{^[0-9a-zA-Z-./]+$}', $matches[2])) { $version = $this->normalize('dev-' . \substr($matches[2], 0, -4)); } else { throw $e; } } $op = $matches[1] ?: '='; if ($op !== '==' && $op !== '=' && !empty($stabilityModifier) && self::parseStability($version) === 'stable') { $version .= '-' . $stabilityModifier; } elseif ('<' === $op || '>=' === $op) { if (!\preg_match('/-' . self::$modifierRegex . '$/', \strtolower($matches[2]))) { if (\strpos($matches[2], 'dev-') !== 0) { $version .= '-dev'; } } } return array(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint($matches[1] ?: '=', $version)); } catch (\Exception $e) { } } $message = 'Could not parse version constraint ' . $constraint; if (isset($e)) { $message .= ': ' . $e->getMessage(); } throw new \UnexpectedValueException($message); } /** * Increment, decrement, or simply pad a version number. * * Support function for {@link parseConstraint()} * * @param array $matches Array with version parts in array indexes 1,2,3,4 * @param int $position 1,2,3,4 - which segment of the version to increment/decrement * @param int $increment * @param string $pad The string to pad version parts after $position * * @return string|null The new version */ private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0') { for ($i = 4; $i > 0; --$i) { if ($i > $position) { $matches[$i] = $pad; } elseif ($i === $position && $increment) { $matches[$i] += $increment; // If $matches[$i] was 0, carry the decrement if ($matches[$i] < 0) { $matches[$i] = $pad; --$position; // Return null on a carry overflow if ($i === 1) { return null; } } } } return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4]; } /** * Expand shorthand stability string to long version. * * @param string $stability * * @return string */ private function expandStability($stability) { $stability = \strtolower($stability); switch ($stability) { case 'a': return 'alpha'; case 'b': return 'beta'; case 'p': case 'pl': return 'patch'; case 'rc': return 'RC'; default: return $stability; } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint; class Semver { const SORT_ASC = 1; const SORT_DESC = -1; /** @var VersionParser */ private static $versionParser; /** * Determine if given version satisfies given constraints. * * @param string $version * @param string $constraints * * @return bool */ public static function satisfies($version, $constraints) { if (null === self::$versionParser) { self::$versionParser = new \_HumbugBoxd02f763d3c56\Composer\Semver\VersionParser(); } $versionParser = self::$versionParser; $provider = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('==', $versionParser->normalize($version)); $parsedConstraints = $versionParser->parseConstraints($constraints); return $parsedConstraints->matches($provider); } /** * Return all versions that satisfy given constraints. * * @param array $versions * @param string $constraints * * @return array */ public static function satisfiedBy(array $versions, $constraints) { $versions = \array_filter($versions, function ($version) use($constraints) { return \_HumbugBoxd02f763d3c56\Composer\Semver\Semver::satisfies($version, $constraints); }); return \array_values($versions); } /** * Sort given array of versions. * * @param array $versions * * @return array */ public static function sort(array $versions) { return self::usort($versions, self::SORT_ASC); } /** * Sort given array of versions in reverse. * * @param array $versions * * @return array */ public static function rsort(array $versions) { return self::usort($versions, self::SORT_DESC); } /** * @param array $versions * @param int $direction * * @return array */ private static function usort(array $versions, $direction) { if (null === self::$versionParser) { self::$versionParser = new \_HumbugBoxd02f763d3c56\Composer\Semver\VersionParser(); } $versionParser = self::$versionParser; $normalized = array(); // Normalize outside of usort() scope for minor performance increase. // Creates an array of arrays: [[normalized, key], ...] foreach ($versions as $key => $version) { $normalizedVersion = $versionParser->normalize($version); $normalizedVersion = $versionParser->normalizeDefaultBranch($normalizedVersion); $normalized[] = array($normalizedVersion, $key); } \usort($normalized, function (array $left, array $right) use($direction) { if ($left[0] === $right[0]) { return 0; } if (\_HumbugBoxd02f763d3c56\Composer\Semver\Comparator::lessThan($left[0], $right[0])) { return -$direction; } return $direction; }); // Recreate input array, using the original indexes which are now in sorted order. $sorted = array(); foreach ($normalized as $item) { $sorted[] = $versions[$item[1]]; } return $sorted; } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver\Constraint; /** * Defines a constraint. */ class Constraint implements \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface { /* operator integer values */ const OP_EQ = 0; const OP_LT = 1; const OP_LE = 2; const OP_GT = 3; const OP_GE = 4; const OP_NE = 5; /** * Operator to integer translation table. * * @var array * @phpstan-var array */ private static $transOpStr = array('=' => self::OP_EQ, '==' => self::OP_EQ, '<' => self::OP_LT, '<=' => self::OP_LE, '>' => self::OP_GT, '>=' => self::OP_GE, '<>' => self::OP_NE, '!=' => self::OP_NE); /** * Integer to operator translation table. * * @var array * @phpstan-var array */ private static $transOpInt = array(self::OP_EQ => '==', self::OP_LT => '<', self::OP_LE => '<=', self::OP_GT => '>', self::OP_GE => '>=', self::OP_NE => '!='); /** * @var int * @phpstan-var self::OP_* */ protected $operator; /** @var string */ protected $version; /** @var string|null */ protected $prettyString; /** @var Bound */ protected $lowerBound; /** @var Bound */ protected $upperBound; /** * Sets operator and version to compare with. * * @param string $operator * @param string $version * * @throws \InvalidArgumentException if invalid operator is given. */ public function __construct($operator, $version) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(\sprintf('Invalid operator "%s" given, expected one of: %s', $operator, \implode(', ', self::getSupportedOperators()))); } $this->operator = self::$transOpStr[$operator]; $this->version = $version; } public function getVersion() { return $this->version; } public function getOperator() { return self::$transOpInt[$this->operator]; } /** * @param ConstraintInterface $provider * * @return bool */ public function matches(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $provider) { if ($provider instanceof self) { return $this->matchSpecific($provider); } // turn matching around to find a match return $provider->matches($this); } /** * @param string|null $prettyString */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * @return string */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return $this->__toString(); } /** * Get all supported comparison operators. * * @return array */ public static function getSupportedOperators() { return \array_keys(self::$transOpStr); } /** * @param string $operator * @return int * * @phpstan-return self::OP_* */ public static function getOperatorConstant($operator) { return self::$transOpStr[$operator]; } /** * @param string $a * @param string $b * @param string $operator * @param bool $compareBranches * * @throws \InvalidArgumentException if invalid operator is given. * * @return bool */ public function versionCompare($a, $b, $operator, $compareBranches = \false) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(\sprintf('Invalid operator "%s" given, expected one of: %s', $operator, \implode(', ', self::getSupportedOperators()))); } $aIsBranch = \strpos($a, 'dev-') === 0; $bIsBranch = \strpos($b, 'dev-') === 0; if ($operator === '!=' && ($aIsBranch || $bIsBranch)) { return $a !== $b; } if ($aIsBranch && $bIsBranch) { return $operator === '==' && $a === $b; } // when branches are not comparable, we make sure dev branches never match anything if (!$compareBranches && ($aIsBranch || $bIsBranch)) { return \false; } return \version_compare($a, $b, $operator); } public function compile($otherOperator) { if (\strpos($this->version, 'dev-') === 0) { if (self::OP_EQ === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('$b && $v === %s', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return \sprintf('!$b || $v !== %s', \var_export($this->version, \true)); } return 'false'; } if (self::OP_NE === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('!$b || $v !== %s', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return 'true'; } return '!$b'; } return 'false'; } if (self::OP_EQ === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('\\version_compare($v, %s, \'==\')', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return \sprintf('$b || \\version_compare($v, %s, \'!=\')', \var_export($this->version, \true)); } return \sprintf('!$b && \\version_compare(%s, $v, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$otherOperator]); } if (self::OP_NE === $this->operator) { if (self::OP_EQ === $otherOperator) { return \sprintf('$b || (!$b && \\version_compare($v, %s, \'!=\'))', \var_export($this->version, \true)); } if (self::OP_NE === $otherOperator) { return 'true'; } return '!$b'; } if (self::OP_LT === $this->operator || self::OP_LE === $this->operator) { if (self::OP_LT === $otherOperator || self::OP_LE === $otherOperator) { return '!$b'; } } elseif (self::OP_GT === $this->operator || self::OP_GE === $this->operator) { if (self::OP_GT === $otherOperator || self::OP_GE === $otherOperator) { return '!$b'; } } if (self::OP_NE === $otherOperator) { return 'true'; } $codeComparison = \sprintf('\\version_compare($v, %s, \'%s\')', \var_export($this->version, \true), self::$transOpInt[$this->operator]); if ($this->operator === self::OP_LE) { if ($otherOperator === self::OP_GT) { return \sprintf('!$b && \\version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison; } } elseif ($this->operator === self::OP_GE) { if ($otherOperator === self::OP_LT) { return \sprintf('!$b && \\version_compare($v, %s, \'!=\') && ', \var_export($this->version, \true)) . $codeComparison; } } return \sprintf('!$b && %s', $codeComparison); } /** * @param Constraint $provider * @param bool $compareBranches * * @return bool */ public function matchSpecific(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint $provider, $compareBranches = \false) { $noEqualOp = \str_replace('=', '', self::$transOpInt[$this->operator]); $providerNoEqualOp = \str_replace('=', '', self::$transOpInt[$provider->operator]); $isEqualOp = self::OP_EQ === $this->operator; $isNonEqualOp = self::OP_NE === $this->operator; $isProviderEqualOp = self::OP_EQ === $provider->operator; $isProviderNonEqualOp = self::OP_NE === $provider->operator; // '!=' operator is match when other operator is not '==' operator or version is not match // these kinds of comparisons always have a solution if ($isNonEqualOp || $isProviderNonEqualOp) { if ($isNonEqualOp && !$isProviderNonEqualOp && !$isProviderEqualOp && \strpos($provider->version, 'dev-') === 0) { return \false; } if ($isProviderNonEqualOp && !$isNonEqualOp && !$isEqualOp && \strpos($this->version, 'dev-') === 0) { return \false; } if (!$isEqualOp && !$isProviderEqualOp) { return \true; } return $this->versionCompare($provider->version, $this->version, '!=', $compareBranches); } // an example for the condition is <= 2.0 & < 1.0 // these kinds of comparisons always have a solution if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) { return !(\strpos($this->version, 'dev-') === 0 || \strpos($provider->version, 'dev-') === 0); } $version1 = $isEqualOp ? $this->version : $provider->version; $version2 = $isEqualOp ? $provider->version : $this->version; $operator = $isEqualOp ? $provider->operator : $this->operator; if ($this->versionCompare($version1, $version2, self::$transOpInt[$operator], $compareBranches)) { // special case, e.g. require >= 1.0 and provide < 1.0 // 1.0 >= 1.0 but 1.0 is outside of the provided interval return !(self::$transOpInt[$provider->operator] === $providerNoEqualOp && self::$transOpInt[$this->operator] !== $noEqualOp && \version_compare($provider->version, $this->version, '==')); } return \false; } /** * @return string */ public function __toString() { return self::$transOpInt[$this->operator] . ' ' . $this->version; } /** * {@inheritDoc} */ public function getLowerBound() { $this->extractBounds(); return $this->lowerBound; } /** * {@inheritDoc} */ public function getUpperBound() { $this->extractBounds(); return $this->upperBound; } private function extractBounds() { if (null !== $this->lowerBound) { return; } // Branches if (\strpos($this->version, 'dev-') === 0) { $this->lowerBound = \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::zero(); $this->upperBound = \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::positiveInfinity(); return; } switch ($this->operator) { case self::OP_EQ: $this->lowerBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound($this->version, \true); $this->upperBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound($this->version, \true); break; case self::OP_LT: $this->lowerBound = \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::zero(); $this->upperBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound($this->version, \false); break; case self::OP_LE: $this->lowerBound = \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::zero(); $this->upperBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound($this->version, \true); break; case self::OP_GT: $this->lowerBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound($this->version, \false); $this->upperBound = \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::positiveInfinity(); break; case self::OP_GE: $this->lowerBound = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound($this->version, \true); $this->upperBound = \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::positiveInfinity(); break; case self::OP_NE: $this->lowerBound = \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::zero(); $this->upperBound = \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::positiveInfinity(); break; } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver\Constraint; /** * Defines a conjunctive or disjunctive set of constraints. */ class MultiConstraint implements \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface { /** @var ConstraintInterface[] */ protected $constraints; /** @var string|null */ protected $prettyString; /** @var string|null */ protected $string; /** @var bool */ protected $conjunctive; /** @var Bound|null */ protected $lowerBound; /** @var Bound|null */ protected $upperBound; /** * @param ConstraintInterface[] $constraints A set of constraints * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive * * @throws \InvalidArgumentException If less than 2 constraints are passed */ public function __construct(array $constraints, $conjunctive = \true) { if (\count($constraints) < 2) { throw new \InvalidArgumentException('Must provide at least two constraints for a MultiConstraint. Use ' . 'the regular Constraint class for one constraint only or MatchAllConstraint for none. You may use ' . 'MultiConstraint::create() which optimizes and handles those cases automatically.'); } $this->constraints = $constraints; $this->conjunctive = $conjunctive; } /** * @return ConstraintInterface[] */ public function getConstraints() { return $this->constraints; } /** * @return bool */ public function isConjunctive() { return $this->conjunctive; } /** * @return bool */ public function isDisjunctive() { return !$this->conjunctive; } public function compile($otherOperator) { $parts = array(); foreach ($this->constraints as $constraint) { $code = $constraint->compile($otherOperator); if ($code === 'true') { if (!$this->conjunctive) { return 'true'; } } elseif ($code === 'false') { if ($this->conjunctive) { return 'false'; } } else { $parts[] = '(' . $code . ')'; } } if (!$parts) { return $this->conjunctive ? 'true' : 'false'; } return $this->conjunctive ? \implode('&&', $parts) : \implode('||', $parts); } /** * @param ConstraintInterface $provider * * @return bool */ public function matches(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $provider) { if (\false === $this->conjunctive) { foreach ($this->constraints as $constraint) { if ($provider->matches($constraint)) { return \true; } } return \false; } foreach ($this->constraints as $constraint) { if (!$provider->matches($constraint)) { return \false; } } return \true; } /** * @param string|null $prettyString */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * @return string */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } /** * @return string */ public function __toString() { if ($this->string !== null) { return $this->string; } $constraints = array(); foreach ($this->constraints as $constraint) { $constraints[] = (string) $constraint; } return $this->string = '[' . \implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']'; } /** * {@inheritDoc} */ public function getLowerBound() { $this->extractBounds(); return $this->lowerBound; } /** * {@inheritDoc} */ public function getUpperBound() { $this->extractBounds(); return $this->upperBound; } /** * Tries to optimize the constraints as much as possible, meaning * reducing/collapsing congruent constraints etc. * Does not necessarily return a MultiConstraint instance if * things can be reduced to a simple constraint * * @param ConstraintInterface[] $constraints A set of constraints * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive * * @return ConstraintInterface */ public static function create(array $constraints, $conjunctive = \true) { if (0 === \count($constraints)) { return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MatchAllConstraint(); } if (1 === \count($constraints)) { return $constraints[0]; } $optimized = self::optimizeConstraints($constraints, $conjunctive); if ($optimized !== null) { list($constraints, $conjunctive) = $optimized; if (\count($constraints) === 1) { return $constraints[0]; } } return new self($constraints, $conjunctive); } /** * @return array|null */ private static function optimizeConstraints(array $constraints, $conjunctive) { // parse the two OR groups and if they are contiguous we collapse // them into one constraint // [>= 1 < 2] || [>= 2 < 3] || [>= 3 < 4] => [>= 1 < 4] if (!$conjunctive) { $left = $constraints[0]; $mergedConstraints = array(); $optimized = \false; for ($i = 1, $l = \count($constraints); $i < $l; $i++) { $right = $constraints[$i]; if ($left instanceof self && $left->conjunctive && $right instanceof self && $right->conjunctive && ($left0 = (string) $left->constraints[0]) && $left0[0] === '>' && $left0[1] === '=' && ($left1 = (string) $left->constraints[1]) && $left1[0] === '<' && ($right0 = (string) $right->constraints[0]) && $right0[0] === '>' && $right0[1] === '=' && ($right1 = (string) $right->constraints[1]) && $right1[0] === '<' && \substr($left1, 2) === \substr($right0, 3)) { $optimized = \true; $left = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\MultiConstraint(\array_merge(array($left->constraints[0], $right->constraints[1]), \array_slice($left->constraints, 2), \array_slice($right->constraints, 2)), \true); } else { $mergedConstraints[] = $left; $left = $right; } } if ($optimized) { $mergedConstraints[] = $left; return array($mergedConstraints, \false); } } // TODO: Here's the place to put more optimizations return null; } private function extractBounds() { if (null !== $this->lowerBound) { return; } foreach ($this->constraints as $constraint) { if (null === $this->lowerBound && null === $this->upperBound) { $this->lowerBound = $constraint->getLowerBound(); $this->upperBound = $constraint->getUpperBound(); continue; } if ($constraint->getLowerBound()->compareTo($this->lowerBound, $this->isConjunctive() ? '>' : '<')) { $this->lowerBound = $constraint->getLowerBound(); } if ($constraint->getUpperBound()->compareTo($this->upperBound, $this->isConjunctive() ? '<' : '>')) { $this->upperBound = $constraint->getUpperBound(); } } } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver\Constraint; /** * Blackhole of constraints, nothing escapes it */ class MatchNoneConstraint implements \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface { /** @var string|null */ protected $prettyString; /** * @param ConstraintInterface $provider * * @return bool */ public function matches(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $provider) { return \false; } public function compile($operator) { return 'false'; } /** * @param string|null $prettyString */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * @return string */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } /** * @return string */ public function __toString() { return '[]'; } /** * {@inheritDoc} */ public function getUpperBound() { return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound('0.0.0.0-dev', \false); } /** * {@inheritDoc} */ public function getLowerBound() { return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound('0.0.0.0-dev', \false); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver\Constraint; /** * DO NOT IMPLEMENT this interface. It is only meant for usage as a type hint * in libraries relying on composer/semver but creating your own constraint class * that implements this interface is not a supported use case and will cause the * composer/semver components to return unexpected results. */ interface ConstraintInterface { /** * Checks whether the given constraint intersects in any way with this constraint * * @param ConstraintInterface $provider * * @return bool */ public function matches(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $provider); /** * Provides a compiled version of the constraint for the given operator * The compiled version must be a PHP expression. * Executor of compile version must provide 2 variables: * - $v = the string version to compare with * - $b = whether or not the version is a non-comparable branch (starts with "dev-") * * @see Constraint::OP_* for the list of available operators. * @example return '!$b && version_compare($v, '1.0', '>')'; * * @param int $operator one Constraint::OP_* * * @return string */ public function compile($operator); /** * @return Bound */ public function getUpperBound(); /** * @return Bound */ public function getLowerBound(); /** * @return string */ public function getPrettyString(); /** * @param string|null $prettyString */ public function setPrettyString($prettyString); /** * @return string */ public function __toString(); } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver\Constraint; /** * Defines the absence of a constraint. * * This constraint matches everything. */ class MatchAllConstraint implements \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface { /** @var string|null */ protected $prettyString; /** * @param ConstraintInterface $provider * * @return bool */ public function matches(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $provider) { return \true; } public function compile($operator) { return 'true'; } /** * @param string|null $prettyString */ public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } /** * @return string */ public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return (string) $this; } /** * @return string */ public function __toString() { return '*'; } /** * {@inheritDoc} */ public function getUpperBound() { return \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::positiveInfinity(); } /** * {@inheritDoc} */ public function getLowerBound() { return \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound::zero(); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver\Constraint; class Bound { /** * @var string */ private $version; /** * @var bool */ private $isInclusive; /** * @param string $version * @param bool $isInclusive */ public function __construct($version, $isInclusive) { $this->version = $version; $this->isInclusive = $isInclusive; } /** * @return string */ public function getVersion() { return $this->version; } /** * @return bool */ public function isInclusive() { return $this->isInclusive; } public function isZero() { return $this->getVersion() === '0.0.0.0-dev' && $this->isInclusive(); } public function isPositiveInfinity() { return $this->getVersion() === \PHP_INT_MAX . '.0.0.0' && !$this->isInclusive(); } /** * Compares a bound to another with a given operator. * * @param Bound $other * @param string $operator * * @return bool */ public function compareTo(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound $other, $operator) { if (!\in_array($operator, array('<', '>'), \true)) { throw new \InvalidArgumentException('Does not support any other operator other than > or <.'); } // If they are the same it doesn't matter if ($this == $other) { return \false; } $compareResult = \version_compare($this->getVersion(), $other->getVersion()); // Not the same version means we don't need to check if the bounds are inclusive or not if (0 !== $compareResult) { return ('>' === $operator ? 1 : -1) === $compareResult; } // Question we're answering here is "am I higher than $other?" return '>' === $operator ? $other->isInclusive() : !$other->isInclusive(); } public function __toString() { return \sprintf('%s [%s]', $this->getVersion(), $this->isInclusive() ? 'inclusive' : 'exclusive'); } /** * @return self */ public static function zero() { return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound('0.0.0.0-dev', \true); } /** * @return self */ public static function positiveInfinity() { return new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Bound(\PHP_INT_MAX . '.0.0.0', \false); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint; class Interval { /** @var Constraint */ private $start; /** @var Constraint */ private $end; public function __construct(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint $start, \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint $end) { $this->start = $start; $this->end = $end; } /** * @return Constraint */ public function getStart() { return $this->start; } /** * @return Constraint */ public function getEnd() { return $this->end; } /** * @return Constraint */ public static function fromZero() { static $zero; if (null === $zero) { $zero = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('>=', '0.0.0.0-dev'); } return $zero; } /** * @return Constraint */ public static function untilPositiveInfinity() { static $positiveInfinity; if (null === $positiveInfinity) { $positiveInfinity = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('<', \PHP_INT_MAX . '.0.0.0'); } return $positiveInfinity; } /** * @return self */ public static function any() { return new self(self::fromZero(), self::untilPositiveInfinity()); } /** * @return array{'names': string[], 'exclude': bool} */ public static function anyDev() { // any == exclude nothing return array('names' => array(), 'exclude' => \true); } /** * @return array{'names': string[], 'exclude': bool} */ public static function noDev() { // nothing == no names included return array('names' => array(), 'exclude' => \false); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface; /** * Helper class to evaluate constraint by compiling and reusing the code to evaluate */ class CompilingMatcher { private static $compiledCheckerCache = array(); private static $enabled; /** * @phpstan-var array */ private static $transOpInt = array(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint::OP_EQ => '==', \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint::OP_LT => '<', \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint::OP_LE => '<=', \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint::OP_GT => '>', \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint::OP_GE => '>=', \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint::OP_NE => '!='); /** * Evaluates the expression: $constraint match $operator $version * * @param ConstraintInterface $constraint * @param int $operator * @phpstan-param Constraint::OP_* $operator * @param string $version * * @return mixed */ public static function match(\_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\ConstraintInterface $constraint, $operator, $version) { if (self::$enabled === null) { self::$enabled = !\in_array('eval', \explode(',', \ini_get('disable_functions')), \true); } if (!self::$enabled) { return $constraint->matches(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint(self::$transOpInt[$operator], $version)); } $cacheKey = $operator . $constraint; if (!isset(self::$compiledCheckerCache[$cacheKey])) { $code = $constraint->compile($operator); self::$compiledCheckerCache[$cacheKey] = $function = eval('return function($v, $b){return ' . $code . ';};'); } else { $function = self::$compiledCheckerCache[$cacheKey]; } return $function($version, \strpos($version, 'dev-') === 0); } } * * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\Composer\Semver; use _HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint; class Comparator { /** * Evaluates the expression: $version1 > $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function greaterThan($version1, $version2) { return self::compare($version1, '>', $version2); } /** * Evaluates the expression: $version1 >= $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function greaterThanOrEqualTo($version1, $version2) { return self::compare($version1, '>=', $version2); } /** * Evaluates the expression: $version1 < $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function lessThan($version1, $version2) { return self::compare($version1, '<', $version2); } /** * Evaluates the expression: $version1 <= $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function lessThanOrEqualTo($version1, $version2) { return self::compare($version1, '<=', $version2); } /** * Evaluates the expression: $version1 == $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function equalTo($version1, $version2) { return self::compare($version1, '==', $version2); } /** * Evaluates the expression: $version1 != $version2. * * @param string $version1 * @param string $version2 * * @return bool */ public static function notEqualTo($version1, $version2) { return self::compare($version1, '!=', $version2); } /** * Evaluates the expression: $version1 $operator $version2. * * @param string $version1 * @param string $operator * @param string $version2 * * @return bool */ public static function compare($version1, $operator, $version2) { $constraint = new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint($operator, $version2); return $constraint->matchSpecific(new \_HumbugBoxd02f763d3c56\Composer\Semver\Constraint\Constraint('==', $version1), \true); } } Copyright (C) 2015 Composer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; final class Diff { /** * @var string */ private $from; /** * @var string */ private $to; /** * @var Chunk[] */ private $chunks; /** * @param Chunk[] $chunks */ public function __construct(string $from, string $to, array $chunks = []) { $this->from = $from; $this->to = $to; $this->chunks = $chunks; } public function getFrom() : string { return $this->from; } public function getTo() : string { return $this->to; } /** * @return Chunk[] */ public function getChunks() : array { return $this->chunks; } /** * @param Chunk[] $chunks */ public function setChunks(array $chunks) : void { $this->chunks = $chunks; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output; /** * Defines how an output builder should take a generated * diff array and return a string representation of that diff. */ interface DiffOutputBuilderInterface { public function getDiff(array $diff) : string; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output; use function count; abstract class AbstractChunkOutputBuilder implements \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface { /** * Takes input of the diff array and returns the common parts. * Iterates through diff line by line. */ protected function getCommonChunks(array $diff, int $lineThreshold = 5) : array { $diffSize = \count($diff); $capturing = \false; $chunkStart = 0; $chunkSize = 0; $commonChunks = []; for ($i = 0; $i < $diffSize; ++$i) { if ($diff[$i][1] === 0) { if ($capturing === \false) { $capturing = \true; $chunkStart = $i; $chunkSize = 0; } else { ++$chunkSize; } } elseif ($capturing !== \false) { if ($chunkSize >= $lineThreshold) { $commonChunks[$chunkStart] = $chunkStart + $chunkSize; } $capturing = \false; } } if ($capturing !== \false && $chunkSize >= $lineThreshold) { $commonChunks[$chunkStart] = $chunkStart + $chunkSize; } return $commonChunks; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output; use function fclose; use function fopen; use function fwrite; use function stream_get_contents; use function substr; use _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ; /** * Builds a diff string representation in a loose unified diff format * listing only changes lines. Does not include line numbers. */ final class DiffOnlyOutputBuilder implements \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface { /** * @var string */ private $header; public function __construct(string $header = "--- Original\n+++ New\n") { $this->header = $header; } public function getDiff(array $diff) : string { $buffer = \fopen('php://memory', 'r+b'); if ('' !== $this->header) { \fwrite($buffer, $this->header); if ("\n" !== \substr($this->header, -1, 1)) { \fwrite($buffer, "\n"); } } foreach ($diff as $diffEntry) { if ($diffEntry[1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::ADDED) { \fwrite($buffer, '+' . $diffEntry[0]); } elseif ($diffEntry[1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::REMOVED) { \fwrite($buffer, '-' . $diffEntry[0]); } elseif ($diffEntry[1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::DIFF_LINE_END_WARNING) { \fwrite($buffer, ' ' . $diffEntry[0]); continue; // Warnings should not be tested for line break, it will always be there } else { /* Not changed (old) 0 */ continue; // we didn't write the non changs line, so do not add a line break either } $lc = \substr($diffEntry[0], -1); if ($lc !== "\n" && $lc !== "\r") { \fwrite($buffer, "\n"); // \No newline at end of file } } $diff = \stream_get_contents($buffer, -1, 0); \fclose($buffer); return $diff; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output; use function array_merge; use function array_splice; use function count; use function fclose; use function fopen; use function fwrite; use function is_bool; use function is_int; use function is_string; use function max; use function min; use function sprintf; use function stream_get_contents; use function substr; use _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\ConfigurationException; use _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ; /** * Strict Unified diff output builder. * * Generates (strict) Unified diff's (unidiffs) with hunks. */ final class StrictUnifiedDiffOutputBuilder implements \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface { private static $default = [ 'collapseRanges' => \true, // ranges of length one are rendered with the trailing `,1` 'commonLineThreshold' => 6, // number of same lines before ending a new hunk and creating a new one (if needed) 'contextLines' => 3, // like `diff: -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3 'fromFile' => null, 'fromFileDate' => null, 'toFile' => null, 'toFileDate' => null, ]; /** * @var bool */ private $changed; /** * @var bool */ private $collapseRanges; /** * @var int >= 0 */ private $commonLineThreshold; /** * @var string */ private $header; /** * @var int >= 0 */ private $contextLines; public function __construct(array $options = []) { $options = \array_merge(self::$default, $options); if (!\is_bool($options['collapseRanges'])) { throw new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\ConfigurationException('collapseRanges', 'a bool', $options['collapseRanges']); } if (!\is_int($options['contextLines']) || $options['contextLines'] < 0) { throw new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\ConfigurationException('contextLines', 'an int >= 0', $options['contextLines']); } if (!\is_int($options['commonLineThreshold']) || $options['commonLineThreshold'] <= 0) { throw new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\ConfigurationException('commonLineThreshold', 'an int > 0', $options['commonLineThreshold']); } $this->assertString($options, 'fromFile'); $this->assertString($options, 'toFile'); $this->assertStringOrNull($options, 'fromFileDate'); $this->assertStringOrNull($options, 'toFileDate'); $this->header = \sprintf("--- %s%s\n+++ %s%s\n", $options['fromFile'], null === $options['fromFileDate'] ? '' : "\t" . $options['fromFileDate'], $options['toFile'], null === $options['toFileDate'] ? '' : "\t" . $options['toFileDate']); $this->collapseRanges = $options['collapseRanges']; $this->commonLineThreshold = $options['commonLineThreshold']; $this->contextLines = $options['contextLines']; } public function getDiff(array $diff) : string { if (0 === \count($diff)) { return ''; } $this->changed = \false; $buffer = \fopen('php://memory', 'r+b'); \fwrite($buffer, $this->header); $this->writeDiffHunks($buffer, $diff); if (!$this->changed) { \fclose($buffer); return ''; } $diff = \stream_get_contents($buffer, -1, 0); \fclose($buffer); // If the last char is not a linebreak: add it. // This might happen when both the `from` and `to` do not have a trailing linebreak $last = \substr($diff, -1); return "\n" !== $last && "\r" !== $last ? $diff . "\n" : $diff; } private function writeDiffHunks($output, array $diff) : void { // detect "No newline at end of file" and insert into `$diff` if needed $upperLimit = \count($diff); if (0 === $diff[$upperLimit - 1][1]) { $lc = \substr($diff[$upperLimit - 1][0], -1); if ("\n" !== $lc) { \array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING]]); } } else { // search back for the last `+` and `-` line, // check if has trailing linebreak, else add under it warning under it $toFind = [1 => \true, 2 => \true]; for ($i = $upperLimit - 1; $i >= 0; --$i) { if (isset($toFind[$diff[$i][1]])) { unset($toFind[$diff[$i][1]]); $lc = \substr($diff[$i][0], -1); if ("\n" !== $lc) { \array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING]]); } if (!\count($toFind)) { break; } } } } // write hunks to output buffer $cutOff = \max($this->commonLineThreshold, $this->contextLines); $hunkCapture = \false; $sameCount = $toRange = $fromRange = 0; $toStart = $fromStart = 1; $i = 0; /** @var int $i */ foreach ($diff as $i => $entry) { if (0 === $entry[1]) { // same if (\false === $hunkCapture) { ++$fromStart; ++$toStart; continue; } ++$sameCount; ++$toRange; ++$fromRange; if ($sameCount === $cutOff) { $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines; // note: $contextEndOffset = $this->contextLines; // // because we never go beyond the end of the diff. // with the cutoff/contextlines here the follow is never true; // // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) { // $contextEndOffset = count($diff) - 1; // } // // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $cutOff + $this->contextLines + 1, $fromStart - $contextStartOffset, $fromRange - $cutOff + $contextStartOffset + $this->contextLines, $toStart - $contextStartOffset, $toRange - $cutOff + $contextStartOffset + $this->contextLines, $output); $fromStart += $fromRange; $toStart += $toRange; $hunkCapture = \false; $sameCount = $toRange = $fromRange = 0; } continue; } $sameCount = 0; if ($entry[1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING) { continue; } $this->changed = \true; if (\false === $hunkCapture) { $hunkCapture = $i; } if (\_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::ADDED === $entry[1]) { // added ++$toRange; } if (\_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::REMOVED === $entry[1]) { // removed ++$fromRange; } } if (\false === $hunkCapture) { return; } // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk, // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines; // prevent trying to write out more common lines than there are in the diff _and_ // do not write more than configured through the context lines $contextEndOffset = \min($sameCount, $this->contextLines); $fromRange -= $sameCount; $toRange -= $sameCount; $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $sameCount + $contextEndOffset + 1, $fromStart - $contextStartOffset, $fromRange + $contextStartOffset + $contextEndOffset, $toStart - $contextStartOffset, $toRange + $contextStartOffset + $contextEndOffset, $output); } private function writeHunk(array $diff, int $diffStartIndex, int $diffEndIndex, int $fromStart, int $fromRange, int $toStart, int $toRange, $output) : void { \fwrite($output, '@@ -' . $fromStart); if (!$this->collapseRanges || 1 !== $fromRange) { \fwrite($output, ',' . $fromRange); } \fwrite($output, ' +' . $toStart); if (!$this->collapseRanges || 1 !== $toRange) { \fwrite($output, ',' . $toRange); } \fwrite($output, " @@\n"); for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { if ($diff[$i][1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::ADDED) { $this->changed = \true; \fwrite($output, '+' . $diff[$i][0]); } elseif ($diff[$i][1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::REMOVED) { $this->changed = \true; \fwrite($output, '-' . $diff[$i][0]); } elseif ($diff[$i][1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::OLD) { \fwrite($output, ' ' . $diff[$i][0]); } elseif ($diff[$i][1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING) { $this->changed = \true; \fwrite($output, $diff[$i][0]); } //} elseif ($diff[$i][1] === Differ::DIFF_LINE_END_WARNING) { // custom comment inserted by PHPUnit/diff package // skip //} else { // unknown/invalid //} } } private function assertString(array $options, string $option) : void { if (!\is_string($options[$option])) { throw new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\ConfigurationException($option, 'a string', $options[$option]); } } private function assertStringOrNull(array $options, string $option) : void { if (null !== $options[$option] && !\is_string($options[$option])) { throw new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\ConfigurationException($option, 'a string or ', $options[$option]); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output; use function array_splice; use function count; use function fclose; use function fopen; use function fwrite; use function max; use function min; use function stream_get_contents; use function strlen; use function substr; use _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ; /** * Builds a diff string representation in unified diff format in chunks. */ final class UnifiedDiffOutputBuilder extends \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\AbstractChunkOutputBuilder { /** * @var bool */ private $collapseRanges = \true; /** * @var int >= 0 */ private $commonLineThreshold = 6; /** * @var int >= 0 */ private $contextLines = 3; /** * @var string */ private $header; /** * @var bool */ private $addLineNumbers; public function __construct(string $header = "--- Original\n+++ New\n", bool $addLineNumbers = \false) { $this->header = $header; $this->addLineNumbers = $addLineNumbers; } public function getDiff(array $diff) : string { $buffer = \fopen('php://memory', 'r+b'); if ('' !== $this->header) { \fwrite($buffer, $this->header); if ("\n" !== \substr($this->header, -1, 1)) { \fwrite($buffer, "\n"); } } if (0 !== \count($diff)) { $this->writeDiffHunks($buffer, $diff); } $diff = \stream_get_contents($buffer, -1, 0); \fclose($buffer); // If the diff is non-empty and last char is not a linebreak: add it. // This might happen when both the `from` and `to` do not have a trailing linebreak $last = \substr($diff, -1); return 0 !== \strlen($diff) && "\n" !== $last && "\r" !== $last ? $diff . "\n" : $diff; } private function writeDiffHunks($output, array $diff) : void { // detect "No newline at end of file" and insert into `$diff` if needed $upperLimit = \count($diff); if (0 === $diff[$upperLimit - 1][1]) { $lc = \substr($diff[$upperLimit - 1][0], -1); if ("\n" !== $lc) { \array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING]]); } } else { // search back for the last `+` and `-` line, // check if has trailing linebreak, else add under it warning under it $toFind = [1 => \true, 2 => \true]; for ($i = $upperLimit - 1; $i >= 0; --$i) { if (isset($toFind[$diff[$i][1]])) { unset($toFind[$diff[$i][1]]); $lc = \substr($diff[$i][0], -1); if ("\n" !== $lc) { \array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING]]); } if (!\count($toFind)) { break; } } } } // write hunks to output buffer $cutOff = \max($this->commonLineThreshold, $this->contextLines); $hunkCapture = \false; $sameCount = $toRange = $fromRange = 0; $toStart = $fromStart = 1; $i = 0; /** @var int $i */ foreach ($diff as $i => $entry) { if (0 === $entry[1]) { // same if (\false === $hunkCapture) { ++$fromStart; ++$toStart; continue; } ++$sameCount; ++$toRange; ++$fromRange; if ($sameCount === $cutOff) { $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines; // note: $contextEndOffset = $this->contextLines; // // because we never go beyond the end of the diff. // with the cutoff/contextlines here the follow is never true; // // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) { // $contextEndOffset = count($diff) - 1; // } // // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $cutOff + $this->contextLines + 1, $fromStart - $contextStartOffset, $fromRange - $cutOff + $contextStartOffset + $this->contextLines, $toStart - $contextStartOffset, $toRange - $cutOff + $contextStartOffset + $this->contextLines, $output); $fromStart += $fromRange; $toStart += $toRange; $hunkCapture = \false; $sameCount = $toRange = $fromRange = 0; } continue; } $sameCount = 0; if ($entry[1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING) { continue; } if (\false === $hunkCapture) { $hunkCapture = $i; } if (\_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::ADDED === $entry[1]) { ++$toRange; } if (\_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::REMOVED === $entry[1]) { ++$fromRange; } } if (\false === $hunkCapture) { return; } // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk, // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold $contextStartOffset = $hunkCapture - $this->contextLines < 0 ? $hunkCapture : $this->contextLines; // prevent trying to write out more common lines than there are in the diff _and_ // do not write more than configured through the context lines $contextEndOffset = \min($sameCount, $this->contextLines); $fromRange -= $sameCount; $toRange -= $sameCount; $this->writeHunk($diff, $hunkCapture - $contextStartOffset, $i - $sameCount + $contextEndOffset + 1, $fromStart - $contextStartOffset, $fromRange + $contextStartOffset + $contextEndOffset, $toStart - $contextStartOffset, $toRange + $contextStartOffset + $contextEndOffset, $output); } private function writeHunk(array $diff, int $diffStartIndex, int $diffEndIndex, int $fromStart, int $fromRange, int $toStart, int $toRange, $output) : void { if ($this->addLineNumbers) { \fwrite($output, '@@ -' . $fromStart); if (!$this->collapseRanges || 1 !== $fromRange) { \fwrite($output, ',' . $fromRange); } \fwrite($output, ' +' . $toStart); if (!$this->collapseRanges || 1 !== $toRange) { \fwrite($output, ',' . $toRange); } \fwrite($output, " @@\n"); } else { \fwrite($output, "@@ @@\n"); } for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { if ($diff[$i][1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::ADDED) { \fwrite($output, '+' . $diff[$i][0]); } elseif ($diff[$i][1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::REMOVED) { \fwrite($output, '-' . $diff[$i][0]); } elseif ($diff[$i][1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::OLD) { \fwrite($output, ' ' . $diff[$i][0]); } elseif ($diff[$i][1] === \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ::NO_LINE_END_EOF_WARNING) { \fwrite($output, "\n"); // $diff[$i][0] } else { /* Not changed (old) Differ::OLD or Warning Differ::DIFF_LINE_END_WARNING */ \fwrite($output, ' ' . $diff[$i][0]); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; use const PHP_INT_SIZE; use const PREG_SPLIT_DELIM_CAPTURE; use const PREG_SPLIT_NO_EMPTY; use function array_shift; use function array_unshift; use function array_values; use function count; use function current; use function end; use function get_class; use function gettype; use function is_array; use function is_object; use function is_string; use function key; use function min; use function preg_split; use function prev; use function reset; use function sprintf; use function substr; use _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface; use _HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; final class Differ { public const OLD = 0; public const ADDED = 1; public const REMOVED = 2; public const DIFF_LINE_END_WARNING = 3; public const NO_LINE_END_EOF_WARNING = 4; /** * @var DiffOutputBuilderInterface */ private $outputBuilder; /** * @param DiffOutputBuilderInterface $outputBuilder * * @throws InvalidArgumentException */ public function __construct($outputBuilder = null) { if ($outputBuilder instanceof \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\DiffOutputBuilderInterface) { $this->outputBuilder = $outputBuilder; } elseif (null === $outputBuilder) { $this->outputBuilder = new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder(); } elseif (\is_string($outputBuilder)) { // PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3 support // @see https://github.com/sebastianbergmann/phpunit/issues/2734#issuecomment-314514056 // @deprecated $this->outputBuilder = new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder($outputBuilder); } else { throw new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\InvalidArgumentException(\sprintf('Expected builder to be an instance of DiffOutputBuilderInterface, or a string, got %s.', \is_object($outputBuilder) ? 'instance of "' . \get_class($outputBuilder) . '"' : \gettype($outputBuilder) . ' "' . $outputBuilder . '"')); } } /** * Returns the diff between two arrays or strings as string. * * @param array|string $from * @param array|string $to */ public function diff($from, $to, \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator $lcs = null) : string { $diff = $this->diffToArray($this->normalizeDiffInput($from), $this->normalizeDiffInput($to), $lcs); return $this->outputBuilder->getDiff($diff); } /** * Returns the diff between two arrays or strings as array. * * Each array element contains two elements: * - [0] => mixed $token * - [1] => 2|1|0 * * - 2: REMOVED: $token was removed from $from * - 1: ADDED: $token was added to $from * - 0: OLD: $token is not changed in $to * * @param array|string $from * @param array|string $to * @param LongestCommonSubsequenceCalculator $lcs */ public function diffToArray($from, $to, \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator $lcs = null) : array { if (\is_string($from)) { $from = $this->splitStringByLines($from); } elseif (!\is_array($from)) { throw new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\InvalidArgumentException('"from" must be an array or string.'); } if (\is_string($to)) { $to = $this->splitStringByLines($to); } elseif (!\is_array($to)) { throw new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\InvalidArgumentException('"to" must be an array or string.'); } [$from, $to, $start, $end] = self::getArrayDiffParted($from, $to); if ($lcs === null) { $lcs = $this->selectLcsImplementation($from, $to); } $common = $lcs->calculate(\array_values($from), \array_values($to)); $diff = []; foreach ($start as $token) { $diff[] = [$token, self::OLD]; } \reset($from); \reset($to); foreach ($common as $token) { while (($fromToken = \reset($from)) !== $token) { $diff[] = [\array_shift($from), self::REMOVED]; } while (($toToken = \reset($to)) !== $token) { $diff[] = [\array_shift($to), self::ADDED]; } $diff[] = [$token, self::OLD]; \array_shift($from); \array_shift($to); } while (($token = \array_shift($from)) !== null) { $diff[] = [$token, self::REMOVED]; } while (($token = \array_shift($to)) !== null) { $diff[] = [$token, self::ADDED]; } foreach ($end as $token) { $diff[] = [$token, self::OLD]; } if ($this->detectUnmatchedLineEndings($diff)) { \array_unshift($diff, ["#Warning: Strings contain different line endings!\n", self::DIFF_LINE_END_WARNING]); } return $diff; } /** * Casts variable to string if it is not a string or array. * * @return array|string */ private function normalizeDiffInput($input) { if (!\is_array($input) && !\is_string($input)) { return (string) $input; } return $input; } /** * Checks if input is string, if so it will split it line-by-line. */ private function splitStringByLines(string $input) : array { return \preg_split('/(.*\\R)/', $input, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); } private function selectLcsImplementation(array $from, array $to) : \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator { // We do not want to use the time-efficient implementation if its memory // footprint will probably exceed this value. Note that the footprint // calculation is only an estimation for the matrix and the LCS method // will typically allocate a bit more memory than this. $memoryLimit = 100 * 1024 * 1024; if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) { return new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\MemoryEfficientLongestCommonSubsequenceCalculator(); } return new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\TimeEfficientLongestCommonSubsequenceCalculator(); } /** * Calculates the estimated memory footprint for the DP-based method. * * @return float|int */ private function calculateEstimatedFootprint(array $from, array $to) { $itemSize = \PHP_INT_SIZE === 4 ? 76 : 144; return $itemSize * \min(\count($from), \count($to)) ** 2; } /** * Returns true if line ends don't match in a diff. */ private function detectUnmatchedLineEndings(array $diff) : bool { $newLineBreaks = ['' => \true]; $oldLineBreaks = ['' => \true]; foreach ($diff as $entry) { if (self::OLD === $entry[1]) { $ln = $this->getLinebreak($entry[0]); $oldLineBreaks[$ln] = \true; $newLineBreaks[$ln] = \true; } elseif (self::ADDED === $entry[1]) { $newLineBreaks[$this->getLinebreak($entry[0])] = \true; } elseif (self::REMOVED === $entry[1]) { $oldLineBreaks[$this->getLinebreak($entry[0])] = \true; } } // if either input or output is a single line without breaks than no warning should be raised if (['' => \true] === $newLineBreaks || ['' => \true] === $oldLineBreaks) { return \false; } // two way compare foreach ($newLineBreaks as $break => $set) { if (!isset($oldLineBreaks[$break])) { return \true; } } foreach ($oldLineBreaks as $break => $set) { if (!isset($newLineBreaks[$break])) { return \true; } } return \false; } private function getLinebreak($line) : string { if (!\is_string($line)) { return ''; } $lc = \substr($line, -1); if ("\r" === $lc) { return "\r"; } if ("\n" !== $lc) { return ''; } if ("\r\n" === \substr($line, -2)) { return "\r\n"; } return "\n"; } private static function getArrayDiffParted(array &$from, array &$to) : array { $start = []; $end = []; \reset($to); foreach ($from as $k => $v) { $toK = \key($to); if ($toK === $k && $v === $to[$k]) { $start[$k] = $v; unset($from[$k], $to[$k]); } else { break; } } \end($from); \end($to); do { $fromK = \key($from); $toK = \key($to); if (null === $fromK || null === $toK || \current($from) !== \current($to)) { break; } \prev($from); \prev($to); $end = [$fromK => $from[$fromK]] + $end; unset($from[$fromK], $to[$toK]); } while (\true); return [$from, $to, $start, $end]; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; use function array_reverse; use function count; use function max; use SplFixedArray; final class TimeEfficientLongestCommonSubsequenceCalculator implements \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator { /** * {@inheritdoc} */ public function calculate(array $from, array $to) : array { $common = []; $fromLength = \count($from); $toLength = \count($to); $width = $fromLength + 1; $matrix = new \SplFixedArray($width * ($toLength + 1)); for ($i = 0; $i <= $fromLength; ++$i) { $matrix[$i] = 0; } for ($j = 0; $j <= $toLength; ++$j) { $matrix[$j * $width] = 0; } for ($i = 1; $i <= $fromLength; ++$i) { for ($j = 1; $j <= $toLength; ++$j) { $o = $j * $width + $i; $matrix[$o] = \max($matrix[$o - 1], $matrix[$o - $width], $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0); } } $i = $fromLength; $j = $toLength; while ($i > 0 && $j > 0) { if ($from[$i - 1] === $to[$j - 1]) { $common[] = $from[$i - 1]; --$i; --$j; } else { $o = $j * $width + $i; if ($matrix[$o - $width] > $matrix[$o - 1]) { --$j; } else { --$i; } } } return \array_reverse($common); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; use function array_pop; use function count; use function max; use function preg_match; use function preg_split; /** * Unified diff parser. */ final class Parser { /** * @return Diff[] */ public function parse(string $string) : array { $lines = \preg_split('(\\r\\n|\\r|\\n)', $string); if (!empty($lines) && $lines[\count($lines) - 1] === '') { \array_pop($lines); } $lineCount = \count($lines); $diffs = []; $diff = null; $collected = []; for ($i = 0; $i < $lineCount; ++$i) { if (\preg_match('(^---\\s+(?P\\S+))', $lines[$i], $fromMatch) && \preg_match('(^\\+\\+\\+\\s+(?P\\S+))', $lines[$i + 1], $toMatch)) { if ($diff !== null) { $this->parseFileDiff($diff, $collected); $diffs[] = $diff; $collected = []; } $diff = new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Diff($fromMatch['file'], $toMatch['file']); ++$i; } else { if (\preg_match('/^(?:diff --git |index [\\da-f\\.]+|[+-]{3} [ab])/', $lines[$i])) { continue; } $collected[] = $lines[$i]; } } if ($diff !== null && \count($collected)) { $this->parseFileDiff($diff, $collected); $diffs[] = $diff; } return $diffs; } private function parseFileDiff(\_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Diff $diff, array $lines) : void { $chunks = []; $chunk = null; $diffLines = []; foreach ($lines as $line) { if (\preg_match('/^@@\\s+-(?P\\d+)(?:,\\s*(?P\\d+))?\\s+\\+(?P\\d+)(?:,\\s*(?P\\d+))?\\s+@@/', $line, $match)) { $chunk = new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Chunk((int) $match['start'], isset($match['startrange']) ? \max(1, (int) $match['startrange']) : 1, (int) $match['end'], isset($match['endrange']) ? \max(1, (int) $match['endrange']) : 1); $chunks[] = $chunk; $diffLines = []; continue; } if (\preg_match('/^(?P[+ -])?(?P.*)/', $line, $match)) { $type = \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Line::UNCHANGED; if ($match['type'] === '+') { $type = \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Line::ADDED; } elseif ($match['type'] === '-') { $type = \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Line::REMOVED; } $diffLines[] = new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Line($type, $match['line']); if (null !== $chunk) { $chunk->setLines($diffLines); } } } $diff->setChunks($chunks); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; interface LongestCommonSubsequenceCalculator { /** * Calculates the longest common subsequence of two arrays. */ public function calculate(array $from, array $to) : array; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; use function get_class; use function gettype; use function is_object; use function sprintf; use Exception; final class ConfigurationException extends \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\InvalidArgumentException { public function __construct(string $option, string $expected, $value, int $code = 0, \Exception $previous = null) { parent::__construct(\sprintf('Option "%s" must be %s, got "%s".', $option, $expected, \is_object($value) ? \get_class($value) : (null === $value ? '' : \gettype($value) . '#' . $value)), $code, $previous); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; interface Exception { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; class InvalidArgumentException extends \InvalidArgumentException implements \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Exception { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; final class Chunk { /** * @var int */ private $start; /** * @var int */ private $startRange; /** * @var int */ private $end; /** * @var int */ private $endRange; /** * @var Line[] */ private $lines; public function __construct(int $start = 0, int $startRange = 1, int $end = 0, int $endRange = 1, array $lines = []) { $this->start = $start; $this->startRange = $startRange; $this->end = $end; $this->endRange = $endRange; $this->lines = $lines; } public function getStart() : int { return $this->start; } public function getStartRange() : int { return $this->startRange; } public function getEnd() : int { return $this->end; } public function getEndRange() : int { return $this->endRange; } /** * @return Line[] */ public function getLines() : array { return $this->lines; } /** * @param Line[] $lines */ public function setLines(array $lines) : void { foreach ($lines as $line) { if (!$line instanceof \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Line) { throw new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\InvalidArgumentException(); } } $this->lines = $lines; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; final class Line { public const ADDED = 1; public const REMOVED = 2; public const UNCHANGED = 3; /** * @var int */ private $type; /** * @var string */ private $content; public function __construct(int $type = self::UNCHANGED, string $content = '') { $this->type = $type; $this->content = $content; } public function getContent() : string { return $this->content; } public function getType() : int { return $this->type; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace _HumbugBoxd02f763d3c56\SebastianBergmann\Diff; use function array_fill; use function array_merge; use function array_reverse; use function array_slice; use function count; use function in_array; use function max; final class MemoryEfficientLongestCommonSubsequenceCalculator implements \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\LongestCommonSubsequenceCalculator { /** * {@inheritdoc} */ public function calculate(array $from, array $to) : array { $cFrom = \count($from); $cTo = \count($to); if ($cFrom === 0) { return []; } if ($cFrom === 1) { if (\in_array($from[0], $to, \true)) { return [$from[0]]; } return []; } $i = (int) ($cFrom / 2); $fromStart = \array_slice($from, 0, $i); $fromEnd = \array_slice($from, $i); $llB = $this->length($fromStart, $to); $llE = $this->length(\array_reverse($fromEnd), \array_reverse($to)); $jMax = 0; $max = 0; for ($j = 0; $j <= $cTo; $j++) { $m = $llB[$j] + $llE[$cTo - $j]; if ($m >= $max) { $max = $m; $jMax = $j; } } $toStart = \array_slice($to, 0, $jMax); $toEnd = \array_slice($to, $jMax); return \array_merge($this->calculate($fromStart, $toStart), $this->calculate($fromEnd, $toEnd)); } private function length(array $from, array $to) : array { $current = \array_fill(0, \count($to) + 1, 0); $cFrom = \count($from); $cTo = \count($to); for ($i = 0; $i < $cFrom; $i++) { $prev = $current; for ($j = 0; $j < $cTo; $j++) { if ($from[$i] === $to[$j]) { $current[$j + 1] = $prev[$j] + 1; } else { $current[$j + 1] = \max($current[$j], $prev[$j + 1]); } } } return $current; } } sebastian/diff Copyright (c) 2002-2020, Sebastian Bergmann . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Sebastian Bergmann nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @throws \Error If the prior promise returned from this method has not resolved. * @throws \Throwable The exception used to fail the iterator. */ public function advance() : \_HumbugBoxd02f763d3c56\Amp\Promise; /** * Gets the last emitted value or throws an exception if the iterator has completed. * * @return mixed Value emitted from the iterator. * @psalm-return TValue * * @throws \Error If the iterator has resolved or advance() was not called before calling this method. * @throws \Throwable The exception used to fail the iterator. */ public function getCurrent(); } current(); $prefix .= \sprintf("; %s yielded at key %s", \is_object($yielded) ? \get_class($yielded) : \gettype($yielded), \var_export($generator->key(), \true)); if (!$generator->valid()) { parent::__construct($prefix, 0, $previous); return; } $reflGen = new \ReflectionGenerator($generator); $exeGen = $reflGen->getExecutingGenerator(); if ($isSubgenerator = $exeGen !== $generator) { $reflGen = new \ReflectionGenerator($exeGen); } parent::__construct(\sprintf("%s on line %s in %s", $prefix, $reflGen->getExecutingLine(), $reflGen->getExecutingFile()), 0, $previous); } } promisor = $promisor; } /** * {@inheritdoc} */ public function onResolve(callable $onResolved) { if ($this->promise === null) { \assert($this->promisor !== null); $provider = $this->promisor; $this->promisor = null; $this->promise = call($provider); } \assert($this->promise !== null); $this->promise->onResolve($onResolved); } } reasons = $reasons; } /** * @return \Throwable[] */ public function getReasons() : array { return $this->reasons; } } , mixed, * mixed>|null) | callable(\Throwable|null, mixed): void $onResolved * * @return void */ public function onResolve(callable $onResolved); } */ final class Producer implements \_HumbugBoxd02f763d3c56\Amp\Iterator { /** * @use Internal\Producer */ use CallableMaker, Internal\Producer; /** * @param callable(callable(TValue):Promise):\Generator $producer * * @throws \Error Thrown if the callable does not return a Generator. */ public function __construct(callable $producer) { $result = $producer($this->callableFromInstanceMethod("emit")); if (!$result instanceof \Generator) { throw new \Error("The callable did not return a Generator"); } $coroutine = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); $coroutine->onResolve(function ($exception) { if ($this->complete) { return; } if ($exception) { $this->fail($exception); return; } $this->complete(); }); } } */ final class Success implements \_HumbugBoxd02f763d3c56\Amp\Promise { /** @var mixed */ private $value; /** * @param mixed $value Anything other than a Promise object. * * @psalm-param TValue $value * * @throws \Error If a promise is given as the value. */ public function __construct($value = null) { if ($value instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $value instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { throw new \Error("Cannot use a promise as success value"); } $this->value = $value; } /** * {@inheritdoc} */ public function onResolve(callable $onResolved) { try { $result = $onResolved(null, $this->value); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { \_HumbugBoxd02f763d3c56\Amp\Loop::defer(static function () use($exception) { throw $exception; }); } } } Has public emit, complete, and fail methods. */ private $emitter; /** @var Iterator Hides producer methods. */ private $iterator; public function __construct() { $this->emitter = new class implements \_HumbugBoxd02f763d3c56\Amp\Iterator { use Internal\Producer { emit as public; complete as public; fail as public; } }; $this->iterator = new \_HumbugBoxd02f763d3c56\Amp\Internal\PrivateIterator($this->emitter); } /** * @return Iterator * @psalm-return Iterator */ public function iterate() : \_HumbugBoxd02f763d3c56\Amp\Iterator { return $this->iterator; } /** * Emits a value to the iterator. * * @param mixed $value * * @psalm-param TValue $value * * @return Promise * @psalm-return Promise * @psalm-suppress MixedInferredReturnType * @psalm-suppress MixedReturnStatement */ public function emit($value) : \_HumbugBoxd02f763d3c56\Amp\Promise { /** @psalm-suppress UndefinedInterfaceMethod */ return $this->emitter->emit($value); } /** * Completes the iterator. * * @return void */ public function complete() { /** @psalm-suppress UndefinedInterfaceMethod */ $this->emitter->complete(); } /** * Fails the iterator with the given reason. * * @param \Throwable $reason * * @return void */ public function fail(\Throwable $reason) { /** @psalm-suppress UndefinedInterfaceMethod */ $this->emitter->fail($reason); } } */ final class Delayed implements \_HumbugBoxd02f763d3c56\Amp\Promise { use Internal\Placeholder; /** @var string|null Event loop watcher identifier. */ private $watcher; /** * @param int $time Milliseconds before succeeding the promise. * @param TReturn $value Succeed the promise with this value. */ public function __construct(int $time, $value = null) { $this->watcher = \_HumbugBoxd02f763d3c56\Amp\Loop::delay($time, function () use($value) { $this->watcher = null; $this->resolve($value); }); } /** * References the internal watcher in the event loop, keeping the loop running while this promise is pending. * * @return self */ public function reference() : self { if ($this->watcher !== null) { \_HumbugBoxd02f763d3c56\Amp\Loop::reference($this->watcher); } return $this; } /** * Unreferences the internal watcher in the event loop, allowing the loop to stop while this promise is pending if * no other events are pending in the loop. * * @return self */ public function unreference() : self { if ($this->watcher !== null) { \_HumbugBoxd02f763d3c56\Amp\Loop::unreference($this->watcher); } return $this; } } */ final class Coroutine implements \_HumbugBoxd02f763d3c56\Amp\Promise { use Internal\Placeholder; /** * Attempts to transform the non-promise yielded from the generator into a promise, otherwise returns an instance * `Amp\Failure` failed with an instance of `Amp\InvalidYieldError`. * * @param mixed $yielded Non-promise yielded from generator. * @param \Generator $generator No type for performance, we already know the type. * * @return Promise */ private static function transform($yielded, $generator) : \_HumbugBoxd02f763d3c56\Amp\Promise { $exception = null; // initialize here, see https://github.com/vimeo/psalm/issues/2951 try { if (\is_array($yielded)) { return \_HumbugBoxd02f763d3c56\Amp\Promise\all($yielded); } if ($yielded instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { return \_HumbugBoxd02f763d3c56\Amp\Promise\adapt($yielded); } // No match, continue to returning Failure below. } catch (\Throwable $exception) { // Conversion to promise failed, fall-through to returning Failure below. } return new \_HumbugBoxd02f763d3c56\Amp\Failure(new \_HumbugBoxd02f763d3c56\Amp\InvalidYieldError($generator, \sprintf("Unexpected yield; Expected an instance of %s or %s or an array of such instances", \_HumbugBoxd02f763d3c56\Amp\Promise::class, \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface::class), $exception)); } /** * @param \Generator $generator * @psalm-param \Generator,mixed,Promise|ReactPromise|TReturn> $generator */ public function __construct(\Generator $generator) { try { $yielded = $generator->current(); if (!$yielded instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { if (!$generator->valid()) { $this->resolve($generator->getReturn()); return; } $yielded = self::transform($yielded, $generator); } } catch (\Throwable $exception) { $this->fail($exception); return; } /** * @param \Throwable|null $e Exception to be thrown into the generator. * @param mixed $v Value to be sent into the generator. * * @return void * * @psalm-suppress MissingClosureParamType * @psalm-suppress MissingClosureReturnType */ $onResolve = function (\Throwable $e = null, $v) use($generator, &$onResolve) { /** @var bool $immediate Used to control iterative coroutine continuation. */ static $immediate = \true; /** @var \Throwable|null $exception Promise failure reason when executing next coroutine step, null at all other times. */ static $exception; /** @var mixed $value Promise success value when executing next coroutine step, null at all other times. */ static $value; $exception = $e; /** @psalm-suppress MixedAssignment */ $value = $v; if (!$immediate) { $immediate = \true; return; } try { try { do { if ($exception) { // Throw exception at current execution point. $yielded = $generator->throw($exception); } else { // Send the new value and execute to next yield statement. $yielded = $generator->send($value); } if (!$yielded instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { if (!$generator->valid()) { $this->resolve($generator->getReturn()); $onResolve = null; return; } $yielded = self::transform($yielded, $generator); } $immediate = \false; $yielded->onResolve($onResolve); } while ($immediate); $immediate = \true; } catch (\Throwable $exception) { $this->fail($exception); $onResolve = null; } finally { $exception = null; $value = null; } } catch (\Throwable $e) { \_HumbugBoxd02f763d3c56\Amp\Loop::defer(static function () use($e) { throw $e; }); } }; try { $yielded->onResolve($onResolve); unset($generator, $yielded, $onResolve); } catch (\Throwable $e) { \_HumbugBoxd02f763d3c56\Amp\Loop::defer(static function () use($e) { throw $e; }); } } } handle = \uv_loop_new(); /** * @param $event * @param $status * @param $events * @param $resource * * @return void */ $this->ioCallback = function ($event, $status, $events, $resource) { $watchers = $this->watchers[(int) $event]; switch ($status) { case 0: // OK break; default: // Invoke the callback on errors, as this matches behavior with other loop back-ends. // Re-enable watcher as libuv disables the watcher on non-zero status. $flags = 0; foreach ($watchers as $watcher) { $flags |= $watcher->enabled ? $watcher->type : 0; } \uv_poll_start($event, $flags, $this->ioCallback); break; } foreach ($watchers as $watcher) { // $events is OR'ed with 4 to trigger watcher if no events are indicated (0) or on UV_DISCONNECT (4). // http://docs.libuv.org/en/v1.x/poll.html if (!($watcher->enabled && ($watcher->type & $events || ($events | 4) === 4))) { continue; } try { $result = ($watcher->callback)($watcher->id, $resource, $watcher->data); if ($result === null) { continue; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } } }; /** * @param $event * * @return void */ $this->timerCallback = function ($event) { $watcher = $this->watchers[(int) $event][0]; if ($watcher->type & \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY) { unset($this->events[$watcher->id], $this->watchers[(int) $event]); // Avoid call to uv_is_active(). $this->cancel($watcher->id); // Remove reference to watcher in parent. } elseif ($watcher->value === 0) { // Disable and re-enable so it's not executed repeatedly in the same tick // See https://github.com/amphp/amp/issues/131 $this->disable($watcher->id); $this->enable($watcher->id); } try { $result = ($watcher->callback)($watcher->id, $watcher->data); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } }; /** * @param $event * @param $signo * * @return void */ $this->signalCallback = function ($event, $signo) { $watcher = $this->watchers[(int) $event][0]; try { $result = ($watcher->callback)($watcher->id, $signo, $watcher->data); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } }; } /** * {@inheritdoc} */ public function cancel(string $watcherId) { parent::cancel($watcherId); if (!isset($this->events[$watcherId])) { return; } $event = $this->events[$watcherId]; $eventId = (int) $event; if (isset($this->watchers[$eventId][0])) { // All except IO watchers. unset($this->watchers[$eventId]); } elseif (isset($this->watchers[$eventId][$watcherId])) { $watcher = $this->watchers[$eventId][$watcherId]; unset($this->watchers[$eventId][$watcherId]); if (empty($this->watchers[$eventId])) { unset($this->watchers[$eventId], $this->streams[(int) $watcher->value]); } } unset($this->events[$watcherId]); } public static function isSupported() : bool { return \extension_loaded("uv"); } /** * {@inheritdoc} */ public function now() : int { \uv_update_time($this->handle); /** @psalm-suppress TooManyArguments */ return \uv_now($this->handle); } /** * {@inheritdoc} */ public function getHandle() { return $this->handle; } /** * {@inheritdoc} * * @return void */ protected function dispatch(bool $blocking) { /** @psalm-suppress TooManyArguments */ \uv_run($this->handle, $blocking ? \UV::RUN_ONCE : \UV::RUN_NOWAIT); } /** * {@inheritdoc} * * @return void */ protected function activate(array $watchers) { $now = $this->now(); foreach ($watchers as $watcher) { $id = $watcher->id; switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::READABLE: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::WRITABLE: \assert(\is_resource($watcher->value)); $streamId = (int) $watcher->value; if (isset($this->streams[$streamId])) { $event = $this->streams[$streamId]; } elseif (isset($this->events[$id])) { $event = $this->streams[$streamId] = $this->events[$id]; } else { /** @psalm-suppress UndefinedFunction */ $event = $this->streams[$streamId] = \_HumbugBoxd02f763d3c56\uv_poll_init_socket($this->handle, $watcher->value); } $eventId = (int) $event; $this->events[$id] = $event; $this->watchers[$eventId][$id] = $watcher; $flags = 0; foreach ($this->watchers[$eventId] as $w) { $flags |= $w->enabled ? $w->type : 0; } \uv_poll_start($event, $flags, $this->ioCallback); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT: \assert(\is_int($watcher->value)); if (isset($this->events[$id])) { $event = $this->events[$id]; } else { $event = $this->events[$id] = \uv_timer_init($this->handle); } $this->watchers[(int) $event] = [$watcher]; \uv_timer_start($event, \max(0, $watcher->expiration - $now), $watcher->type & \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT ? $watcher->value : 0, $this->timerCallback); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL: \assert(\is_int($watcher->value)); if (isset($this->events[$id])) { $event = $this->events[$id]; } else { /** @psalm-suppress UndefinedFunction */ $event = $this->events[$id] = \_HumbugBoxd02f763d3c56\uv_signal_init($this->handle); } $this->watchers[(int) $event] = [$watcher]; /** @psalm-suppress UndefinedFunction */ \_HumbugBoxd02f763d3c56\uv_signal_start($event, $this->signalCallback, $watcher->value); break; default: // @codeCoverageIgnoreStart throw new \Error("Unknown watcher type"); } } } /** * {@inheritdoc} * * @return void */ protected function deactivate(\_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { $id = $watcher->id; if (!isset($this->events[$id])) { return; } $event = $this->events[$id]; if (!\uv_is_active($event)) { return; } switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::READABLE: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::WRITABLE: $flags = 0; foreach ($this->watchers[(int) $event] as $w) { $flags |= $w->enabled ? $w->type : 0; } if ($flags) { \uv_poll_start($event, $flags, $this->ioCallback); } else { \uv_poll_stop($event); } break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT: \uv_timer_stop($event); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL: \uv_signal_stop($event); break; default: // @codeCoverageIgnoreStart throw new \Error("Unknown watcher type"); } } } handle = new \EventBase(); $this->nowOffset = \_HumbugBoxd02f763d3c56\Amp\Internal\getCurrentTime(); $this->now = \random_int(0, $this->nowOffset); $this->nowOffset -= $this->now; if (self::$activeSignals === null) { self::$activeSignals =& $this->signals; } /** * @param $resource * @param $what * @param Watcher $watcher * * @return void */ $this->ioCallback = function ($resource, $what, \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { \assert(\is_resource($watcher->value)); try { $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } }; /** * @param $resource * @param $what * @param Watcher $watcher * * @return void */ $this->timerCallback = function ($resource, $what, \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { \assert(\is_int($watcher->value)); if ($watcher->type & \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY) { $this->cancel($watcher->id); } else { $this->events[$watcher->id]->add($watcher->value / self::MILLISEC_PER_SEC); } try { $result = ($watcher->callback)($watcher->id, $watcher->data); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } }; /** * @param $signum * @param $what * @param Watcher $watcher * * @return void */ $this->signalCallback = function ($signum, $what, \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { try { $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } }; } /** * {@inheritdoc} */ public function cancel(string $watcherId) { parent::cancel($watcherId); if (isset($this->events[$watcherId])) { $this->events[$watcherId]->free(); unset($this->events[$watcherId]); } } public static function isSupported() : bool { return \extension_loaded("event"); } /** * @codeCoverageIgnore */ public function __destruct() { foreach ($this->events as $event) { if ($event !== null) { // Events may have been nulled in extension depending on destruct order. $event->free(); } } // Unset here, otherwise $event->del() fails with a warning, because __destruct order isn't defined. // See https://github.com/amphp/amp/issues/159. $this->events = []; // Manually free the loop handle to fully release loop resources. // See https://github.com/amphp/amp/issues/177. if ($this->handle !== null) { $this->handle->free(); $this->handle = null; } } /** * {@inheritdoc} */ public function run() { $active = self::$activeSignals; \assert($active !== null); foreach ($active as $event) { $event->del(); } self::$activeSignals =& $this->signals; foreach ($this->signals as $event) { /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */ $event->add(); } try { parent::run(); } finally { foreach ($this->signals as $event) { $event->del(); } self::$activeSignals =& $active; foreach ($active as $event) { /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */ $event->add(); } } } /** * {@inheritdoc} */ public function stop() { $this->handle->stop(); parent::stop(); } /** * {@inheritdoc} */ public function now() : int { $this->now = \_HumbugBoxd02f763d3c56\Amp\Internal\getCurrentTime() - $this->nowOffset; return $this->now; } /** * {@inheritdoc} */ public function getHandle() : \EventBase { return $this->handle; } /** * {@inheritdoc} * * @return void */ protected function dispatch(bool $blocking) { $this->handle->loop($blocking ? \EventBase::LOOP_ONCE : \EventBase::LOOP_ONCE | \EventBase::LOOP_NONBLOCK); } /** * {@inheritdoc} * * @return void */ protected function activate(array $watchers) { $now = $this->now(); foreach ($watchers as $watcher) { if (!isset($this->events[$id = $watcher->id])) { switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::READABLE: \assert(\is_resource($watcher->value)); $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::READ | \Event::PERSIST, $this->ioCallback, $watcher); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::WRITABLE: \assert(\is_resource($watcher->value)); $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::WRITE | \Event::PERSIST, $this->ioCallback, $watcher); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT: \assert(\is_int($watcher->value)); $this->events[$id] = new \Event($this->handle, -1, \Event::TIMEOUT, $this->timerCallback, $watcher); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL: \assert(\is_int($watcher->value)); $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::SIGNAL | \Event::PERSIST, $this->signalCallback, $watcher); break; default: // @codeCoverageIgnoreStart throw new \Error("Unknown watcher type"); } } switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT: \assert(\is_int($watcher->value)); $interval = \max(0, $watcher->expiration - $now); $this->events[$id]->add($interval > 0 ? $interval / self::MILLISEC_PER_SEC : 0); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL: $this->signals[$id] = $this->events[$id]; // no break default: /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */ $this->events[$id]->add(); break; } } } /** * {@inheritdoc} * * @return void */ protected function deactivate(\_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { if (isset($this->events[$id = $watcher->id])) { $this->events[$id]->del(); if ($watcher->type === \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL) { unset($this->signals[$id]); } } } } handle = new \EvLoop(); $this->nowOffset = \_HumbugBoxd02f763d3c56\Amp\Internal\getCurrentTime(); $this->now = \random_int(0, $this->nowOffset); $this->nowOffset -= $this->now; if (self::$activeSignals === null) { self::$activeSignals =& $this->signals; } /** * @param \EvIO $event * * @return void */ $this->ioCallback = function (\_HumbugBoxd02f763d3c56\EvIO $event) { /** @var Watcher $watcher */ $watcher = $event->data; try { $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } }; /** * @param \EvTimer $event * * @return void */ $this->timerCallback = function (\EvTimer $event) { /** @var Watcher $watcher */ $watcher = $event->data; if ($watcher->type & \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY) { $this->cancel($watcher->id); } elseif ($watcher->value === 0) { // Disable and re-enable so it's not executed repeatedly in the same tick // See https://github.com/amphp/amp/issues/131 $this->disable($watcher->id); $this->enable($watcher->id); } try { $result = ($watcher->callback)($watcher->id, $watcher->data); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } }; /** * @param \EvSignal $event * * @return void */ $this->signalCallback = function (\EvSignal $event) { /** @var Watcher $watcher */ $watcher = $event->data; try { $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } }; } /** * {@inheritdoc} */ public function cancel(string $watcherId) { parent::cancel($watcherId); unset($this->events[$watcherId]); } public function __destruct() { foreach ($this->events as $event) { /** @psalm-suppress all */ if ($event !== null) { // Events may have been nulled in extension depending on destruct order. $event->stop(); } } // We need to clear all references to events manually, see // https://bitbucket.org/osmanov/pecl-ev/issues/31/segfault-in-ev_timer_stop $this->events = []; } /** * {@inheritdoc} */ public function run() { $active = self::$activeSignals; \assert($active !== null); foreach ($active as $event) { $event->stop(); } self::$activeSignals =& $this->signals; foreach ($this->signals as $event) { $event->start(); } try { parent::run(); } finally { foreach ($this->signals as $event) { $event->stop(); } self::$activeSignals =& $active; foreach ($active as $event) { $event->start(); } } } /** * {@inheritdoc} */ public function stop() { $this->handle->stop(); parent::stop(); } /** * {@inheritdoc} */ public function now() : int { $this->now = \_HumbugBoxd02f763d3c56\Amp\Internal\getCurrentTime() - $this->nowOffset; return $this->now; } /** * {@inheritdoc} */ public function getHandle() : \EvLoop { return $this->handle; } /** * {@inheritdoc} * * @return void */ protected function dispatch(bool $blocking) { $this->handle->run($blocking ? \Ev::RUN_ONCE : \Ev::RUN_ONCE | \Ev::RUN_NOWAIT); } /** * {@inheritdoc} * * @return void */ protected function activate(array $watchers) { $this->handle->nowUpdate(); $now = $this->now(); foreach ($watchers as $watcher) { if (!isset($this->events[$id = $watcher->id])) { switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::READABLE: \assert(\is_resource($watcher->value)); $this->events[$id] = $this->handle->io($watcher->value, \Ev::READ, $this->ioCallback, $watcher); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::WRITABLE: \assert(\is_resource($watcher->value)); $this->events[$id] = $this->handle->io($watcher->value, \Ev::WRITE, $this->ioCallback, $watcher); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT: \assert(\is_int($watcher->value)); $interval = $watcher->value / self::MILLISEC_PER_SEC; $this->events[$id] = $this->handle->timer(\max(0, ($watcher->expiration - $now) / self::MILLISEC_PER_SEC), $watcher->type & \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT ? $interval : 0, $this->timerCallback, $watcher); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL: \assert(\is_int($watcher->value)); $this->events[$id] = $this->handle->signal($watcher->value, $this->signalCallback, $watcher); break; default: // @codeCoverageIgnoreStart throw new \Error("Unknown watcher type"); } } else { $this->events[$id]->start(); } if ($watcher->type === \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL) { /** @psalm-suppress PropertyTypeCoercion */ $this->signals[$id] = $this->events[$id]; } } } /** * {@inheritdoc} * * @return void */ protected function deactivate(\_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { if (isset($this->events[$id = $watcher->id])) { $this->events[$id]->stop(); if ($watcher->type === \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL) { unset($this->signals[$id]); } } } } watcher = $watcher; $this->expiration = $expiration; } } $watcher * * @return void */ public function insert(\_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { \assert($watcher->expiration !== null); \assert(!isset($this->pointers[$watcher->id])); $entry = new \_HumbugBoxd02f763d3c56\Amp\Loop\Internal\TimerQueueEntry($watcher, $watcher->expiration); $node = \count($this->data); $this->data[$node] = $entry; $this->pointers[$watcher->id] = $node; while ($node !== 0 && $entry->expiration < $this->data[$parent = $node - 1 >> 1]->expiration) { $temp = $this->data[$parent]; $this->data[$node] = $temp; $this->pointers[$temp->watcher->id] = $node; $this->data[$parent] = $entry; $this->pointers[$watcher->id] = $parent; $node = $parent; } } /** * Removes the given watcher from the queue. Time complexity: O(log(n)). * * @param Watcher $watcher * * @psalm-param Watcher $watcher * * @return void */ public function remove(\_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { $id = $watcher->id; if (!isset($this->pointers[$id])) { return; } $this->removeAndRebuild($this->pointers[$id]); } /** * Deletes and returns the Watcher on top of the heap if it has expired, otherwise null is returned. * Time complexity: O(log(n)). * * @param int $now Current loop time. * * @return Watcher|null Expired watcher at the top of the heap or null if the watcher has not expired. * * @psalm-return Watcher|null */ public function extract(int $now) { if (empty($this->data)) { return null; } $data = $this->data[0]; if ($data->expiration > $now) { return null; } $this->removeAndRebuild(0); return $data->watcher; } /** * Returns the expiration time value at the top of the heap. Time complexity: O(1). * * @return int|null Expiration time of the watcher at the top of the heap or null if the heap is empty. */ public function peek() { return isset($this->data[0]) ? $this->data[0]->expiration : null; } /** * @param int $node Remove the given node and then rebuild the data array from that node downward. * * @return void */ private function removeAndRebuild(int $node) { $length = \count($this->data) - 1; $id = $this->data[$node]->watcher->id; $left = $this->data[$node] = $this->data[$length]; $this->pointers[$left->watcher->id] = $node; unset($this->data[$length], $this->pointers[$id]); while (($child = ($node << 1) + 1) < $length) { if ($this->data[$child]->expiration < $this->data[$node]->expiration && ($child + 1 >= $length || $this->data[$child]->expiration < $this->data[$child + 1]->expiration)) { // Left child is less than parent and right child. $swap = $child; } elseif ($child + 1 < $length && $this->data[$child + 1]->expiration < $this->data[$node]->expiration) { // Right child is less than parent and left child. $swap = $child + 1; } else { // Left and right child are greater than parent. break; } $left = $this->data[$node]; $right = $this->data[$swap]; $this->data[$node] = $right; $this->pointers[$right->watcher->id] = $node; $this->data[$swap] = $left; $this->pointers[$left->watcher->id] = $swap; $node = $swap; } } } createDriverFromEnv()) { return $driver; } if (\_HumbugBoxd02f763d3c56\Amp\Loop\UvDriver::isSupported()) { return new \_HumbugBoxd02f763d3c56\Amp\Loop\UvDriver(); } if (\_HumbugBoxd02f763d3c56\Amp\Loop\EvDriver::isSupported()) { return new \_HumbugBoxd02f763d3c56\Amp\Loop\EvDriver(); } if (\_HumbugBoxd02f763d3c56\Amp\Loop\EventDriver::isSupported()) { return new \_HumbugBoxd02f763d3c56\Amp\Loop\EventDriver(); } return new \_HumbugBoxd02f763d3c56\Amp\Loop\NativeDriver(); })(); if (\getenv("AMP_DEBUG_TRACE_WATCHERS")) { return new \_HumbugBoxd02f763d3c56\Amp\Loop\TracingDriver($driver); } return $driver; } /** * @return Driver|null */ private function createDriverFromEnv() { $driver = \getenv("AMP_LOOP_DRIVER"); if (!$driver) { return null; } if (!\class_exists($driver)) { throw new \Error(\sprintf("Driver '%s' does not exist.", $driver)); } if (!\is_subclass_of($driver, \_HumbugBoxd02f763d3c56\Amp\Loop\Driver::class)) { throw new \Error(\sprintf("Driver '%s' is not a subclass of '%s'.", $driver, \_HumbugBoxd02f763d3c56\Amp\Loop\Driver::class)); } return new $driver(); } } // @codeCoverageIgnoreEnd driver = $driver; } public function run() { $this->driver->run(); } public function stop() { $this->driver->stop(); } public function defer(callable $callback, $data = null) : string { $id = $this->driver->defer(function (...$args) use($callback) { $this->cancel($args[0]); return $callback(...$args); }, $data); $this->creationTraces[$id] = \_HumbugBoxd02f763d3c56\Amp\Internal\formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS)); $this->enabledWatchers[$id] = \true; return $id; } public function delay(int $delay, callable $callback, $data = null) : string { $id = $this->driver->delay($delay, function (...$args) use($callback) { $this->cancel($args[0]); return $callback(...$args); }, $data); $this->creationTraces[$id] = \_HumbugBoxd02f763d3c56\Amp\Internal\formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS)); $this->enabledWatchers[$id] = \true; return $id; } public function repeat(int $interval, callable $callback, $data = null) : string { $id = $this->driver->repeat($interval, $callback, $data); $this->creationTraces[$id] = \_HumbugBoxd02f763d3c56\Amp\Internal\formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS)); $this->enabledWatchers[$id] = \true; return $id; } public function onReadable($stream, callable $callback, $data = null) : string { $id = $this->driver->onReadable($stream, $callback, $data); $this->creationTraces[$id] = \_HumbugBoxd02f763d3c56\Amp\Internal\formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS)); $this->enabledWatchers[$id] = \true; return $id; } public function onWritable($stream, callable $callback, $data = null) : string { $id = $this->driver->onWritable($stream, $callback, $data); $this->creationTraces[$id] = \_HumbugBoxd02f763d3c56\Amp\Internal\formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS)); $this->enabledWatchers[$id] = \true; return $id; } public function onSignal(int $signo, callable $callback, $data = null) : string { $id = $this->driver->onSignal($signo, $callback, $data); $this->creationTraces[$id] = \_HumbugBoxd02f763d3c56\Amp\Internal\formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS)); $this->enabledWatchers[$id] = \true; return $id; } public function enable(string $watcherId) { try { $this->driver->enable($watcherId); $this->enabledWatchers[$watcherId] = \true; } catch (\_HumbugBoxd02f763d3c56\Amp\Loop\InvalidWatcherError $e) { throw new \_HumbugBoxd02f763d3c56\Amp\Loop\InvalidWatcherError($watcherId, $e->getMessage() . "\r\n\r\n" . $this->getTraces($watcherId)); } } public function cancel(string $watcherId) { $this->driver->cancel($watcherId); if (!isset($this->cancelTraces[$watcherId])) { $this->cancelTraces[$watcherId] = \_HumbugBoxd02f763d3c56\Amp\Internal\formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS)); } unset($this->enabledWatchers[$watcherId], $this->unreferencedWatchers[$watcherId]); } public function disable(string $watcherId) { $this->driver->disable($watcherId); unset($this->enabledWatchers[$watcherId]); } public function reference(string $watcherId) { try { $this->driver->reference($watcherId); unset($this->unreferencedWatchers[$watcherId]); } catch (\_HumbugBoxd02f763d3c56\Amp\Loop\InvalidWatcherError $e) { throw new \_HumbugBoxd02f763d3c56\Amp\Loop\InvalidWatcherError($watcherId, $e->getMessage() . "\r\n\r\n" . $this->getTraces($watcherId)); } } public function unreference(string $watcherId) { $this->driver->unreference($watcherId); $this->unreferencedWatchers[$watcherId] = \true; } public function setErrorHandler(callable $callback = null) { return $this->driver->setErrorHandler($callback); } /** @inheritdoc */ public function getHandle() { $this->driver->getHandle(); } public function dump() : string { $dump = "Enabled, referenced watchers keeping the loop running: "; foreach ($this->enabledWatchers as $watcher => $_) { if (isset($this->unreferencedWatchers[$watcher])) { continue; } $dump .= "Watcher ID: " . $watcher . "\r\n"; $dump .= $this->getCreationTrace($watcher); $dump .= "\r\n\r\n"; } return \rtrim($dump); } public function getInfo() : array { return $this->driver->getInfo(); } public function __debugInfo() { return $this->driver->__debugInfo(); } public function now() : int { return $this->driver->now(); } protected function error(\Throwable $exception) { $this->driver->error($exception); } /** * @inheritdoc * * @return void */ protected function activate(array $watchers) { // nothing to do in a decorator } /** * @inheritdoc * * @return void */ protected function dispatch(bool $blocking) { // nothing to do in a decorator } /** * @inheritdoc * * @return void */ protected function deactivate(\_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { // nothing to do in a decorator } private function getTraces(string $watcherId) : string { return "Creation Trace:\r\n" . $this->getCreationTrace($watcherId) . "\r\n\r\n" . "Cancellation Trace:\r\n" . $this->getCancelTrace($watcherId); } private function getCreationTrace(string $watcher) : string { if (!isset($this->creationTraces[$watcher])) { return 'No creation trace, yet.'; } return $this->creationTraces[$watcher]; } private function getCancelTrace(string $watcher) : string { if (!isset($this->cancelTraces[$watcher])) { return 'No cancellation trace, yet.'; } return $this->cancelTraces[$watcher]; } } running = \true; try { while ($this->running) { if ($this->isEmpty()) { return; } $this->tick(); } } finally { $this->stop(); } } /** * @return bool True if no enabled and referenced watchers remain in the loop. */ private function isEmpty() : bool { foreach ($this->watchers as $watcher) { if ($watcher->enabled && $watcher->referenced) { return \false; } } return \true; } /** * Executes a single tick of the event loop. * * @return void */ private function tick() { if (empty($this->deferQueue)) { $this->deferQueue = $this->nextTickQueue; } else { $this->deferQueue = \array_merge($this->deferQueue, $this->nextTickQueue); } $this->nextTickQueue = []; $this->activate($this->enableQueue); $this->enableQueue = []; foreach ($this->deferQueue as $watcher) { if (!isset($this->deferQueue[$watcher->id])) { continue; // Watcher disabled by another defer watcher. } unset($this->watchers[$watcher->id], $this->deferQueue[$watcher->id]); try { /** @var mixed $result */ $result = ($watcher->callback)($watcher->id, $watcher->data); if ($result === null) { continue; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } } /** @psalm-suppress RedundantCondition */ $this->dispatch(empty($this->nextTickQueue) && empty($this->enableQueue) && $this->running && !$this->isEmpty()); } /** * Activates (enables) all the given watchers. * * @param Watcher[] $watchers * * @return void */ protected abstract function activate(array $watchers); /** * Dispatches any pending read/write, timer, and signal events. * * @param bool $blocking * * @return void */ protected abstract function dispatch(bool $blocking); /** * Stop the event loop. * * When an event loop is stopped, it continues with its current tick and exits the loop afterwards. Multiple calls * to stop MUST be ignored and MUST NOT raise an exception. * * @return void */ public function stop() { $this->running = \false; } /** * Defer the execution of a callback. * * The deferred callable MUST be executed before any other type of watcher in a tick. Order of enabling MUST be * preserved when executing the callbacks. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param callable (string $watcherId, mixed $data) $callback The callback to defer. The `$watcherId` will be * invalidated before the callback call. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public function defer(callable $callback, $data = null) : string { /** @psalm-var Watcher $watcher */ $watcher = new \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher(); $watcher->type = \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DEFER; $watcher->id = $this->nextId++; $watcher->callback = $callback; $watcher->data = $data; $this->watchers[$watcher->id] = $watcher; $this->nextTickQueue[$watcher->id] = $watcher; return $watcher->id; } /** * Delay the execution of a callback. * * The delay is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be determined by which * timers expire first, but timers with the same expiration time MAY be executed in any order. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param int $delay The amount of time, in milliseconds, to delay the execution for. * @param callable (string $watcherId, mixed $data) $callback The callback to delay. The `$watcherId` will be * invalidated before the callback call. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public function delay(int $delay, callable $callback, $data = null) : string { if ($delay < 0) { throw new \Error("Delay must be greater than or equal to zero"); } /** @psalm-var Watcher $watcher */ $watcher = new \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher(); $watcher->type = \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY; $watcher->id = $this->nextId++; $watcher->callback = $callback; $watcher->value = $delay; $watcher->expiration = $this->now() + $delay; $watcher->data = $data; $this->watchers[$watcher->id] = $watcher; $this->enableQueue[$watcher->id] = $watcher; return $watcher->id; } /** * Repeatedly execute a callback. * * The interval between executions is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be * determined by which timers expire first, but timers with the same expiration time MAY be executed in any order. * The first execution is scheduled after the first interval period. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param int $interval The time interval, in milliseconds, to wait between executions. * @param callable (string $watcherId, mixed $data) $callback The callback to repeat. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public function repeat(int $interval, callable $callback, $data = null) : string { if ($interval < 0) { throw new \Error("Interval must be greater than or equal to zero"); } /** @psalm-var Watcher $watcher */ $watcher = new \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher(); $watcher->type = \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT; $watcher->id = $this->nextId++; $watcher->callback = $callback; $watcher->value = $interval; $watcher->expiration = $this->now() + $interval; $watcher->data = $data; $this->watchers[$watcher->id] = $watcher; $this->enableQueue[$watcher->id] = $watcher; return $watcher->id; } /** * Execute a callback when a stream resource becomes readable or is closed for reading. * * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the * watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid * resources, but are not required to, due to the high performance impact. Watchers on closed resources are * therefore undefined behavior. * * Multiple watchers on the same stream MAY be executed in any order. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param resource $stream The stream to monitor. * @param callable (string $watcherId, resource $stream, mixed $data) $callback The callback to execute. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public function onReadable($stream, callable $callback, $data = null) : string { /** @psalm-var Watcher $watcher */ $watcher = new \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher(); $watcher->type = \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::READABLE; $watcher->id = $this->nextId++; $watcher->callback = $callback; $watcher->value = $stream; $watcher->data = $data; $this->watchers[$watcher->id] = $watcher; $this->enableQueue[$watcher->id] = $watcher; return $watcher->id; } /** * Execute a callback when a stream resource becomes writable or is closed for writing. * * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the * watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid * resources, but are not required to, due to the high performance impact. Watchers on closed resources are * therefore undefined behavior. * * Multiple watchers on the same stream MAY be executed in any order. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param resource $stream The stream to monitor. * @param callable (string $watcherId, resource $stream, mixed $data) $callback The callback to execute. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public function onWritable($stream, callable $callback, $data = null) : string { /** @psalm-var Watcher $watcher */ $watcher = new \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher(); $watcher->type = \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::WRITABLE; $watcher->id = $this->nextId++; $watcher->callback = $callback; $watcher->value = $stream; $watcher->data = $data; $this->watchers[$watcher->id] = $watcher; $this->enableQueue[$watcher->id] = $watcher; return $watcher->id; } /** * Execute a callback when a signal is received. * * Warning: Installing the same signal on different instances of this interface is deemed undefined behavior. * Implementations MAY try to detect this, if possible, but are not required to. This is due to technical * limitations of the signals being registered globally per process. * * Multiple watchers on the same signal MAY be executed in any order. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param int $signo The signal number to monitor. * @param callable (string $watcherId, int $signo, mixed $data) $callback The callback to execute. * @param mixed $data Arbitrary data given to the callback function as the $data parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. * * @throws UnsupportedFeatureException If signal handling is not supported. */ public function onSignal(int $signo, callable $callback, $data = null) : string { /** @psalm-var Watcher $watcher */ $watcher = new \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher(); $watcher->type = \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL; $watcher->id = $this->nextId++; $watcher->callback = $callback; $watcher->value = $signo; $watcher->data = $data; $this->watchers[$watcher->id] = $watcher; $this->enableQueue[$watcher->id] = $watcher; return $watcher->id; } /** * Enable a watcher to be active starting in the next tick. * * Watchers MUST immediately be marked as enabled, but only be activated (i.e. callbacks can be called) right before * the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param string $watcherId The watcher identifier. * * @return void * * @throws InvalidWatcherError If the watcher identifier is invalid. */ public function enable(string $watcherId) { if (!isset($this->watchers[$watcherId])) { throw new \_HumbugBoxd02f763d3c56\Amp\Loop\InvalidWatcherError($watcherId, "Cannot enable an invalid watcher identifier: '{$watcherId}'"); } $watcher = $this->watchers[$watcherId]; if ($watcher->enabled) { return; // Watcher already enabled. } $watcher->enabled = \true; switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DEFER: $this->nextTickQueue[$watcher->id] = $watcher; break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY: \assert(\is_int($watcher->value)); $watcher->expiration = $this->now() + $watcher->value; $this->enableQueue[$watcher->id] = $watcher; break; default: $this->enableQueue[$watcher->id] = $watcher; break; } } /** * Cancel a watcher. * * This will detach the event loop from all resources that are associated to the watcher. After this operation the * watcher is permanently invalid. Calling this function MUST NOT fail, even if passed an invalid watcher. * * @param string $watcherId The watcher identifier. * * @return void */ public function cancel(string $watcherId) { $this->disable($watcherId); unset($this->watchers[$watcherId]); } /** * Disable a watcher immediately. * * A watcher MUST be disabled immediately, e.g. if a defer watcher disables a later defer watcher, the second defer * watcher isn't executed in this tick. * * Disabling a watcher MUST NOT invalidate the watcher. Calling this function MUST NOT fail, even if passed an * invalid watcher. * * @param string $watcherId The watcher identifier. * * @return void */ public function disable(string $watcherId) { if (!isset($this->watchers[$watcherId])) { return; } $watcher = $this->watchers[$watcherId]; if (!$watcher->enabled) { return; // Watcher already disabled. } $watcher->enabled = \false; $id = $watcher->id; switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DEFER: if (isset($this->nextTickQueue[$id])) { // Watcher was only queued to be enabled. unset($this->nextTickQueue[$id]); } else { unset($this->deferQueue[$id]); } break; default: if (isset($this->enableQueue[$id])) { // Watcher was only queued to be enabled. unset($this->enableQueue[$id]); } else { $this->deactivate($watcher); } break; } } /** * Deactivates (disables) the given watcher. * * @param Watcher $watcher * * @return void */ protected abstract function deactivate(\_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher); /** * Reference a watcher. * * This will keep the event loop alive whilst the watcher is still being monitored. Watchers have this state by * default. * * @param string $watcherId The watcher identifier. * * @return void * * @throws InvalidWatcherError If the watcher identifier is invalid. */ public function reference(string $watcherId) { if (!isset($this->watchers[$watcherId])) { throw new \_HumbugBoxd02f763d3c56\Amp\Loop\InvalidWatcherError($watcherId, "Cannot reference an invalid watcher identifier: '{$watcherId}'"); } $this->watchers[$watcherId]->referenced = \true; } /** * Unreference a watcher. * * The event loop should exit the run method when only unreferenced watchers are still being monitored. Watchers * are all referenced by default. * * @param string $watcherId The watcher identifier. * * @return void */ public function unreference(string $watcherId) { if (!isset($this->watchers[$watcherId])) { return; } $this->watchers[$watcherId]->referenced = \false; } /** * Stores information in the loop bound registry. * * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages * MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key. * * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated * interface for that purpose instead of sharing the storage key. * * @param string $key The namespaced storage key. * @param mixed $value The value to be stored. * * @return void */ public final function setState(string $key, $value) { if ($value === null) { unset($this->registry[$key]); } else { $this->registry[$key] = $value; } } /** * Gets information stored bound to the loop. * * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages * MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key. * * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated * interface for that purpose instead of sharing the storage key. * * @param string $key The namespaced storage key. * * @return mixed The previously stored value or `null` if it doesn't exist. */ public final function getState(string $key) { return isset($this->registry[$key]) ? $this->registry[$key] : null; } /** * Set a callback to be executed when an error occurs. * * The callback receives the error as the first and only parameter. The return value of the callback gets ignored. * If it can't handle the error, it MUST throw the error. Errors thrown by the callback or during its invocation * MUST be thrown into the `run` loop and stop the driver. * * Subsequent calls to this method will overwrite the previous handler. * * @param callable(\Throwable $error):void|null $callback The callback to execute. `null` will clear the * current handler. * * @return callable(\Throwable $error):void|null The previous handler, `null` if there was none. */ public function setErrorHandler(callable $callback = null) { $previous = $this->errorHandler; $this->errorHandler = $callback; return $previous; } /** * Invokes the error handler with the given exception. * * @param \Throwable $exception The exception thrown from a watcher callback. * * @return void * @throws \Throwable If no error handler has been set. */ protected function error(\Throwable $exception) { if ($this->errorHandler === null) { throw $exception; } ($this->errorHandler)($exception); } /** * Returns the current loop time in millisecond increments. Note this value does not necessarily correlate to * wall-clock time, rather the value returned is meant to be used in relative comparisons to prior values returned * by this method (intervals, expiration calculations, etc.) and is only updated once per loop tick. * * Extending classes should override this function to return a value cached once per loop tick. * * @return int */ public function now() : int { return (int) (\microtime(\true) * self::MILLISEC_PER_SEC); } /** * Get the underlying loop handle. * * Example: the `uv_loop` resource for `libuv` or the `EvLoop` object for `libev` or `null` for a native driver. * * Note: This function is *not* exposed in the `Loop` class. Users shall access it directly on the respective loop * instance. * * @return null|object|resource The loop handle the event loop operates on. `null` if there is none. */ public abstract function getHandle(); /** * Returns the same array of data as getInfo(). * * @return array */ public function __debugInfo() { // @codeCoverageIgnoreStart return $this->getInfo(); // @codeCoverageIgnoreEnd } /** * Retrieve an associative array of information about the event loop driver. * * The returned array MUST contain the following data describing the driver's currently registered watchers: * * [ * "defer" => ["enabled" => int, "disabled" => int], * "delay" => ["enabled" => int, "disabled" => int], * "repeat" => ["enabled" => int, "disabled" => int], * "on_readable" => ["enabled" => int, "disabled" => int], * "on_writable" => ["enabled" => int, "disabled" => int], * "on_signal" => ["enabled" => int, "disabled" => int], * "enabled_watchers" => ["referenced" => int, "unreferenced" => int], * "running" => bool * ]; * * Implementations MAY optionally add more information in the array but at minimum the above `key => value` format * MUST always be provided. * * @return array Statistics about the loop in the described format. */ public function getInfo() : array { $watchers = ["referenced" => 0, "unreferenced" => 0]; $defer = $delay = $repeat = $onReadable = $onWritable = $onSignal = ["enabled" => 0, "disabled" => 0]; foreach ($this->watchers as $watcher) { switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::READABLE: $array =& $onReadable; break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::WRITABLE: $array =& $onWritable; break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL: $array =& $onSignal; break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DEFER: $array =& $defer; break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY: $array =& $delay; break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT: $array =& $repeat; break; default: // @codeCoverageIgnoreStart throw new \Error("Unknown watcher type"); } if ($watcher->enabled) { ++$array["enabled"]; if ($watcher->referenced) { ++$watchers["referenced"]; } else { ++$watchers["unreferenced"]; } } else { ++$array["disabled"]; } } return ["enabled_watchers" => $watchers, "defer" => $defer, "delay" => $delay, "repeat" => $repeat, "on_readable" => $onReadable, "on_writable" => $onWritable, "on_signal" => $onSignal, "running" => (bool) $this->running]; } } timerQueue = new \_HumbugBoxd02f763d3c56\Amp\Loop\Internal\TimerQueue(); $this->signalHandling = \extension_loaded("pcntl"); $this->nowOffset = \_HumbugBoxd02f763d3c56\Amp\Internal\getCurrentTime(); $this->now = \random_int(0, $this->nowOffset); $this->nowOffset -= $this->now; } /** * {@inheritdoc} * * @throws \Amp\Loop\UnsupportedFeatureException If the pcntl extension is not available. */ public function onSignal(int $signo, callable $callback, $data = null) : string { if (!$this->signalHandling) { throw new \_HumbugBoxd02f763d3c56\Amp\Loop\UnsupportedFeatureException("Signal handling requires the pcntl extension"); } return parent::onSignal($signo, $callback, $data); } /** * {@inheritdoc} */ public function now() : int { $this->now = \_HumbugBoxd02f763d3c56\Amp\Internal\getCurrentTime() - $this->nowOffset; return $this->now; } /** * {@inheritdoc} */ public function getHandle() { return null; } /** * @param bool $blocking * * @return void * * @throws \Throwable */ protected function dispatch(bool $blocking) { $this->selectStreams($this->readStreams, $this->writeStreams, $blocking ? $this->getTimeout() : 0); $now = $this->now(); while ($watcher = $this->timerQueue->extract($now)) { if ($watcher->type & \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT) { $watcher->enabled = \false; // Trick base class into adding to enable queue when calling enable() $this->enable($watcher->id); } else { $this->cancel($watcher->id); } try { // Execute the timer. $result = ($watcher->callback)($watcher->id, $watcher->data); if ($result === null) { continue; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } } if ($this->signalHandling) { \pcntl_signal_dispatch(); } } /** * @param resource[] $read * @param resource[] $write * @param int $timeout * * @return void */ private function selectStreams(array $read, array $write, int $timeout) { $timeout /= self::MILLISEC_PER_SEC; if (!empty($read) || !empty($write)) { // Use stream_select() if there are any streams in the loop. if ($timeout >= 0) { $seconds = (int) $timeout; $microseconds = (int) (($timeout - $seconds) * self::MICROSEC_PER_SEC); } else { $seconds = null; $microseconds = null; } $except = null; // Error reporting suppressed since stream_select() emits an E_WARNING if it is interrupted by a signal. if (!($result = @\stream_select($read, $write, $except, $seconds, $microseconds))) { if ($result === 0) { return; } $error = \error_get_last(); if (\strpos($error["message"] ?? '', "unable to select") !== 0) { return; } $this->error(new \Exception($error["message"] ?? 'Unknown error during stream_select')); } foreach ($read as $stream) { $streamId = (int) $stream; if (!isset($this->readWatchers[$streamId])) { continue; // All read watchers disabled. } foreach ($this->readWatchers[$streamId] as $watcher) { if (!isset($this->readWatchers[$streamId][$watcher->id])) { continue; // Watcher disabled by another IO watcher. } try { $result = ($watcher->callback)($watcher->id, $stream, $watcher->data); if ($result === null) { continue; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } } } \assert(\is_array($write)); // See https://github.com/vimeo/psalm/issues/3036 foreach ($write as $stream) { $streamId = (int) $stream; if (!isset($this->writeWatchers[$streamId])) { continue; // All write watchers disabled. } foreach ($this->writeWatchers[$streamId] as $watcher) { if (!isset($this->writeWatchers[$streamId][$watcher->id])) { continue; // Watcher disabled by another IO watcher. } try { $result = ($watcher->callback)($watcher->id, $stream, $watcher->data); if ($result === null) { continue; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } } } return; } if ($timeout > 0) { // Otherwise sleep with usleep() if $timeout > 0. \usleep((int) ($timeout * self::MICROSEC_PER_SEC)); } } /** * @return int Milliseconds until next timer expires or -1 if there are no pending times. */ private function getTimeout() : int { $expiration = $this->timerQueue->peek(); if ($expiration === null) { return -1; } $expiration -= \_HumbugBoxd02f763d3c56\Amp\Internal\getCurrentTime() - $this->nowOffset; return $expiration > 0 ? $expiration : 0; } /** * {@inheritdoc} * * @return void */ protected function activate(array $watchers) { foreach ($watchers as $watcher) { switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::READABLE: \assert(\is_resource($watcher->value)); $streamId = (int) $watcher->value; $this->readWatchers[$streamId][$watcher->id] = $watcher; $this->readStreams[$streamId] = $watcher->value; break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::WRITABLE: \assert(\is_resource($watcher->value)); $streamId = (int) $watcher->value; $this->writeWatchers[$streamId][$watcher->id] = $watcher; $this->writeStreams[$streamId] = $watcher->value; break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT: \assert(\is_int($watcher->value)); $this->timerQueue->insert($watcher); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL: \assert(\is_int($watcher->value)); if (!isset($this->signalWatchers[$watcher->value])) { if (!@\pcntl_signal($watcher->value, $this->callableFromInstanceMethod('handleSignal'))) { $message = "Failed to register signal handler"; if ($error = \error_get_last()) { $message .= \sprintf("; Errno: %d; %s", $error["type"], $error["message"]); } throw new \Error($message); } } $this->signalWatchers[$watcher->value][$watcher->id] = $watcher; break; default: // @codeCoverageIgnoreStart throw new \Error("Unknown watcher type"); } } } /** * {@inheritdoc} * * @return void */ protected function deactivate(\_HumbugBoxd02f763d3c56\Amp\Loop\Watcher $watcher) { switch ($watcher->type) { case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::READABLE: $streamId = (int) $watcher->value; unset($this->readWatchers[$streamId][$watcher->id]); if (empty($this->readWatchers[$streamId])) { unset($this->readWatchers[$streamId], $this->readStreams[$streamId]); } break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::WRITABLE: $streamId = (int) $watcher->value; unset($this->writeWatchers[$streamId][$watcher->id]); if (empty($this->writeWatchers[$streamId])) { unset($this->writeWatchers[$streamId], $this->writeStreams[$streamId]); } break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::DELAY: case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::REPEAT: $this->timerQueue->remove($watcher); break; case \_HumbugBoxd02f763d3c56\Amp\Loop\Watcher::SIGNAL: \assert(\is_int($watcher->value)); if (isset($this->signalWatchers[$watcher->value])) { unset($this->signalWatchers[$watcher->value][$watcher->id]); if (empty($this->signalWatchers[$watcher->value])) { unset($this->signalWatchers[$watcher->value]); @\pcntl_signal($watcher->value, \SIG_DFL); } } break; default: // @codeCoverageIgnoreStart throw new \Error("Unknown watcher type"); } } /** * @param int $signo * * @return void */ private function handleSignal(int $signo) { foreach ($this->signalWatchers[$signo] as $watcher) { if (!isset($this->signalWatchers[$signo][$watcher->id])) { continue; } try { $result = ($watcher->callback)($watcher->id, $signo, $watcher->data); if ($result === null) { continue; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { $this->error($exception); } } } } watcherId = $watcherId; parent::__construct($message); } /** * @return string The watcher identifier. */ public function getWatcherId() { return $this->watcherId; } } */ final class Failure implements \_HumbugBoxd02f763d3c56\Amp\Promise { /** @var \Throwable $exception */ private $exception; /** * @param \Throwable $exception Rejection reason. */ public function __construct(\Throwable $exception) { $this->exception = $exception; } /** * {@inheritdoc} */ public function onResolve(callable $onResolved) { try { /** @var mixed $result */ $result = $onResolved($this->exception, null); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { \_HumbugBoxd02f763d3c56\Amp\Loop::defer(static function () use($exception) { throw $exception; }); } } } getMethod($method); } return self::$__reflectionMethods[$method]->getClosure($this); } /** * Creates a callable from a protected or private static method that may be invoked by methods requiring a * publicly invokable callback. * * @param string $method Static method name. * * @return callable * * @psalm-suppress MixedInferredReturnType */ private static function callableFromStaticMethod(string $method) : callable { if (!isset(self::$__reflectionMethods[$method])) { if (self::$__reflectionClass === null) { self::$__reflectionClass = new \ReflectionClass(self::class); } self::$__reflectionMethods[$method] = self::$__reflectionClass->getMethod($method); } return self::$__reflectionMethods[$method]->getClosure(); } } } else { /** @psalm-suppress DuplicateClass */ trait CallableMaker { /** * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1. */ private function callableFromInstanceMethod(string $method) : callable { return \Closure::fromCallable([$this, $method]); } /** * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1. */ private static function callableFromStaticMethod(string $method) : callable { return \Closure::fromCallable([self::class, $method]); } } } // @codeCoverageIgnoreEnd getToken(); * * $response = yield $httpClient->request("https://example.com/stream", $token); * $responseBody = $response->getBody(); * * while (($chunk = yield $response->read()) !== null) { * // consume $chunk * * if ($noLongerInterested) { * $cancellationTokenSource->cancel(); * break; * } * } * ``` * * @see CancellationToken * @see CancelledException */ final class CancellationTokenSource { /** @var CancellationToken */ private $token; /** @var callable|null */ private $onCancel; public function __construct() { $onCancel = null; $this->token = new class($onCancel) implements \_HumbugBoxd02f763d3c56\Amp\CancellationToken { /** @var string */ private $nextId = "a"; /** @var callable[] */ private $callbacks = []; /** @var \Throwable|null */ private $exception; /** * @param mixed $onCancel * @param-out callable $onCancel */ public function __construct(&$onCancel) { /** @psalm-suppress MissingClosureReturnType We still support PHP 7.0 */ $onCancel = function (\Throwable $exception) { $this->exception = $exception; $callbacks = $this->callbacks; $this->callbacks = []; foreach ($callbacks as $callback) { $this->invokeCallback($callback); } }; } /** * @param callable $callback * * @return void */ private function invokeCallback(callable $callback) { // No type declaration to prevent exception outside the try! try { /** @var mixed $result */ $result = $callback($this->exception); if ($result instanceof \Generator) { /** @psalm-var \Generator $result */ $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { \_HumbugBoxd02f763d3c56\Amp\Loop::defer(static function () use($exception) { throw $exception; }); } } public function subscribe(callable $callback) : string { $id = $this->nextId++; if ($this->exception) { $this->invokeCallback($callback); } else { $this->callbacks[$id] = $callback; } return $id; } public function unsubscribe(string $id) { unset($this->callbacks[$id]); } public function isRequested() : bool { return isset($this->exception); } public function throwIfRequested() { if (isset($this->exception)) { throw $this->exception; } } }; $this->onCancel = $onCancel; } public function getToken() : \_HumbugBoxd02f763d3c56\Amp\CancellationToken { return $this->token; } /** * @param \Throwable|null $previous Exception to be used as the previous exception to CancelledException. * * @return void */ public function cancel(\Throwable $previous = null) { if ($this->onCancel === null) { return; } $onCancel = $this->onCancel; $this->onCancel = null; $onCancel(new \_HumbugBoxd02f763d3c56\Amp\CancelledException($previous)); } } promise = $promise; } public function onResolve(callable $onResolved) { $this->promise->onResolve($onResolved); } } */ public function advance() : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->waiting !== null) { throw new \Error("The prior promise returned must resolve before invoking this method again"); } unset($this->values[$this->consumePosition]); $position = ++$this->consumePosition; if (\array_key_exists($position, $this->values)) { \assert(isset($this->backPressure[$position])); $deferred = $this->backPressure[$position]; unset($this->backPressure[$position]); $deferred->resolve(); return new \_HumbugBoxd02f763d3c56\Amp\Success(\true); } if ($this->complete) { return $this->complete; } $this->waiting = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); return $this->waiting->promise(); } /** * {@inheritdoc} * * @return TValue */ public function getCurrent() { if (empty($this->values) && $this->complete) { throw new \Error("The iterator has completed"); } if (!\array_key_exists($this->consumePosition, $this->values)) { throw new \Error("Promise returned from advance() must resolve before calling this method"); } return $this->values[$this->consumePosition]; } /** * Emits a value from the iterator. The returned promise is resolved once the emitted value has been consumed. * * @param mixed $value * * @return Promise * @psalm-return Promise * * @throws \Error If the iterator has completed. */ private function emit($value) : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->complete) { throw new \Error("Iterators cannot emit values after calling complete"); } if ($value instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { $value = \_HumbugBoxd02f763d3c56\Amp\Promise\adapt($value); } if ($value instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); $value->onResolve(function ($e, $v) use($deferred) { if ($this->complete) { $deferred->fail(new \Error("The iterator was completed before the promise result could be emitted")); return; } if ($e) { $this->fail($e); $deferred->fail($e); return; } $deferred->resolve($this->emit($v)); }); return $deferred->promise(); } $position = ++$this->emitPosition; $this->values[$position] = $value; if ($this->waiting !== null) { $waiting = $this->waiting; $this->waiting = null; $waiting->resolve(\true); return new \_HumbugBoxd02f763d3c56\Amp\Success(); // Consumer was already waiting for a new value, so back-pressure is unnecessary. } $this->backPressure[$position] = $pressure = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); return $pressure->promise(); } /** * Completes the iterator. * * @return void * * @throws \Error If the iterator has already been completed. */ private function complete() { if ($this->complete) { $message = "Iterator has already been completed"; if (isset($this->resolutionTrace)) { $trace = formatStacktrace($this->resolutionTrace); $message .= ". Previous completion trace:\n\n{$trace}\n\n"; } else { // @codeCoverageIgnoreStart $message .= ", define environment variable AMP_DEBUG or const AMP_DEBUG = true and enable assertions " . "for a stacktrace of the previous resolution."; // @codeCoverageIgnoreEnd } throw new \Error($message); } \assert((function () { $env = \getenv("AMP_DEBUG") ?: "0"; if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG") && \AMP_DEBUG) { $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); \array_shift($trace); // remove current closure $this->resolutionTrace = $trace; } return \true; })()); $this->complete = new \_HumbugBoxd02f763d3c56\Amp\Success(\false); if ($this->waiting !== null) { $waiting = $this->waiting; $this->waiting = null; $waiting->resolve($this->complete); } } /** * @param \Throwable $exception * * @return void */ private function fail(\Throwable $exception) { $this->complete = new \_HumbugBoxd02f763d3c56\Amp\Failure($exception); if ($this->waiting !== null) { $waiting = $this->waiting; $this->waiting = null; $waiting->resolve($this->complete); } } } , mixed, * mixed>|null)|callable(\Throwable|null, mixed): void */ private $onResolved; /** @var null|array */ private $resolutionTrace; /** * @inheritdoc */ public function onResolve(callable $onResolved) { if ($this->resolved) { if ($this->result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { $this->result->onResolve($onResolved); return; } try { /** @var mixed $result */ $result = $onResolved(null, $this->result); if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { \_HumbugBoxd02f763d3c56\Amp\Loop::defer(static function () use($exception) { throw $exception; }); } return; } if (null === $this->onResolved) { $this->onResolved = $onResolved; return; } if (!$this->onResolved instanceof \_HumbugBoxd02f763d3c56\Amp\Internal\ResolutionQueue) { /** @psalm-suppress InternalClass */ $this->onResolved = new \_HumbugBoxd02f763d3c56\Amp\Internal\ResolutionQueue($this->onResolved); } /** @psalm-suppress InternalMethod */ $this->onResolved->push($onResolved); } public function __destruct() { try { $this->result = null; } catch (\Throwable $e) { \_HumbugBoxd02f763d3c56\Amp\Loop::defer(static function () use($e) { throw $e; }); } } /** * @param mixed $value * * @return void * * @throws \Error Thrown if the promise has already been resolved. */ private function resolve($value = null) { if ($this->resolved) { $message = "Promise has already been resolved"; if (isset($this->resolutionTrace)) { $trace = formatStacktrace($this->resolutionTrace); $message .= ". Previous resolution trace:\n\n{$trace}\n\n"; } else { // @codeCoverageIgnoreStart $message .= ", define environment variable AMP_DEBUG or const AMP_DEBUG = true and enable assertions " . "for a stacktrace of the previous resolution."; // @codeCoverageIgnoreEnd } throw new \Error($message); } \assert((function () { $env = \getenv("AMP_DEBUG") ?: "0"; if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG") && \AMP_DEBUG) { $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); \array_shift($trace); // remove current closure $this->resolutionTrace = $trace; } return \true; })()); if ($value instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { $value = \_HumbugBoxd02f763d3c56\Amp\Promise\adapt($value); } $this->resolved = \true; $this->result = $value; if ($this->onResolved === null) { return; } $onResolved = $this->onResolved; $this->onResolved = null; if ($this->result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { $this->result->onResolve($onResolved); return; } try { /** @var mixed $result */ $result = $onResolved(null, $this->result); $onResolved = null; // allow garbage collection of $onResolved, to catch any exceptions from destructors if ($result === null) { return; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { \_HumbugBoxd02f763d3c56\Amp\Loop::defer(static function () use($exception) { throw $exception; }); } } /** * @param \Throwable $reason Failure reason. * * @return void */ private function fail(\Throwable $reason) { $this->resolve(new \_HumbugBoxd02f763d3c56\Amp\Failure($reason)); } } , mixed, * mixed>|null) | callable(\Throwable|null, mixed): void> */ private $queue = []; /** * @param callable|null $callback Initial callback to add to queue. * * @psalm-param null|callable(\Throwable|null, mixed): (Promise|\React\Promise\PromiseInterface|\Generator, mixed, * mixed>|null) | callable(\Throwable|null, mixed): void $callback */ public function __construct(callable $callback = null) { if ($callback !== null) { $this->push($callback); } } /** * Unrolls instances of self to avoid blowing up the call stack on resolution. * * @param callable $callback * * @psalm-param callable(\Throwable|null, mixed): (Promise|\React\Promise\PromiseInterface|\Generator, mixed, * mixed>|null) | callable(\Throwable|null, mixed): void $callback * * @return void */ public function push(callable $callback) { if ($callback instanceof self) { $this->queue = \array_merge($this->queue, $callback->queue); return; } $this->queue[] = $callback; } /** * Calls each callback in the queue, passing the provided values to the function. * * @param \Throwable|null $exception * @param mixed $value * * @return void */ public function __invoke($exception, $value) { foreach ($this->queue as $callback) { try { $result = $callback($exception, $value); if ($result === null) { continue; } if ($result instanceof \Generator) { $result = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise || $result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow($result); } } catch (\Throwable $exception) { \_HumbugBoxd02f763d3c56\Amp\Loop::defer(static function () use($exception) { throw $exception; }); } } } } */ final class PrivateIterator implements \_HumbugBoxd02f763d3c56\Amp\Iterator { /** @var Iterator */ private $iterator; /** * @param Iterator $iterator * * @psalm-param Iterator $iterator */ public function __construct(\_HumbugBoxd02f763d3c56\Amp\Iterator $iterator) { $this->iterator = $iterator; } /** * @return Promise */ public function advance() : \_HumbugBoxd02f763d3c56\Amp\Promise { return $this->iterator->advance(); } /** * @psalm-return TValue */ public function getCurrent() { return $this->iterator->getCurrent(); } } $trace Output of * `debug_backtrace()`. * * @return string Formatted stacktrace. * * @codeCoverageIgnore * @internal */ function formatStacktrace(array $trace) : string { return \implode("\n", \array_map(static function ($e, $i) { $line = "#{$i} "; if (isset($e["file"])) { $line .= "{$e['file']}:{$e['line']} "; } if (isset($e["type"])) { $line .= $e["class"] . $e["type"]; } return $line . $e["function"] . "()"; }, $trace, \array_keys($trace))); } /** * Creates a `TypeError` with a standardized error message. * * @param string[] $expected Expected types. * @param mixed $given Given value. * * @return \TypeError * * @internal */ function createTypeError(array $expected, $given) : \TypeError { $givenType = \is_object($given) ? \sprintf("instance of %s", \get_class($given)) : \gettype($given); if (\count($expected) === 1) { $expectedType = "Expected the following type: " . \array_pop($expected); } else { $expectedType = "Expected one of the following types: " . \implode(", ", $expected); } return new \TypeError("{$expectedType}; {$givenType} given"); } /** * Returns the current time relative to an arbitrary point in time. * * @return int Time in milliseconds. */ function getCurrentTime() : int { /** @var int|null $startTime */ static $startTime; /** @var int|null $nextWarning */ static $nextWarning; if (\PHP_INT_SIZE === 4) { // @codeCoverageIgnoreStart if ($startTime === null) { $startTime = \PHP_VERSION_ID >= 70300 ? \hrtime(\false)[0] : \time(); $nextWarning = \PHP_INT_MAX - 86400 * 7; } if (\PHP_VERSION_ID >= 70300) { list($seconds, $nanoseconds) = \hrtime(\false); $seconds -= $startTime; if ($seconds >= $nextWarning) { $timeToOverflow = (\PHP_INT_MAX - $seconds * 1000) / 1000; \trigger_error("getCurrentTime() will overflow in {$timeToOverflow} seconds, please restart the process before that. " . "You're using a 32 bit version of PHP, so time will overflow about every 24 days. Regular restarts are required.", \E_USER_WARNING); /** @psalm-suppress PossiblyNullOperand */ $nextWarning += 600; // every 10 minutes } return (int) ($seconds * 1000 + $nanoseconds / 1000000); } $seconds = \microtime(\true) - $startTime; if ($seconds >= $nextWarning) { $timeToOverflow = (\PHP_INT_MAX - $seconds * 1000) / 1000; \trigger_error("getCurrentTime() will overflow in {$timeToOverflow} seconds, please restart the process before that. " . "You're using a 32 bit version of PHP, so time will overflow about every 24 days. Regular restarts are required.", \E_USER_WARNING); /** @psalm-suppress PossiblyNullOperand */ $nextWarning += 600; // every 10 minutes } return (int) ($seconds * 1000); // @codeCoverageIgnoreEnd } if (\PHP_VERSION_ID >= 70300) { list($seconds, $nanoseconds) = \hrtime(\false); return (int) ($seconds * 1000 + $nanoseconds / 1000000); } return (int) (\microtime(\true) * 1000); } generateStructPropertyError($property)); } /** * @param string $property * @param mixed $value * * @psalm-return no-return */ public function __set(string $property, $value) { throw new \Error($this->generateStructPropertyError($property)); } private function generateStructPropertyError(string $property) : string { $suggestion = $this->suggestPropertyName($property); $suggestStr = $suggestion == "" ? "" : " ... did you mean \"{$suggestion}?\""; return \sprintf( "%s property \"%s\" does not exist%s", \str_replace("\0", "@", \get_class($this)), // Handle anonymous class names. $property, $suggestStr ); } private function suggestPropertyName(string $badProperty) : string { $badProperty = \strtolower($badProperty); $bestMatch = ""; $bestMatchPercentage = 0; /** @psalm-suppress RawObjectIteration */ foreach ($this as $property => $value) { // Never suggest properties that begin with an underscore if ($property[0] === "_") { continue; } \similar_text($badProperty, \strtolower($property), $byRefPercentage); if ($byRefPercentage > $bestMatchPercentage) { $bestMatchPercentage = $byRefPercentage; $bestMatch = $property; } } return $bestMatchPercentage >= $this->__propertySuggestThreshold ? $bestMatch : ""; } } token = $source->getToken(); $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); $this->watcher = \_HumbugBoxd02f763d3c56\Amp\Loop::delay($timeout, static function () use($source, $message, $trace) { $trace = \_HumbugBoxd02f763d3c56\Amp\Internal\formatStacktrace($trace); $source->cancel(new \_HumbugBoxd02f763d3c56\Amp\TimeoutException("{$message}\r\nTimeoutCancellationToken was created here:\r\n{$trace}")); }); \_HumbugBoxd02f763d3c56\Amp\Loop::unreference($this->watcher); } /** * Cancels the delay watcher. */ public function __destruct() { \_HumbugBoxd02f763d3c56\Amp\Loop::cancel($this->watcher); } /** * {@inheritdoc} */ public function subscribe(callable $callback) : string { return $this->token->subscribe($callback); } /** * {@inheritdoc} */ public function unsubscribe(string $id) { $this->token->unsubscribe($id); } /** * {@inheritdoc} */ public function isRequested() : bool { return $this->token->isRequested(); } /** * {@inheritdoc} */ public function throwIfRequested() { $this->token->throwIfRequested(); } } throwIfRequested(); * } * ``` * * potentially multiple times, it allows writing * * ```php * $token = $token ?? new NullCancellationToken; * * // ... * * $token->throwIfRequested(); * ``` * * instead. */ final class NullCancellationToken implements \_HumbugBoxd02f763d3c56\Amp\CancellationToken { /** @inheritdoc */ public function subscribe(callable $callback) : string { return "null-token"; } /** @inheritdoc */ public function unsubscribe(string $id) { // nothing to do } /** @inheritdoc */ public function isRequested() : bool { return \false; } /** @inheritdoc */ public function throwIfRequested() { // nothing to do } } defer($callback); } self::$driver->run(); } /** * Stop the event loop. * * When an event loop is stopped, it continues with its current tick and exits the loop afterwards. Multiple calls * to stop MUST be ignored and MUST NOT raise an exception. * * @return void */ public static function stop() { self::$driver->stop(); } /** * Defer the execution of a callback. * * The deferred callable MUST be executed before any other type of watcher in a tick. Order of enabling MUST be * preserved when executing the callbacks. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param callable(string $watcherId, mixed $data) $callback The callback to defer. The `$watcherId` will be * invalidated before the callback call. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public static function defer(callable $callback, $data = null) : string { return self::$driver->defer($callback, $data); } /** * Delay the execution of a callback. * * The delay is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be determined by which * timers expire first, but timers with the same expiration time MAY be executed in any order. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param int $delay The amount of time, in milliseconds, to delay the execution for. * @param callable(string $watcherId, mixed $data) $callback The callback to delay. The `$watcherId` will be * invalidated before the callback call. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public static function delay(int $delay, callable $callback, $data = null) : string { return self::$driver->delay($delay, $callback, $data); } /** * Repeatedly execute a callback. * * The interval between executions is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be * determined by which timers expire first, but timers with the same expiration time MAY be executed in any order. * The first execution is scheduled after the first interval period. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param int $interval The time interval, in milliseconds, to wait between executions. * @param callable(string $watcherId, mixed $data) $callback The callback to repeat. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public static function repeat(int $interval, callable $callback, $data = null) : string { return self::$driver->repeat($interval, $callback, $data); } /** * Execute a callback when a stream resource becomes readable or is closed for reading. * * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the * watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid * resources, but are not required to, due to the high performance impact. Watchers on closed resources are * therefore undefined behavior. * * Multiple watchers on the same stream MAY be executed in any order. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param resource $stream The stream to monitor. * @param callable(string $watcherId, resource $stream, mixed $data) $callback The callback to execute. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public static function onReadable($stream, callable $callback, $data = null) : string { return self::$driver->onReadable($stream, $callback, $data); } /** * Execute a callback when a stream resource becomes writable or is closed for writing. * * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the * watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid * resources, but are not required to, due to the high performance impact. Watchers on closed resources are * therefore undefined behavior. * * Multiple watchers on the same stream MAY be executed in any order. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param resource $stream The stream to monitor. * @param callable(string $watcherId, resource $stream, mixed $data) $callback The callback to execute. * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. */ public static function onWritable($stream, callable $callback, $data = null) : string { return self::$driver->onWritable($stream, $callback, $data); } /** * Execute a callback when a signal is received. * * Warning: Installing the same signal on different instances of this interface is deemed undefined behavior. * Implementations MAY try to detect this, if possible, but are not required to. This is due to technical * limitations of the signals being registered globally per process. * * Multiple watchers on the same signal MAY be executed in any order. * * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called) * right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param int $signo The signal number to monitor. * @param callable(string $watcherId, int $signo, mixed $data) $callback The callback to execute. * @param mixed $data Arbitrary data given to the callback function as the $data parameter. * * @return string An unique identifier that can be used to cancel, enable or disable the watcher. * * @throws UnsupportedFeatureException If signal handling is not supported. */ public static function onSignal(int $signo, callable $callback, $data = null) : string { return self::$driver->onSignal($signo, $callback, $data); } /** * Enable a watcher to be active starting in the next tick. * * Watchers MUST immediately be marked as enabled, but only be activated (i.e. callbacks can be called) right before * the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled. * * @param string $watcherId The watcher identifier. * * @return void * * @throws InvalidWatcherError If the watcher identifier is invalid. */ public static function enable(string $watcherId) { self::$driver->enable($watcherId); } /** * Disable a watcher immediately. * * A watcher MUST be disabled immediately, e.g. if a defer watcher disables a later defer watcher, the second defer * watcher isn't executed in this tick. * * Disabling a watcher MUST NOT invalidate the watcher. Calling this function MUST NOT fail, even if passed an * invalid watcher. * * @param string $watcherId The watcher identifier. * * @return void */ public static function disable(string $watcherId) { if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) { // Prior to PHP 7.2, self::$driver may be unset during destruct. // See https://github.com/amphp/amp/issues/212. return; } self::$driver->disable($watcherId); } /** * Cancel a watcher. * * This will detatch the event loop from all resources that are associated to the watcher. After this operation the * watcher is permanently invalid. Calling this function MUST NOT fail, even if passed an invalid watcher. * * @param string $watcherId The watcher identifier. * * @return void */ public static function cancel(string $watcherId) { if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) { // Prior to PHP 7.2, self::$driver may be unset during destruct. // See https://github.com/amphp/amp/issues/212. return; } self::$driver->cancel($watcherId); } /** * Reference a watcher. * * This will keep the event loop alive whilst the watcher is still being monitored. Watchers have this state by * default. * * @param string $watcherId The watcher identifier. * * @return void * * @throws InvalidWatcherError If the watcher identifier is invalid. */ public static function reference(string $watcherId) { self::$driver->reference($watcherId); } /** * Unreference a watcher. * * The event loop should exit the run method when only unreferenced watchers are still being monitored. Watchers * are all referenced by default. * * @param string $watcherId The watcher identifier. * * @return void */ public static function unreference(string $watcherId) { if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) { // Prior to PHP 7.2, self::$driver may be unset during destruct. // See https://github.com/amphp/amp/issues/212. return; } self::$driver->unreference($watcherId); } /** * Returns the current loop time in millisecond increments. Note this value does not necessarily correlate to * wall-clock time, rather the value returned is meant to be used in relative comparisons to prior values returned * by this method (intervals, expiration calculations, etc.) and is only updated once per loop tick. * * @return int */ public static function now() : int { return self::$driver->now(); } /** * Stores information in the loop bound registry. * * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages * MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key. * * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated * interface for that purpose instead of sharing the storage key. * * @param string $key The namespaced storage key. * @param mixed $value The value to be stored. * * @return void */ public static function setState(string $key, $value) { self::$driver->setState($key, $value); } /** * Gets information stored bound to the loop. * * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages * MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key. * * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated * interface for that purpose instead of sharing the storage key. * * @param string $key The namespaced storage key. * * @return mixed The previously stored value or `null` if it doesn't exist. */ public static function getState(string $key) { return self::$driver->getState($key); } /** * Set a callback to be executed when an error occurs. * * The callback receives the error as the first and only parameter. The return value of the callback gets ignored. * If it can't handle the error, it MUST throw the error. Errors thrown by the callback or during its invocation * MUST be thrown into the `run` loop and stop the driver. * * Subsequent calls to this method will overwrite the previous handler. * * @param callable(\Throwable $error)|null $callback The callback to execute. `null` will clear the * current handler. * * @return callable(\Throwable $error)|null The previous handler, `null` if there was none. */ public static function setErrorHandler(callable $callback = null) { return self::$driver->setErrorHandler($callback); } /** * Retrieve an associative array of information about the event loop driver. * * The returned array MUST contain the following data describing the driver's currently registered watchers: * * [ * "defer" => ["enabled" => int, "disabled" => int], * "delay" => ["enabled" => int, "disabled" => int], * "repeat" => ["enabled" => int, "disabled" => int], * "on_readable" => ["enabled" => int, "disabled" => int], * "on_writable" => ["enabled" => int, "disabled" => int], * "on_signal" => ["enabled" => int, "disabled" => int], * "enabled_watchers" => ["referenced" => int, "unreferenced" => int], * "running" => bool * ]; * * Implementations MAY optionally add more information in the array but at minimum the above `key => value` format * MUST always be provided. * * @return array Statistics about the loop in the described format. */ public static function getInfo() : array { return self::$driver->getInfo(); } /** * Retrieve the event loop driver that is in scope. * * @return Driver */ public static function get() : \_HumbugBoxd02f763d3c56\Amp\Loop\Driver { return self::$driver; } } // Default factory, don't move this to a file loaded by the composer "files" autoload mechanism, otherwise custom // implementations might have issues setting a default loop, because it's overridden by us then. // @codeCoverageIgnoreStart \_HumbugBoxd02f763d3c56\Amp\Loop::set((new \_HumbugBoxd02f763d3c56\Amp\Loop\DriverFactory())->create()); // @codeCoverageIgnoreEnd subscribe(function (\_HumbugBoxd02f763d3c56\Amp\CancelledException $exception) { $this->exception = $exception; $callbacks = $this->callbacks; $this->callbacks = []; foreach ($callbacks as $callback) { asyncCall($callback, $this->exception); } }); $this->tokens[] = [$token, $id]; } } public function __destruct() { foreach ($this->tokens as list($token, $id)) { /** @var CancellationToken $token */ $token->unsubscribe($id); } } /** @inheritdoc */ public function subscribe(callable $callback) : string { $id = $this->nextId++; if ($this->exception) { asyncCall($callback, $this->exception); } else { $this->callbacks[$id] = $callback; } return $id; } /** @inheritdoc */ public function unsubscribe(string $id) { unset($this->callbacks[$id]); } /** @inheritdoc */ public function isRequested() : bool { foreach ($this->tokens as list($token)) { if ($token->isRequested()) { return \true; } } return \false; } /** @inheritdoc */ public function throwIfRequested() { foreach ($this->tokens as list($token)) { $token->throwIfRequested(); } } } Has public resolve and fail methods. */ private $resolver; /** @var Promise Hides placeholder methods */ private $promise; public function __construct() { $this->resolver = new class implements \_HumbugBoxd02f763d3c56\Amp\Promise { use Internal\Placeholder { resolve as public; fail as public; } }; $this->promise = new \_HumbugBoxd02f763d3c56\Amp\Internal\PrivatePromise($this->resolver); } /** * @return Promise */ public function promise() : \_HumbugBoxd02f763d3c56\Amp\Promise { return $this->promise; } /** * Fulfill the promise with the given value. * * @param mixed $value * * @psalm-param TValue|Promise $value * * @return void */ public function resolve($value = null) { /** @psalm-suppress UndefinedInterfaceMethod */ $this->resolver->resolve($value); } /** * Fails the promise the the given reason. * * @param \Throwable $reason * * @return void */ public function fail(\Throwable $reason) { /** @psalm-suppress UndefinedInterfaceMethod */ $this->resolver->fail($reason); } } * @template T as TReturn|Promise|\Generator * * @formatter:off * * @param callable(...mixed): T $callback * * @return callable * @psalm-return (T is Promise ? (callable(mixed...): Promise) : (T is \Generator ? (TGenerator is Promise ? (callable(mixed...): Promise) : (callable(mixed...): Promise)) : (callable(mixed...): Promise))) * * @formatter:on * * @see asyncCoroutine() * * @psalm-suppress InvalidReturnType */ function coroutine(callable $callback) : callable { /** @psalm-suppress InvalidReturnStatement */ return static function (...$args) use($callback) : Promise { return call($callback, ...$args); }; } /** * Returns a new function that wraps $callback in a promise/coroutine-aware function that automatically runs * Generators as coroutines. The returned function always returns void when invoked. Errors are forwarded to the * loop's error handler using `Amp\Promise\rethrow()`. * * Use this function to create a coroutine-aware callable for a non-promise-aware callback caller. * * @param callable(...mixed): mixed $callback * * @return callable * @psalm-return callable(mixed...): void * * @see coroutine() */ function asyncCoroutine(callable $callback) : callable { return static function (...$args) use($callback) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow(call($callback, ...$args)); }; } /** * Calls the given function, always returning a promise. If the function returns a Generator, it will be run as a * coroutine. If the function throws, a failed promise will be returned. * * @template TReturn * @template TPromise * @template TGeneratorReturn * @template TGeneratorPromise * * @template TGenerator as TGeneratorReturn|Promise * @template T as TReturn|Promise|\Generator * * @formatter:off * * @param callable(...mixed): T $callback * @param mixed ...$args Arguments to pass to the function. * * @return Promise * @psalm-return (T is Promise ? Promise : (T is \Generator ? (TGenerator is Promise ? Promise : Promise) : Promise)) * * @formatter:on */ function call(callable $callback, ...$args) : \_HumbugBoxd02f763d3c56\Amp\Promise { try { $result = $callback(...$args); } catch (\Throwable $exception) { return new \_HumbugBoxd02f763d3c56\Amp\Failure($exception); } if ($result instanceof \Generator) { return new \_HumbugBoxd02f763d3c56\Amp\Coroutine($result); } if ($result instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { return $result; } if ($result instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { return \_HumbugBoxd02f763d3c56\Amp\Promise\adapt($result); } return new \_HumbugBoxd02f763d3c56\Amp\Success($result); } /** * Calls the given function. If the function returns a Generator, it will be run as a coroutine. If the function * throws or returns a failing promise, the failure is forwarded to the loop error handler. * * @param callable(...mixed): mixed $callback * @param mixed ...$args Arguments to pass to the function. * * @return void */ function asyncCall(callable $callback, ...$args) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow(call($callback, ...$args)); } /** * Sleeps for the specified number of milliseconds. * * @param int $milliseconds * * @return Delayed */ function delay(int $milliseconds) : \_HumbugBoxd02f763d3c56\Amp\Delayed { return new \_HumbugBoxd02f763d3c56\Amp\Delayed($milliseconds); } /** * Returns the current time relative to an arbitrary point in time. * * @return int Time in milliseconds. */ function getCurrentTime() : int { return \_HumbugBoxd02f763d3c56\Amp\Internal\getCurrentTime(); } namespace _HumbugBoxd02f763d3c56\Amp\Promise; use _HumbugBoxd02f763d3c56\Amp\Deferred; use _HumbugBoxd02f763d3c56\Amp\Loop; use _HumbugBoxd02f763d3c56\Amp\MultiReasonException; use _HumbugBoxd02f763d3c56\Amp\Promise; use _HumbugBoxd02f763d3c56\Amp\Success; use _HumbugBoxd02f763d3c56\Amp\TimeoutException; use _HumbugBoxd02f763d3c56\React\Promise\PromiseInterface as ReactPromise; use function _HumbugBoxd02f763d3c56\Amp\call; use function _HumbugBoxd02f763d3c56\Amp\Internal\createTypeError; /** * Registers a callback that will forward the failure reason to the event loop's error handler if the promise fails. * * Use this function if you neither return the promise nor handle a possible error yourself to prevent errors from * going entirely unnoticed. * * @param Promise|ReactPromise $promise Promise to register the handler on. * * @return void * @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface. * */ function rethrow($promise) { if (!$promise instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { if ($promise instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { $promise = adapt($promise); } else { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError([\_HumbugBoxd02f763d3c56\Amp\Promise::class, \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface::class], $promise); } } $promise->onResolve(static function ($exception) { if ($exception) { throw $exception; } }); } /** * Runs the event loop until the promise is resolved. Should not be called within a running event loop. * * Use this function only in synchronous contexts to wait for an asynchronous operation. Use coroutines and yield to * await promise resolution in a fully asynchronous application instead. * * @template TPromise * @template T as Promise|ReactPromise * * @param Promise|ReactPromise $promise Promise to wait for. * * @return mixed Promise success value. * * @psalm-param T $promise * @psalm-return (T is Promise ? TPromise : mixed) * * @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface. * @throws \Error If the event loop stopped without the $promise being resolved. * @throws \Throwable Promise failure reason. */ function wait($promise) { if (!$promise instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { if ($promise instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { $promise = adapt($promise); } else { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError([\_HumbugBoxd02f763d3c56\Amp\Promise::class, \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface::class], $promise); } } $resolved = \false; try { \_HumbugBoxd02f763d3c56\Amp\Loop::run(function () use(&$resolved, &$value, &$exception, $promise) { $promise->onResolve(function ($e, $v) use(&$resolved, &$value, &$exception) { \_HumbugBoxd02f763d3c56\Amp\Loop::stop(); $resolved = \true; $exception = $e; $value = $v; }); }); } catch (\Throwable $throwable) { throw new \Error("Loop exceptionally stopped without resolving the promise", 0, $throwable); } if (!$resolved) { throw new \Error("Loop stopped without resolving the promise"); } if ($exception) { throw $exception; } return $value; } /** * Creates an artificial timeout for any `Promise`. * * If the timeout expires before the promise is resolved, the returned promise fails with an instance of * `Amp\TimeoutException`. * * @template TReturn * * @param Promise|ReactPromise $promise Promise to which the timeout is applied. * @param int $timeout Timeout in milliseconds. * * @return Promise * * @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface. */ function timeout($promise, int $timeout) : \_HumbugBoxd02f763d3c56\Amp\Promise { if (!$promise instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { if ($promise instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { $promise = adapt($promise); } else { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError([\_HumbugBoxd02f763d3c56\Amp\Promise::class, \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface::class], $promise); } } $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); $watcher = \_HumbugBoxd02f763d3c56\Amp\Loop::delay($timeout, static function () use(&$deferred) { $temp = $deferred; // prevent double resolve $deferred = null; $temp->fail(new \_HumbugBoxd02f763d3c56\Amp\TimeoutException()); }); \_HumbugBoxd02f763d3c56\Amp\Loop::unreference($watcher); $promise->onResolve(function () use(&$deferred, $promise, $watcher) { if ($deferred !== null) { \_HumbugBoxd02f763d3c56\Amp\Loop::cancel($watcher); $deferred->resolve($promise); } }); return $deferred->promise(); } /** * Creates an artificial timeout for any `Promise`. * * If the promise is resolved before the timeout expires, the result is returned * * If the timeout expires before the promise is resolved, a default value is returned * * @template TReturn * * @param Promise|ReactPromise $promise Promise to which the timeout is applied. * @param int $timeout Timeout in milliseconds. * @param TReturn $default * * @return Promise * * @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface. */ function timeoutWithDefault($promise, int $timeout, $default = null) : \_HumbugBoxd02f763d3c56\Amp\Promise { $promise = timeout($promise, $timeout); return \_HumbugBoxd02f763d3c56\Amp\call(static function () use($promise, $default) { try { return (yield $promise); } catch (\_HumbugBoxd02f763d3c56\Amp\TimeoutException $exception) { return $default; } }); } /** * Adapts any object with a done(callable $onFulfilled, callable $onRejected) or then(callable $onFulfilled, * callable $onRejected) method to a promise usable by components depending on placeholders implementing * \AsyncInterop\Promise. * * @param object $promise Object with a done() or then() method. * * @return Promise Promise resolved by the $thenable object. * * @throws \Error If the provided object does not have a then() method. */ function adapt($promise) : \_HumbugBoxd02f763d3c56\Amp\Promise { $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); if (\method_exists($promise, 'done')) { $promise->done([$deferred, 'resolve'], [$deferred, 'fail']); } elseif (\method_exists($promise, 'then')) { $promise->then([$deferred, 'resolve'], [$deferred, 'fail']); } else { throw new \Error("Object must have a 'then' or 'done' method"); } return $deferred->promise(); } /** * Returns a promise that is resolved when all promises are resolved. The returned promise will not fail. * Returned promise succeeds with a two-item array delineating successful and failed promise results, * with keys identical and corresponding to the original given array. * * This function is the same as some() with the notable exception that it will never fail even * if all promises in the array resolve unsuccessfully. * * @param Promise[]|ReactPromise[] $promises * * @return Promise * * @throws \Error If a non-Promise is in the array. */ function any(array $promises) : \_HumbugBoxd02f763d3c56\Amp\Promise { return some($promises, 0); } /** * Returns a promise that succeeds when all promises succeed, and fails if any promise fails. Returned * promise succeeds with an array of values used to succeed each contained promise, with keys corresponding to * the array of promises. * * @param Promise[]|ReactPromise[] $promises Array of only promises. * * @return Promise * * @throws \Error If a non-Promise is in the array. * * @template TValue * * @psalm-param array|ReactPromise> $promises * @psalm-assert array|ReactPromise> $promises $promises * @psalm-return Promise> */ function all(array $promises) : \_HumbugBoxd02f763d3c56\Amp\Promise { if (empty($promises)) { return new \_HumbugBoxd02f763d3c56\Amp\Success([]); } $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); $result = $deferred->promise(); $pending = \count($promises); $values = []; foreach ($promises as $key => $promise) { if ($promise instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { $promise = adapt($promise); } elseif (!$promise instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError([\_HumbugBoxd02f763d3c56\Amp\Promise::class, \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface::class], $promise); } $values[$key] = null; // add entry to array to preserve order $promise->onResolve(function ($exception, $value) use(&$deferred, &$values, &$pending, $key) { if ($pending === 0) { return; } if ($exception) { $pending = 0; $deferred->fail($exception); $deferred = null; return; } $values[$key] = $value; if (0 === --$pending) { $deferred->resolve($values); } }); } return $result; } /** * Returns a promise that succeeds when the first promise succeeds, and fails only if all promises fail. * * @param Promise[]|ReactPromise[] $promises Array of only promises. * * @return Promise * * @throws \Error If the array is empty or a non-Promise is in the array. */ function first(array $promises) : \_HumbugBoxd02f763d3c56\Amp\Promise { if (empty($promises)) { throw new \Error("No promises provided"); } $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); $result = $deferred->promise(); $pending = \count($promises); $exceptions = []; foreach ($promises as $key => $promise) { if ($promise instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { $promise = adapt($promise); } elseif (!$promise instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError([\_HumbugBoxd02f763d3c56\Amp\Promise::class, \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface::class], $promise); } $exceptions[$key] = null; // add entry to array to preserve order $promise->onResolve(function ($error, $value) use(&$deferred, &$exceptions, &$pending, $key) { if ($pending === 0) { return; } if (!$error) { $pending = 0; $deferred->resolve($value); $deferred = null; return; } $exceptions[$key] = $error; if (0 === --$pending) { $deferred->fail(new \_HumbugBoxd02f763d3c56\Amp\MultiReasonException($exceptions)); } }); } return $result; } /** * Resolves with a two-item array delineating successful and failed Promise results. * * The returned promise will only fail if the given number of required promises fail. * * @param Promise[]|ReactPromise[] $promises Array of only promises. * @param int $required Number of promises that must succeed for the * returned promise to succeed. * * @return Promise * * @throws \Error If a non-Promise is in the array. */ function some(array $promises, int $required = 1) : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($required < 0) { throw new \Error("Number of promises required must be non-negative"); } $pending = \count($promises); if ($required > $pending) { throw new \Error("Too few promises provided"); } if (empty($promises)) { return new \_HumbugBoxd02f763d3c56\Amp\Success([[], []]); } $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); $result = $deferred->promise(); $values = []; $exceptions = []; foreach ($promises as $key => $promise) { if ($promise instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { $promise = adapt($promise); } elseif (!$promise instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError([\_HumbugBoxd02f763d3c56\Amp\Promise::class, \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface::class], $promise); } $values[$key] = $exceptions[$key] = null; // add entry to arrays to preserve order $promise->onResolve(static function ($exception, $value) use(&$values, &$exceptions, &$pending, $key, $required, $deferred) { if ($exception) { $exceptions[$key] = $exception; unset($values[$key]); } else { $values[$key] = $value; unset($exceptions[$key]); } if (0 === --$pending) { if (\count($values) < $required) { $deferred->fail(new \_HumbugBoxd02f763d3c56\Amp\MultiReasonException($exceptions)); } else { $deferred->resolve([$exceptions, $values]); } } }); } return $result; } /** * Wraps a promise into another promise, altering the exception or result. * * @param Promise|ReactPromise $promise * @param callable $callback * * @return Promise */ function wrap($promise, callable $callback) : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($promise instanceof \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface) { $promise = adapt($promise); } elseif (!$promise instanceof \_HumbugBoxd02f763d3c56\Amp\Promise) { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError([\_HumbugBoxd02f763d3c56\Amp\Promise::class, \_HumbugBoxd02f763d3c56\React\Promise\PromiseInterface::class], $promise); } $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); $promise->onResolve(static function (\Throwable $exception = null, $result) use($deferred, $callback) { try { $result = $callback($exception, $result); } catch (\Throwable $exception) { $deferred->fail($exception); return; } $deferred->resolve($result); }); return $deferred->promise(); } namespace _HumbugBoxd02f763d3c56\Amp\Iterator; use _HumbugBoxd02f763d3c56\Amp\Delayed; use _HumbugBoxd02f763d3c56\Amp\Emitter; use _HumbugBoxd02f763d3c56\Amp\Iterator; use _HumbugBoxd02f763d3c56\Amp\Producer; use _HumbugBoxd02f763d3c56\Amp\Promise; use function _HumbugBoxd02f763d3c56\Amp\call; use function _HumbugBoxd02f763d3c56\Amp\coroutine; use function _HumbugBoxd02f763d3c56\Amp\Internal\createTypeError; /** * Creates an iterator from the given iterable, emitting the each value. The iterable may contain promises. If any * promise fails, the iterator will fail with the same reason. * * @param array|\Traversable $iterable Elements to emit. * @param int $delay Delay between element emissions in milliseconds. * * @return Iterator * * @throws \TypeError If the argument is not an array or instance of \Traversable. */ function fromIterable($iterable, int $delay = 0) : \_HumbugBoxd02f763d3c56\Amp\Iterator { if (!$iterable instanceof \Traversable && !\is_array($iterable)) { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError(["array", "Traversable"], $iterable); } if ($delay) { return new \_HumbugBoxd02f763d3c56\Amp\Producer(static function (callable $emit) use($iterable, $delay) { foreach ($iterable as $value) { (yield new \_HumbugBoxd02f763d3c56\Amp\Delayed($delay)); (yield $emit($value)); } }); } return new \_HumbugBoxd02f763d3c56\Amp\Producer(static function (callable $emit) use($iterable) { foreach ($iterable as $value) { (yield $emit($value)); } }); } /** * @template TValue * @template TReturn * * @param Iterator $iterator * @param callable (TValue $value): TReturn $onEmit * * @return Iterator */ function map(\_HumbugBoxd02f763d3c56\Amp\Iterator $iterator, callable $onEmit) : \_HumbugBoxd02f763d3c56\Amp\Iterator { return new \_HumbugBoxd02f763d3c56\Amp\Producer(static function (callable $emit) use($iterator, $onEmit) { while ((yield $iterator->advance())) { (yield $emit($onEmit($iterator->getCurrent()))); } }); } /** * @template TValue * * @param Iterator $iterator * @param callable(TValue $value):bool $filter * * @return Iterator */ function filter(\_HumbugBoxd02f763d3c56\Amp\Iterator $iterator, callable $filter) : \_HumbugBoxd02f763d3c56\Amp\Iterator { return new \_HumbugBoxd02f763d3c56\Amp\Producer(static function (callable $emit) use($iterator, $filter) { while ((yield $iterator->advance())) { if ($filter($iterator->getCurrent())) { (yield $emit($iterator->getCurrent())); } } }); } /** * Creates an iterator that emits values emitted from any iterator in the array of iterators. * * @param Iterator[] $iterators * * @return Iterator */ function merge(array $iterators) : \_HumbugBoxd02f763d3c56\Amp\Iterator { $emitter = new \_HumbugBoxd02f763d3c56\Amp\Emitter(); $result = $emitter->iterate(); $coroutine = \_HumbugBoxd02f763d3c56\Amp\coroutine(static function (\_HumbugBoxd02f763d3c56\Amp\Iterator $iterator) use(&$emitter) { while ((yield $iterator->advance()) && $emitter !== null) { (yield $emitter->emit($iterator->getCurrent())); } }); $coroutines = []; foreach ($iterators as $iterator) { if (!$iterator instanceof \_HumbugBoxd02f763d3c56\Amp\Iterator) { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError([\_HumbugBoxd02f763d3c56\Amp\Iterator::class], $iterator); } $coroutines[] = $coroutine($iterator); } \_HumbugBoxd02f763d3c56\Amp\Promise\all($coroutines)->onResolve(static function ($exception) use(&$emitter) { if ($exception) { $emitter->fail($exception); $emitter = null; } else { $emitter->complete(); } }); return $result; } /** * Concatenates the given iterators into a single iterator, emitting values from a single iterator at a time. The * prior iterator must complete before values are emitted from any subsequent iterators. Iterators are concatenated * in the order given (iteration order of the array). * * @param Iterator[] $iterators * * @return Iterator */ function concat(array $iterators) : \_HumbugBoxd02f763d3c56\Amp\Iterator { foreach ($iterators as $iterator) { if (!$iterator instanceof \_HumbugBoxd02f763d3c56\Amp\Iterator) { throw \_HumbugBoxd02f763d3c56\Amp\Internal\createTypeError([\_HumbugBoxd02f763d3c56\Amp\Iterator::class], $iterator); } } $emitter = new \_HumbugBoxd02f763d3c56\Amp\Emitter(); $previous = []; $promise = \_HumbugBoxd02f763d3c56\Amp\Promise\all($previous); $coroutine = \_HumbugBoxd02f763d3c56\Amp\coroutine(static function (\_HumbugBoxd02f763d3c56\Amp\Iterator $iterator, callable $emit) { while ((yield $iterator->advance())) { (yield $emit($iterator->getCurrent())); } }); foreach ($iterators as $iterator) { $emit = \_HumbugBoxd02f763d3c56\Amp\coroutine(static function ($value) use($emitter, $promise) { static $pending = \true, $failed = \false; if ($failed) { return; } if ($pending) { try { (yield $promise); $pending = \false; } catch (\Throwable $exception) { $failed = \true; return; // Prior iterator failed. } } (yield $emitter->emit($value)); }); $previous[] = $coroutine($iterator, $emit); $promise = \_HumbugBoxd02f763d3c56\Amp\Promise\all($previous); } $promise->onResolve(static function ($exception) use($emitter) { if ($exception) { $emitter->fail($exception); return; } $emitter->complete(); }); return $emitter->iterate(); } /** * Discards all remaining items and returns the number of discarded items. * * @template TValue * * @param Iterator $iterator * * @return Promise * * @psalm-param Iterator $iterator * @psalm-return Promise */ function discard(\_HumbugBoxd02f763d3c56\Amp\Iterator $iterator) : \_HumbugBoxd02f763d3c56\Amp\Promise { return \_HumbugBoxd02f763d3c56\Amp\call(static function () use($iterator) : \Generator { $count = 0; while ((yield $iterator->advance())) { $count++; } return $count; }); } /** * Collects all items from an iterator into an array. * * @template TValue * * @param Iterator $iterator * * @psalm-param Iterator $iterator * * @return Promise * @psalm-return Promise> */ function toArray(\_HumbugBoxd02f763d3c56\Amp\Iterator $iterator) : \_HumbugBoxd02f763d3c56\Amp\Promise { return \_HumbugBoxd02f763d3c56\Amp\call(static function () use($iterator) { /** @psalm-var list $array */ $array = []; while ((yield $iterator->advance())) { $array[] = $iterator->getCurrent(); } return $array; }); } The MIT License (MIT) Copyright (c) 2015-2019 amphp Copyright (c) 2016 PHP Asynchronous Interoperability Group Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. source = $source; $this->encoding = $encoding; $this->options = $options; $this->resource = @\inflate_init($encoding, $options); if ($this->resource === \false) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException("Failed initializing deflate context"); } } /** @inheritdoc */ public function read() : \_HumbugBoxd02f763d3c56\Amp\Promise { return \_HumbugBoxd02f763d3c56\Amp\call(function () { if ($this->resource === null) { return null; } \assert($this->source !== null); $data = (yield $this->source->read()); // Needs a double guard, as stream might have been closed while reading /** @psalm-suppress ParadoxicalCondition */ if ($this->resource === null) { return null; } if ($data === null) { $decompressed = @\inflate_add($this->resource, "", \ZLIB_FINISH); if ($decompressed === \false) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException("Failed adding data to deflate context"); } $this->close(); return $decompressed; } $decompressed = @\inflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH); if ($decompressed === \false) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException("Failed adding data to deflate context"); } return $decompressed; }); } /** * @internal * @return void */ private function close() { $this->resource = null; $this->source = null; } /** * Gets the used compression encoding. * * @return int Encoding specified on construction time. */ public function getEncoding() : int { return $this->encoding; } /** * Gets the used compression options. * * @return array Options array passed on construction time. */ public function getOptions() : array { return $this->options; } } source = $source; } public function read() : \_HumbugBoxd02f763d3c56\Amp\Promise { return \_HumbugBoxd02f763d3c56\Amp\call(function () { $chunk = (yield $this->source->read()); if ($chunk === null) { if ($this->buffer === null) { return null; } $chunk = \base64_encode($this->buffer); $this->buffer = null; return $chunk; } $this->buffer .= $chunk; $length = \strlen($this->buffer); $chunk = \base64_encode(\substr($this->buffer, 0, $length - $length % 3)); $this->buffer = \substr($this->buffer, $length - $length % 3); return $chunk; }); } } destination = $destination; } public function write(string $data) : \_HumbugBoxd02f763d3c56\Amp\Promise { $this->buffer .= $data; $length = \strlen($this->buffer); $chunk = \base64_encode(\substr($this->buffer, 0, $length - $length % 3)); $this->buffer = \substr($this->buffer, $length - $length % 3); return $this->destination->write($chunk); } public function end(string $finalData = "") : \_HumbugBoxd02f763d3c56\Amp\Promise { $chunk = \base64_encode($this->buffer . $finalData); $this->buffer = ''; return $this->destination->end($chunk); } } source = $source; } public function read() : \_HumbugBoxd02f763d3c56\Amp\Promise { return \_HumbugBoxd02f763d3c56\Amp\call(function () { if ($this->source === null) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException('Failed to read stream chunk due to invalid base64 data'); } $chunk = (yield $this->source->read()); if ($chunk === null) { if ($this->buffer === null) { return null; } $chunk = \base64_decode($this->buffer, \true); if ($chunk === \false) { $this->source = null; $this->buffer = null; throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException('Failed to read stream chunk due to invalid base64 data'); } $this->buffer = null; return $chunk; } $this->buffer .= $chunk; $length = \strlen($this->buffer); $chunk = \base64_decode(\substr($this->buffer, 0, $length - $length % 4), \true); if ($chunk === \false) { $this->source = null; $this->buffer = null; throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException('Failed to read stream chunk due to invalid base64 data'); } $this->buffer = \substr($this->buffer, $length - $length % 4); return $chunk; }); } } destination = $destination; } public function write(string $data) : \_HumbugBoxd02f763d3c56\Amp\Promise { $this->buffer .= $data; $length = \strlen($this->buffer); $chunk = \base64_decode(\substr($this->buffer, 0, $length - $length % 4), \true); if ($chunk === \false) { return new \_HumbugBoxd02f763d3c56\Amp\Failure(new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException('Invalid base64 near offset ' . $this->offset)); } $this->offset += $length - $length % 4; $this->buffer = \substr($this->buffer, $length - $length % 4); return $this->destination->write($chunk); } public function end(string $finalData = "") : \_HumbugBoxd02f763d3c56\Amp\Promise { $this->offset += \strlen($this->buffer); $chunk = \base64_decode($this->buffer . $finalData, \true); if ($chunk === \false) { return new \_HumbugBoxd02f763d3c56\Amp\Failure(new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException('Invalid base64 near offset ' . $this->offset)); } $this->buffer = ''; return $this->destination->end($chunk); } } useSingleRead = $useSingleRead; if (\strpos($meta["mode"], "r") === \false && \strpos($meta["mode"], "+") === \false) { throw new \Error("Expected a readable stream"); } \stream_set_blocking($stream, \false); \stream_set_read_buffer($stream, 0); $this->resource =& $stream; $this->chunkSize =& $chunkSize; $deferred =& $this->deferred; $readable =& $this->readable; $this->watcher = \_HumbugBoxd02f763d3c56\Amp\Loop::onReadable($this->resource, static function ($watcher) use(&$deferred, &$readable, &$stream, &$chunkSize, $useSingleRead) { if ($useSingleRead) { $data = @\fread($stream, $chunkSize); } else { $data = @\stream_get_contents($stream, $chunkSize); } \assert($data !== \false, "Trying to read from a previously fclose()'d resource. Do NOT manually fclose() resources the loop still has a reference to."); // Error suppression, because pthreads does crazy things with resources, // which might be closed during two operations. // See https://github.com/amphp/byte-stream/issues/32 if ($data === '' && @\feof($stream)) { $readable = \false; $stream = null; $data = null; // Stream closed, resolve read with null. \_HumbugBoxd02f763d3c56\Amp\Loop::cancel($watcher); } else { \_HumbugBoxd02f763d3c56\Amp\Loop::disable($watcher); } $temp = $deferred; $deferred = null; \assert($temp instanceof \_HumbugBoxd02f763d3c56\Amp\Deferred); $temp->resolve($data); }); $this->immediateCallable = static function ($watcherId, $data) use(&$deferred) { $temp = $deferred; $deferred = null; \assert($temp instanceof \_HumbugBoxd02f763d3c56\Amp\Deferred); $temp->resolve($data); }; \_HumbugBoxd02f763d3c56\Amp\Loop::disable($this->watcher); } /** @inheritdoc */ public function read() : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->deferred !== null) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\PendingReadError(); } if (!$this->readable) { return new \_HumbugBoxd02f763d3c56\Amp\Success(); // Resolve with null on closed stream. } \assert($this->resource !== null); // Attempt a direct read, because Windows suffers from slow I/O on STDIN otherwise. if ($this->useSingleRead) { $data = @\fread($this->resource, $this->chunkSize); } else { $data = @\stream_get_contents($this->resource, $this->chunkSize); } \assert($data !== \false, "Trying to read from a previously fclose()'d resource. Do NOT manually fclose() resources the loop still has a reference to."); if ($data === '') { // Error suppression, because pthreads does crazy things with resources, // which might be closed during two operations. // See https://github.com/amphp/byte-stream/issues/32 if (@\feof($this->resource)) { $this->readable = \false; $this->resource = null; \_HumbugBoxd02f763d3c56\Amp\Loop::cancel($this->watcher); return new \_HumbugBoxd02f763d3c56\Amp\Success(); // Stream closed, resolve read with null. } $this->deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); \_HumbugBoxd02f763d3c56\Amp\Loop::enable($this->watcher); return $this->deferred->promise(); } // Prevent an immediate read → write loop from blocking everything // See e.g. examples/benchmark-throughput.php $this->deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); $this->immediateWatcher = \_HumbugBoxd02f763d3c56\Amp\Loop::defer($this->immediateCallable, $data); return $this->deferred->promise(); } /** * Closes the stream forcefully. Multiple `close()` calls are ignored. * * @return void */ public function close() { if ($this->resource) { // Error suppression, as resource might already be closed $meta = @\stream_get_meta_data($this->resource); if ($meta && \strpos($meta["mode"], "+") !== \false) { @\stream_socket_shutdown($this->resource, \STREAM_SHUT_RD); } else { /** @psalm-suppress InvalidPropertyAssignmentValue */ @\fclose($this->resource); } } $this->free(); } /** * Nulls reference to resource, marks stream unreadable, and succeeds any pending read with null. * * @return void */ private function free() { $this->readable = \false; $this->resource = null; if ($this->deferred !== null) { $deferred = $this->deferred; $this->deferred = null; $deferred->resolve(); } \_HumbugBoxd02f763d3c56\Amp\Loop::cancel($this->watcher); if ($this->immediateWatcher !== null) { \_HumbugBoxd02f763d3c56\Amp\Loop::cancel($this->immediateWatcher); } } /** * @return resource|null The stream resource or null if the stream has closed. */ public function getResource() { return $this->resource; } /** * @return void */ public function setChunkSize(int $chunkSize) { $this->chunkSize = $chunkSize; } /** * References the read watcher, so the loop keeps running in case there's an active read. * * @return void * * @see Loop::reference() */ public function reference() { if (!$this->resource) { throw new \Error("Resource has already been freed"); } \_HumbugBoxd02f763d3c56\Amp\Loop::reference($this->watcher); } /** * Unreferences the read watcher, so the loop doesn't keep running even if there are active reads. * * @return void * * @see Loop::unreference() */ public function unreference() { if (!$this->resource) { throw new \Error("Resource has already been freed"); } \_HumbugBoxd02f763d3c56\Amp\Loop::unreference($this->watcher); } public function __destruct() { if ($this->resource !== null) { $this->free(); } } } destination = $destination; $this->encoding = $encoding; $this->options = $options; $this->resource = @\deflate_init($encoding, $options); if ($this->resource === \false) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException("Failed initializing deflate context"); } } /** @inheritdoc */ public function write(string $data) : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->resource === null) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ClosedException("The stream has already been closed"); } \assert($this->destination !== null); $compressed = \deflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH); if ($compressed === \false) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException("Failed adding data to deflate context"); } $promise = $this->destination->write($compressed); $promise->onResolve(function ($error) { if ($error) { $this->close(); } }); return $promise; } /** @inheritdoc */ public function end(string $finalData = "") : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->resource === null) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ClosedException("The stream has already been closed"); } \assert($this->destination !== null); $compressed = \deflate_add($this->resource, $finalData, \ZLIB_FINISH); if ($compressed === \false) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException("Failed adding data to deflate context"); } $promise = $this->destination->end($compressed); $promise->onResolve(function () { $this->close(); }); return $promise; } /** * @internal * @return void */ private function close() { $this->resource = null; $this->destination = null; } /** * Gets the used compression encoding. * * @return int Encoding specified on construction time. */ public function getEncoding() : int { return $this->encoding; } /** * Gets the used compression options. * * @return array Options array passed on construction time. */ public function getOptions() : array { return $this->options; } } stream = $stream; } public function __destruct() { if (!$this->promise) { \_HumbugBoxd02f763d3c56\Amp\Promise\rethrow(new \_HumbugBoxd02f763d3c56\Amp\Coroutine($this->consume())); } } private function consume() : \Generator { try { if ($this->lastRead && null === (yield $this->lastRead)) { return; } while (null !== (yield $this->stream->read())) { // Discard unread bytes from message. } } catch (\Throwable $exception) { // If exception is thrown here the connection closed anyway. } } /** * @inheritdoc * * @throws \Error If a buffered message was requested by calling buffer(). */ public final function read() : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->promise) { throw new \Error("Cannot stream message data once a buffered message has been requested"); } return $this->lastRead = $this->stream->read(); } /** * Buffers the entire message and resolves the returned promise then. * * @return Promise Resolves with the entire message contents. */ public final function buffer() : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->promise) { return $this->promise; } return $this->promise = \_HumbugBoxd02f763d3c56\Amp\call(function () { $buffer = ''; if ($this->lastRead && null === (yield $this->lastRead)) { return $buffer; } while (null !== ($chunk = (yield $this->stream->read()))) { $buffer .= $chunk; } return $buffer; }); } } read()) !== null) { * $buffer .= $chunk; * } * * return $buffer; * }); * } * ``` */ interface InputStream { /** * Reads data from the stream. * * @return Promise Resolves with a string when new data is available or `null` if the stream has closed. * * @psalm-return Promise * * @throws PendingReadError Thrown if another read operation is still pending. */ public function read() : \_HumbugBoxd02f763d3c56\Amp\Promise; } contents = $contents; } /** * Reads data from the stream. * * @return Promise Resolves with the full contents or `null` if the stream has closed / already been consumed. */ public function read() : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->contents === null) { return new \_HumbugBoxd02f763d3c56\Amp\Success(); } $promise = new \_HumbugBoxd02f763d3c56\Amp\Success($this->contents); $this->contents = null; return $promise; } } */ private $writes; /** @var bool */ private $writable = \true; /** @var int|null */ private $chunkSize; /** * @param resource $stream Stream resource. * @param int|null $chunkSize Chunk size per `fwrite()` operation. */ public function __construct($stream, int $chunkSize = null) { if (!\is_resource($stream) || \get_resource_type($stream) !== 'stream') { throw new \Error("Expected a valid stream"); } $meta = \stream_get_meta_data($stream); if (\strpos($meta["mode"], "r") !== \false && \strpos($meta["mode"], "+") === \false) { throw new \Error("Expected a writable stream"); } \stream_set_blocking($stream, \false); \stream_set_write_buffer($stream, 0); $this->resource = $stream; $this->chunkSize =& $chunkSize; $writes = $this->writes = new \SplQueue(); $writable =& $this->writable; $resource =& $this->resource; $this->watcher = \_HumbugBoxd02f763d3c56\Amp\Loop::onWritable($stream, static function ($watcher, $stream) use($writes, &$chunkSize, &$writable, &$resource) { static $emptyWrites = 0; try { while (!$writes->isEmpty()) { /** @var Deferred $deferred */ list($data, $previous, $deferred) = $writes->shift(); $length = \strlen($data); if ($length === 0) { $deferred->resolve(0); continue; } if (!\is_resource($stream) || ($metaData = @\stream_get_meta_data($stream)) && $metaData['eof']) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ClosedException("The stream was closed by the peer"); } // Error reporting suppressed since fwrite() emits E_WARNING if the pipe is broken or the buffer is full. // Use conditional, because PHP doesn't like getting null passed if ($chunkSize) { $written = @\fwrite($stream, $data, $chunkSize); } else { $written = @\fwrite($stream, $data); } \assert( $written !== \false || \PHP_VERSION_ID >= 70400, // PHP 7.4+ returns false on EPIPE. "Trying to write on a previously fclose()'d resource. Do NOT manually fclose() resources the still referenced in the loop." ); // PHP 7.4.0 and 7.4.1 may return false on EAGAIN. if ($written === \false && \PHP_VERSION_ID >= 70402) { $message = "Failed to write to stream"; if ($error = \error_get_last()) { $message .= \sprintf("; %s", $error["message"]); } throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException($message); } // Broken pipes between processes on macOS/FreeBSD do not detect EOF properly. if ($written === 0 || $written === \false) { if ($emptyWrites++ > self::MAX_CONSECUTIVE_EMPTY_WRITES) { $message = "Failed to write to stream after multiple attempts"; if ($error = \error_get_last()) { $message .= \sprintf("; %s", $error["message"]); } throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException($message); } $writes->unshift([$data, $previous, $deferred]); return; } $emptyWrites = 0; if ($length > $written) { $data = \substr($data, $written); $writes->unshift([$data, $written + $previous, $deferred]); return; } $deferred->resolve($written + $previous); } } catch (\Throwable $exception) { $resource = null; $writable = \false; /** @psalm-suppress PossiblyUndefinedVariable */ $deferred->fail($exception); while (!$writes->isEmpty()) { list(, , $deferred) = $writes->shift(); $deferred->fail($exception); } \_HumbugBoxd02f763d3c56\Amp\Loop::cancel($watcher); } finally { if ($writes->isEmpty()) { \_HumbugBoxd02f763d3c56\Amp\Loop::disable($watcher); } } }); \_HumbugBoxd02f763d3c56\Amp\Loop::disable($this->watcher); } /** * Writes data to the stream. * * @param string $data Bytes to write. * * @return Promise Succeeds once the data has been successfully written to the stream. * * @throws ClosedException If the stream has already been closed. */ public function write(string $data) : \_HumbugBoxd02f763d3c56\Amp\Promise { return $this->send($data, \false); } /** * Closes the stream after all pending writes have been completed. Optionally writes a final data chunk before. * * @param string $finalData Bytes to write. * * @return Promise Succeeds once the data has been successfully written to the stream. * * @throws ClosedException If the stream has already been closed. */ public function end(string $finalData = "") : \_HumbugBoxd02f763d3c56\Amp\Promise { return $this->send($finalData, \true); } private function send(string $data, bool $end = \false) : \_HumbugBoxd02f763d3c56\Amp\Promise { if (!$this->writable) { return new \_HumbugBoxd02f763d3c56\Amp\Failure(new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ClosedException("The stream is not writable")); } $length = \strlen($data); $written = 0; if ($end) { $this->writable = \false; } if ($this->writes->isEmpty()) { if ($length === 0) { if ($end) { $this->close(); } return new \_HumbugBoxd02f763d3c56\Amp\Success(0); } if (!\is_resource($this->resource) || ($metaData = @\stream_get_meta_data($this->resource)) && $metaData['eof']) { return new \_HumbugBoxd02f763d3c56\Amp\Failure(new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ClosedException("The stream was closed by the peer")); } // Error reporting suppressed since fwrite() emits E_WARNING if the pipe is broken or the buffer is full. // Use conditional, because PHP doesn't like getting null passed. if ($this->chunkSize) { $written = @\fwrite($this->resource, $data, $this->chunkSize); } else { $written = @\fwrite($this->resource, $data); } \assert( $written !== \false || \PHP_VERSION_ID >= 70400, // PHP 7.4+ returns false on EPIPE. "Trying to write on a previously fclose()'d resource. Do NOT manually fclose() resources the still referenced in the loop." ); // PHP 7.4.0 and 7.4.1 may return false on EAGAIN. if ($written === \false && \PHP_VERSION_ID >= 70402) { $message = "Failed to write to stream"; if ($error = \error_get_last()) { $message .= \sprintf("; %s", $error["message"]); } return new \_HumbugBoxd02f763d3c56\Amp\Failure(new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException($message)); } $written = (int) $written; // Cast potential false to 0. if ($length === $written) { if ($end) { $this->close(); } return new \_HumbugBoxd02f763d3c56\Amp\Success($written); } $data = \substr($data, $written); } $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); if ($length - $written > self::LARGE_CHUNK_SIZE) { $chunks = \str_split($data, self::LARGE_CHUNK_SIZE); $data = \array_pop($chunks); foreach ($chunks as $chunk) { $this->writes->push([$chunk, $written, new \_HumbugBoxd02f763d3c56\Amp\Deferred()]); $written += self::LARGE_CHUNK_SIZE; } } $this->writes->push([$data, $written, $deferred]); \_HumbugBoxd02f763d3c56\Amp\Loop::enable($this->watcher); $promise = $deferred->promise(); if ($end) { $promise->onResolve([$this, "close"]); } return $promise; } /** * Closes the stream forcefully. Multiple `close()` calls are ignored. * * @return void */ public function close() { if ($this->resource) { // Error suppression, as resource might already be closed $meta = @\stream_get_meta_data($this->resource); if ($meta && \strpos($meta["mode"], "+") !== \false) { @\stream_socket_shutdown($this->resource, \STREAM_SHUT_WR); } else { /** @psalm-suppress InvalidPropertyAssignmentValue psalm reports this as closed-resource */ @\fclose($this->resource); } } $this->free(); } /** * Nulls reference to resource, marks stream unwritable, and fails any pending write. * * @return void */ private function free() { $this->resource = null; $this->writable = \false; if (!$this->writes->isEmpty()) { $exception = new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ClosedException("The socket was closed before writing completed"); do { /** @var Deferred $deferred */ list(, , $deferred) = $this->writes->shift(); $deferred->fail($exception); } while (!$this->writes->isEmpty()); } \_HumbugBoxd02f763d3c56\Amp\Loop::cancel($this->watcher); } /** * @return resource|null Stream resource or null if end() has been called or the stream closed. */ public function getResource() { return $this->resource; } /** * @return void */ public function setChunkSize(int $chunkSize) { $this->chunkSize = $chunkSize; } public function __destruct() { if ($this->resource !== null) { $this->free(); } } } source = $inputStream; $this->delimiter = $delimiter === null ? "\n" : $delimiter; $this->lineMode = $delimiter === null; } /** * @return Promise */ public function readLine() : \_HumbugBoxd02f763d3c56\Amp\Promise { return \_HumbugBoxd02f763d3c56\Amp\call(function () { if (\false !== \strpos($this->buffer, $this->delimiter)) { list($line, $this->buffer) = \explode($this->delimiter, $this->buffer, 2); return $this->lineMode ? \rtrim($line, "\r") : $line; } while (null !== ($chunk = (yield $this->source->read()))) { $this->buffer .= $chunk; if (\false !== \strpos($this->buffer, $this->delimiter)) { list($line, $this->buffer) = \explode($this->delimiter, $this->buffer, 2); return $this->lineMode ? \rtrim($line, "\r") : $line; } } if ($this->buffer === "") { return null; } $line = $this->buffer; $this->buffer = ""; return $this->lineMode ? \rtrim($line, "\r") : $line; }); } public function getBuffer() : string { return $this->buffer; } /** * @return void */ public function clearBuffer() { $this->buffer = ""; } } read()) !== null) { * // Immediately use $chunk, reducing memory consumption since the entire message is never buffered. * } * * @deprecated Use Amp\ByteStream\Payload instead. */ class Message implements \_HumbugBoxd02f763d3c56\Amp\ByteStream\InputStream, \_HumbugBoxd02f763d3c56\Amp\Promise { /** @var InputStream */ private $source; /** @var string */ private $buffer = ""; /** @var Deferred|null */ private $pendingRead; /** @var Coroutine|null */ private $coroutine; /** @var bool True if onResolve() has been called. */ private $buffering = \false; /** @var Deferred|null */ private $backpressure; /** @var bool True if the iterator has completed. */ private $complete = \false; /** @var \Throwable|null Used to fail future reads on failure. */ private $error; /** * @param InputStream $source An iterator that only emits strings. */ public function __construct(\_HumbugBoxd02f763d3c56\Amp\ByteStream\InputStream $source) { $this->source = $source; } private function consume() : \Generator { while (($chunk = (yield $this->source->read())) !== null) { $buffer = $this->buffer .= $chunk; if ($buffer === "") { continue; // Do not succeed reads with empty string. } elseif ($this->pendingRead) { $deferred = $this->pendingRead; $this->pendingRead = null; $this->buffer = ""; $deferred->resolve($buffer); $buffer = ""; // Destroy last emitted chunk to free memory. } elseif (!$this->buffering) { $buffer = ""; // Destroy last emitted chunk to free memory. $this->backpressure = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); (yield $this->backpressure->promise()); } } $this->complete = \true; if ($this->pendingRead) { $deferred = $this->pendingRead; $this->pendingRead = null; $deferred->resolve($this->buffer !== "" ? $this->buffer : null); $this->buffer = ""; } return $this->buffer; } /** @inheritdoc */ public final function read() : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->pendingRead) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\PendingReadError(); } if ($this->coroutine === null) { $this->coroutine = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($this->consume()); $this->coroutine->onResolve(function ($error) { if ($error) { $this->error = $error; } if ($this->pendingRead) { $deferred = $this->pendingRead; $this->pendingRead = null; $deferred->fail($error); } }); } if ($this->error) { return new \_HumbugBoxd02f763d3c56\Amp\Failure($this->error); } if ($this->buffer !== "") { $buffer = $this->buffer; $this->buffer = ""; if ($this->backpressure) { $backpressure = $this->backpressure; $this->backpressure = null; $backpressure->resolve(); } return new \_HumbugBoxd02f763d3c56\Amp\Success($buffer); } if ($this->complete) { return new \_HumbugBoxd02f763d3c56\Amp\Success(); } $this->pendingRead = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); return $this->pendingRead->promise(); } /** @inheritdoc */ public final function onResolve(callable $onResolved) { $this->buffering = \true; if ($this->coroutine === null) { $this->coroutine = new \_HumbugBoxd02f763d3c56\Amp\Coroutine($this->consume()); } if ($this->backpressure) { $backpressure = $this->backpressure; $this->backpressure = null; $backpressure->resolve(); } $this->coroutine->onResolve($onResolved); } /** * Exposes the source input stream. * * This might be required to resolve a promise with an InputStream, because promises in Amp can't be resolved with * other promises. * * @return InputStream */ public final function getInputStream() : \_HumbugBoxd02f763d3c56\Amp\ByteStream\InputStream { return $this->source; } } */ private $iterator; /** @var \Throwable|null */ private $exception; /** @var bool */ private $pending = \false; /** * @psam-param Iterator $iterator */ public function __construct(\_HumbugBoxd02f763d3c56\Amp\Iterator $iterator) { $this->iterator = $iterator; } /** @inheritdoc */ public function read() : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->exception) { return new \_HumbugBoxd02f763d3c56\Amp\Failure($this->exception); } if ($this->pending) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\PendingReadError(); } $this->pending = \true; /** @var Deferred $deferred */ $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); $this->iterator->advance()->onResolve(function ($error, $hasNextElement) use($deferred) { $this->pending = \false; if ($error) { $this->exception = $error; $deferred->fail($error); } elseif ($hasNextElement) { $chunk = $this->iterator->getCurrent(); if (!\is_string($chunk)) { $this->exception = new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException(\sprintf("Unexpected iterator value of type '%s', expected string", \is_object($chunk) ? \get_class($chunk) : \gettype($chunk))); $deferred->fail($this->exception); return; } $deferred->resolve($chunk); } else { $deferred->resolve(); } }); return $deferred->promise(); } } read())) !== null) { $written += \strlen($chunk); $writePromise = $destination->write($chunk); $chunk = null; // free memory (yield $writePromise); } return $written; }); } /** * @param \Amp\ByteStream\InputStream $source * * @return \Amp\Promise */ function buffer(\_HumbugBoxd02f763d3c56\Amp\ByteStream\InputStream $source) : \_HumbugBoxd02f763d3c56\Amp\Promise { return \_HumbugBoxd02f763d3c56\Amp\call(function () use($source) : \Generator { $buffer = ""; while (($chunk = (yield $source->read())) !== null) { $buffer .= $chunk; $chunk = null; // free memory } return $buffer; }); } /** * The php://input input buffer stream for the process associated with the currently active event loop. * * @return ResourceInputStream */ function getInputBufferStream() : \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceInputStream { static $key = \_HumbugBoxd02f763d3c56\Amp\ByteStream\InputStream::class . '\\input'; $stream = \_HumbugBoxd02f763d3c56\Amp\Loop::getState($key); if (!$stream) { $stream = new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceInputStream(\fopen('php://input', 'rb')); \_HumbugBoxd02f763d3c56\Amp\Loop::setState($key, $stream); } return $stream; } /** * The php://output output buffer stream for the process associated with the currently active event loop. * * @return ResourceOutputStream */ function getOutputBufferStream() : \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceOutputStream { static $key = \_HumbugBoxd02f763d3c56\Amp\ByteStream\OutputStream::class . '\\output'; $stream = \_HumbugBoxd02f763d3c56\Amp\Loop::getState($key); if (!$stream) { $stream = new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceOutputStream(\fopen('php://output', 'wb')); \_HumbugBoxd02f763d3c56\Amp\Loop::setState($key, $stream); } return $stream; } /** * The STDIN stream for the process associated with the currently active event loop. * * @return ResourceInputStream */ function getStdin() : \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceInputStream { static $key = \_HumbugBoxd02f763d3c56\Amp\ByteStream\InputStream::class . '\\stdin'; $stream = \_HumbugBoxd02f763d3c56\Amp\Loop::getState($key); if (!$stream) { $stream = new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceInputStream(\STDIN); \_HumbugBoxd02f763d3c56\Amp\Loop::setState($key, $stream); } return $stream; } /** * The STDOUT stream for the process associated with the currently active event loop. * * @return ResourceOutputStream */ function getStdout() : \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceOutputStream { static $key = \_HumbugBoxd02f763d3c56\Amp\ByteStream\OutputStream::class . '\\stdout'; $stream = \_HumbugBoxd02f763d3c56\Amp\Loop::getState($key); if (!$stream) { $stream = new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceOutputStream(\STDOUT); \_HumbugBoxd02f763d3c56\Amp\Loop::setState($key, $stream); } return $stream; } /** * The STDERR stream for the process associated with the currently active event loop. * * @return ResourceOutputStream */ function getStderr() : \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceOutputStream { static $key = \_HumbugBoxd02f763d3c56\Amp\ByteStream\OutputStream::class . '\\stderr'; $stream = \_HumbugBoxd02f763d3c56\Amp\Loop::getState($key); if (!$stream) { $stream = new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceOutputStream(\STDERR); \_HumbugBoxd02f763d3c56\Amp\Loop::setState($key, $stream); } return $stream; } function parseLineDelimitedJson(\_HumbugBoxd02f763d3c56\Amp\ByteStream\InputStream $stream, bool $assoc = \false, int $depth = 512, int $options = 0) : \_HumbugBoxd02f763d3c56\Amp\Iterator { return new \_HumbugBoxd02f763d3c56\Amp\Producer(static function (callable $emit) use($stream, $assoc, $depth, $options) { $reader = new \_HumbugBoxd02f763d3c56\Amp\ByteStream\LineReader($stream); while (null !== ($line = (yield $reader->readLine()))) { $line = \trim($line); if ($line === '') { continue; } /** @noinspection PhpComposerExtensionStubsInspection */ $data = \json_decode($line, $assoc, $depth, $options); /** @noinspection PhpComposerExtensionStubsInspection */ $error = \json_last_error(); /** @noinspection PhpComposerExtensionStubsInspection */ if ($error !== \JSON_ERROR_NONE) { /** @noinspection PhpComposerExtensionStubsInspection */ throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\StreamException('Failed to parse JSON: ' . \json_last_error_msg(), $error); } (yield $emit($data)); } }); } deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); } public function write(string $data) : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->closed) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ClosedException("The stream has already been closed."); } $this->contents .= $data; return new \_HumbugBoxd02f763d3c56\Amp\Success(\strlen($data)); } public function end(string $finalData = "") : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->closed) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ClosedException("The stream has already been closed."); } $this->contents .= $finalData; $this->closed = \true; $this->deferred->resolve($this->contents); $this->contents = ""; return new \_HumbugBoxd02f763d3c56\Amp\Success(\strlen($finalData)); } public function onResolve(callable $onResolved) { $this->deferred->promise()->onResolve($onResolved); } } streams = $streams; } /** @inheritDoc */ public function read() : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->reading) { throw new \_HumbugBoxd02f763d3c56\Amp\ByteStream\PendingReadError(); } if (!$this->streams) { return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } return \_HumbugBoxd02f763d3c56\Amp\call(function () { $this->reading = \true; try { while ($this->streams) { $chunk = (yield $this->streams[0]->read()); if ($chunk === null) { \array_shift($this->streams); continue; } return $chunk; } return null; } finally { $this->reading = \false; } }); } } The MIT License (MIT) Copyright (c) 2016-2020 amphp Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. > */ function xdebug_get_code_coverage() : array { } /** * @param array $configuration */ function xdebug_set_filter(int $group, int $list_type, array $configuration) : array { } function xdebug_start_code_coverage(int $options) : void { } function xdebug_stop_code_coverage(int $cleanup = 1) : void { } * * @param TArray $arr * @param mixed $search_value * @param bool $strict * * @return (TArray is non-empty-array ? non-empty-list : list) * @psalm-pure */ function array_keys(array $arr, $search_value = null, bool $strict = false) { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * * @return array * @psalm-pure */ function array_intersect(array $arr, array $arr2, array ...$arr3) { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * * @return array * @psalm-pure */ function array_intersect_key(array $arr, array $arr2, array ...$arr3) { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * @param callable(TKey): int $keyCompareFunc * * @return array * * @psalm-pure */ function array_intersect_ukey(array $arr, array $arr2, array ...$arr3, callable $keyCompareFunc): array { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * * @return array * @psalm-pure */ function array_intersect_assoc(array $arr, array $arr2, array ...$arr3) { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * @param callable(TKey): int $keyCompareFunc * * @return array * * @psalm-pure */ function array_intersect_uassoc(array $arr, array $arr2, array ...$arr3, callable $keyCompareFunc): array {} { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * * @return array|false * @psalm-ignore-falsable-return * @psalm-pure */ function array_combine(array $arr, array $arr2) { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * * @return array * @psalm-pure */ function array_diff(array $arr, array $arr2, array ...$arr3) { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * * @return array * @psalm-pure */ function array_diff_key(array $arr, array $arr2, array ...$arr3) { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * @param callable(TKey, TKey): int $keyCompareFunc * * @return array * @psalm-pure */ function array_diff_ukey(array $arr, array $arr2, array ...$arr3, callable $keyCompareFunc): array {} { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * * @return array * @psalm-pure */ function array_diff_assoc(array $arr, array $arr2, array ...$arr3) { } /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array $arr2 * @param array ...$arr3 * @param callable(TKey, TKey): int $keyCompareFunc * * @return array * @psalm-pure */ function array_diff_uassoc(array $arr, array $arr2, array ... $arr3, callable $keyCompareFunc): array {} /** * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * * @return array * @psalm-pure */ function array_flip(array $arr) { } /** * @psalm-template TKey as array-key * @psalm-template TArray as array * * @param TArray $arr * * @return (TArray is array ? null : TKey|null) * @psalm-pure * @psalm-ignore-nullable-return */ function key($arr) { } /** * @psalm-template TKey as array-key * @psalm-template TArray as array * * @param TArray $arr * * @return (TArray is array ? null : (TArray is non-empty-array ? TKey : TKey|null)) * @psalm-pure */ function array_key_first($arr) { } /** * @psalm-template TKey as array-key * @psalm-template TArray as array * * @param TArray $arr * * @return (TArray is array ? null : (TArray is non-empty-array ? TKey : TKey|null)) * @psalm-pure */ function array_key_last($arr) { } /** * @psalm-template T * * @param mixed $needle * @param array $haystack * @param bool $strict * * @return T|false * @psalm-pure */ function array_search($needle, array $haystack, bool $strict = false) { } /** * @psalm-template T * * @param T[] $arr * @param-out list $arr */ function shuffle(array &$arr): bool { } /** * @psalm-template T * * @param T[] $arr * @param-out list $arr */ function sort(array &$arr, int $sort_flags = SORT_REGULAR): bool { } /** * @psalm-template T * * @param T[] $arr * @param-out list $arr */ function rsort(array &$arr, int $sort_flags = SORT_REGULAR): bool { } /** * @psalm-template T * * @param T[] $arr * @param callable(T,T):int $callback * @param-out list $arr */ function usort(array &$arr, callable $callback): bool { } /** * @psalm-template TKey * @psalm-template T * * @param array $arr * @param callable(T,T):int $callback * @param-out array $arr */ function uasort(array &$arr, callable $callback): bool { } /** * @psalm-template TKey * @psalm-template T * * @param array $arr * @param callable(TKey,TKey):int $callback * @param-out array $arr */ function uksort(array &$arr, callable $callback): bool { } /** * @psalm-pure * * @psalm-template K of array-key * @psalm-template T * * @param array $arr * * @return array */ function array_change_key_case(array $arr, int $case = CASE_LOWER) { } /** * @psalm-pure * * @psalm-template TKey as array-key * * @param TKey $key * @param array $search * * @return bool */ function array_key_exists($key, array $search) : bool { } /** * @psalm-pure * * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $arr * @param array ...$arr2 * * @return array */ function array_merge_recursive(array $arr, array ...$arr2) { } /** * @psalm-pure * * @psalm-template TKey as array-key * @psalm-template TValue * * @param array $keys * @param TValue $value * * @return array */ function array_fill_keys(array $keys, $value): array { } /** * @psalm-pure * * @psalm-template TKey * * @param string $pattern * @param array $input * @param 0|1 $flags 1=PREG_GREP_INVERT * @return array */ function preg_grep($pattern, array $input, $flags = 0) { } /** * @param resource $handle * @param-out closed-resource $handle */ function fclose(&$handle) : bool { } /** * @param string $reference * @param-out null $reference */ function sodium_memzero(string &$reference): void { } /** * @param mixed $var * @param bool $return * @return ($return is true ? string : void) * * @psalm-taint-specialize * @psalm-flow ($var) -> return */ function var_export($var, bool $return = false) {} /** * @param mixed $var * @param bool $return * @return ($return is true ? string : true) * * @psalm-taint-specialize * @psalm-flow ($var) -> return */ function print_r($var, bool $return = false) {} /** * @psalm-pure * * @param mixed $var * @return ($return is true ? string : bool) */ function highlight_file($var, bool $return = false) {} /** * @psalm-pure * * @param mixed $var * @return ($return is true ? string : bool) * * @psalm-flow ($var) -> return */ function highlight_string($var, bool $return = false) {} /** * @psalm-pure * * @return ($get_as_float is true ? float : string) */ function microtime(bool $get_as_float = false) {} /** * @psalm-pure * * @return ($return_float is true ? float : array) */ function gettimeofday(bool $return_float = false) {} /** * @psalm-pure * * @param numeric $number * @return ($number is int ? int : ($number is float ? float : int|float)) */ function abs($number) {} /** * @psalm-pure * * @template T as string|int|float * @template TStep as int|float * @param T $start * @param T $end * @param TStep $step * @return ( * T is int * ? (TStep is int ? list : list) * : ( * T is float * ? list * : ( * T is string * ? list * : ( * T is int|float * ? list * : list * ) * ) * ) * ) */ function range($start, $end, $step = 1) {} /** * @psalm-pure * * @return ( * $format is 'd'|'j'|'N'|'w'|'z'|'W'|'m'|'n'|'t'|'L'|'o'|'Y'|'y'|'B'|'g'|'G'|'h'|'H'|'i'|'s'|'u'|'v'|'Z'|'U'|'I' * ? numeric-string * : ($timestamp is numeric ? string : string|false) * ) */ function date(string $format, int $timestamp = 0) {} /** * @psalm-pure * * @param mixed $vars * @param-out string|int|float $vars * @return (func_num_args() is 2 ? list : int) */ function sscanf(string $str, string $format, &...$vars) {} /** * @psalm-pure * * @return ( * func_num_args() is 1 * ? array{dirname: string, basename: string, extension?: string, filename: string} * : string * ) */ function pathinfo(string $path, int $options = \PATHINFO_DIRNAME) {} /** * @psalm-pure * * @return (func_num_args() is 0 ? array : string|false) */ function getenv(string $varname = '', bool $local_only = false) {} /** * @psalm-pure * * @return ( * $str is non-empty-string ? non-empty-lowercase-string : lowercase-string * ) * * @psalm-flow ($str) -> return */ function strtolower(string $str) : string {} /** * @psalm-pure * * @psalm-flow ($str) -> return */ function strtoupper(string $str) : string {} /** * @psalm-pure * * @param string $haystack * * @psalm-return positive-int|0|false */ function strpos($haystack, $needle, int $offset = 0) : int {} /** * @psalm-pure * * @psalm-flow ($str) -> return */ function trim(string $str, string $character_mask = " \t\n\r\0\x0B") : string {} /** * @psalm-pure * * @psalm-flow ($str) -> return */ function ltrim(string $str, string $character_mask = " \t\n\r\0\x0B") : string {} /** * @psalm-pure * * @psalm-flow ($str) -> return */ function rtrim(string $str, string $character_mask = " \t\n\r\0\x0B") : string {} /** * @psalm-pure * * @param string|array $glue * * @return ( * $glue is non-empty-string * ? ($pieces is non-empty-array * ? non-empty-string * : string) * : string * ) * * @psalm-flow ($glue) -> return * @psalm-flow ($pieces) -(array-fetch)-> return */ function implode($glue, array $pieces = []) : string {} /** * @psalm-pure * * @psalm-flow ($string) -(array-assignment)-> return */ function explode(string $delimiter, string $string, int $limit = -1) : array {} /** * @psalm-pure * * @psalm-flow ($subject) -(array-assignment)-> return * * @template TFlags as 0|1|2|3|4|5|6|7 * * @param TFlags $flags * * @return (TFlags is 0|2 ? non-empty-list|false : (TFlags is 1|3 ? list|false : list|false)) * * @psalm-ignore-falsable-return */ function preg_split(string $pattern, string $subject, int $limit = -1, int $flags = 0) {} /** * @param array $input * * @return ( * $input is array * ? int * : ($input is array * ? float * : float|int * ) * ) */ function array_sum(array $input) {} /** * @param array $input * * @return ( * $input is array * ? int * : ($input is array * ? float * : float|int * ) * ) */ function array_product(array $input) {} /** * @psalm-pure * * @psalm-taint-escape html * @psalm-flow ($str) -> return */ function strip_tags(string $str, ?string $allowable_tags = null) : string {} /** * @psalm-pure * * @psalm-taint-escape html * * @psalm-flow ($string) -> return */ function htmlentities(string $string, ?int $quote_style = null, ?string $charset = null, bool $double_encode = true) : string {} /** * @psalm-pure * * @psalm-taint-unescape html * * @psalm-flow ($string) -> return */ function html_entity_decode(string $string, ?int $quote_style = null, ?string $charset = null) : string {} /** * @psalm-pure * * @psalm-taint-escape html * @psalm-taint-escape sql * * @psalm-flow ($string) -> return */ function htmlspecialchars(string $string, int $flags = ENT_COMPAT | ENT_HTML401, string $encoding = 'UTF-8', bool $double_encode = true) : string {} /** * @psalm-pure * * @psalm-taint-unescape html * @psalm-taint-unescape sql * * @psalm-flow ($string) -> return */ function htmlspecialchars_decode(string $string, ?int $quote_style = null) : string {} /** * @psalm-pure * * @param string|array $search * @param string|array $replace * @param string|array $subject * @param int $count * @return ($subject is array ? array : string) * * @psalm-flow ($replace, $subject) -> return */ function str_replace($search, $replace, $subject, &$count = null) {} /** * @psalm-pure * * @param string|string[] $search * @param string|array $replace * @param string|array $subject * @param int $count * @return ($subject is array ? array : string) * * @psalm-flow ($replace, $subject) -> return */ function preg_replace($search, $replace, $subject, int $limit = -1, &$count = null) {} /** * @param string|string[] $search * @param callable(array):string $replace * @param string|array $subject * @param int $count * @return ($subject is array ? array : string) * * @psalm-taint-specialize * @psalm-flow ($subject) -> return */ function preg_replace_callback($search, $replace, $subject, int $limit = -1, &$count = null) {} /** * @psalm-pure * @template TFlags as int * * @param string $pattern * @param string $subject * @param mixed $matches * @param TFlags $flags * @param-out ( * TFlags is 1 * ? array> * : (TFlags is 2 * ? list> * : (TFlags is 256|257 * ? array> * : (TFlags is 258 * ? list> * : (TFlags is 512|513 * ? array> * : (TFlags is 514 * ? list> * : (TFlags is 770 * ? list> * : array * ) * ) * ) * ) * ) * ) * ) $matches * @return int|false * @psalm-ignore-falsable-return */ function preg_match_all($pattern, $replace, &$matches = [], int $flags = 1, int $offset = 0) {} /** * @psalm-pure * * @return string|false * @psalm-ignore-falsable-return * * @psalm-flow ($string) -> return */ function substr(string $string, int $start, ?int $length = null) {} /** * @psalm-pure * * @psalm-flow ($str) -> return */ function preg_quote(string $str, ?string $delimiter = null) : string {} /** * @psalm-pure * * @param string|int|float $args * * @psalm-flow ($format, $args) -> return */ function sprintf(string $format, ...$args) : string {} /** * @psalm-pure * * @return string|false * @psalm-ignore-falsable-return * * @psalm-flow ($path) -> return */ function realpath(string $path) {} /** * @psalm-pure * * @param numeric-string $left_operand * @param numeric-string $right_operand * @return ($right_operand is "0" ? null : numeric-string) */ function bcdiv(string $left_operand, string $right_operand, int $scale = 0): ?string {} /** * @psalm-pure * * @param scalar|null|object $var * @return string The string value of var. * * @psalm-flow ($var) -> return */ function strval ($var): string {} /** * @return ($input is non-empty-string ? non-empty-list : non-empty-list|array{null}) * @psalm-pure */ function str_getcsv(string $input, string $delimiter = ',', string $enclosure = '"', string $escape = '\\\\') { } /** * @return ($min is positive-int ? positive-int : int) */ function random_int(int $min, int $max): int {} /** * @template TKey as array-key * * @param array $array * * @return array * * @psalm-pure */ function array_count_values(array $array): array {} */ interface Collection extends Traversable, Countable, JsonSerializable { /** * @return Collection */ public function copy(): Collection; /** * @return array */ public function toArray(): array; } /** * @template TValue * @implements Sequence */ final class Deque implements Sequence { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Deque */ public function copy(): Deque { } /** * @return list */ public function toArray(): array { } /** * @return TValue * @throws \UnderflowException */ public function first() { } /** * @return TValue * @throws \OutOfRangeException */ public function get(int $index) { } /** * @return TValue * @throws \UnderflowException */ public function last() { } /** * @return TValue * @throws \UnderflowException */ public function pop() { } /** * @template TCarry * @param callable(TCarry, TValue): TCarry $callback * @param TCarry $initial * @return TCarry */ public function reduce(callable $callback, $initial = null) { } /** * @return TValue * @throws \OutOfRangeException */ public function remove(int $index) { } /** * @return TValue * @throws \UnderflowException */ public function shift() { } /** * @template TValue2 * @param iterable $values * @return Deque */ public function merge(iterable $values): Deque { } /** * @param (callable(TValue): bool)|null $callback * @return Deque */ public function filter(callable $callback = null): Deque { } /** * @template TNewValue * @param callable(TValue): TNewValue $callback * @return Deque */ public function map(callable $callback): Deque { } /** * @return Deque */ public function reversed(): Deque { } /** * @return Deque */ public function slice(int $offset, ?int $length = null): Deque { } /** * @param (callable(TValue, TValue): int)|null $comparator * @return Sequence */ public function sorted(callable $comparator = null): Deque { } } /** * @template TKey * @template TValue * @implements Collection */ final class Map implements Collection { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Map */ public function copy(): Map { } /** * @param callable(TKey, TValue): TValue $callback */ public function apply(callable $callback): void { } /** * @return Pair * @throws UnderflowException */ public function first(): Pair { } /** * @return Pair * @throws UnderflowException */ public function last(): Pair { } /** * @return Pair * @throws OutOfRangeException */ public function skip(int $position): Pair { } /** * @template TKey2 * @template TValue2 * @param iterable $values * @return Map */ public function merge(iterable $values): Map { } /** * @template TKey2 * @template TValue2 * @param Map $map * @return Map */ public function intersect(Map $map): Map { } /** * @template TValue2 * @param Map $map * @return Map */ public function diff(Map $map): Map { } /** * @param TKey $key */ public function hasKey($key): bool { } /** * @param TValue $value */ public function hasValue($value): bool { } /** * @param (callable(TKey, TValue): bool)|null $callback * @return Map */ public function filter(callable $callback = null): Map { } /** * @template TDefault * @param TKey $key * @param TDefault $default * @return ( * func_num_args() is 1 * ? TValue * : TValue|TDefault * ) * @throws OutOfBoundsException */ public function get($key, $default = null) { } /** * @return Set */ public function keys(): Set { } /** * @template TNewValue * @param callable(TKey, TValue): TNewValue $callback * @return Map */ public function map(callable $callback): Map { } /** * @return Sequence> */ public function pairs(): Sequence { } /** * @param TKey $key * @param TValue $value */ public function put($key, $value) { } /** * @param iterable $values */ public function putAll(iterable $values) { } /** * @template TCarry * @param callable(TCarry, TKey, TValue): TCarry $callback * @param TCarry $initial * @return TCarry */ public function reduce(callable $callback, $initial = null) { } /** * @template TDefault * @param TKey $key * @param TDefault $default * @return ( * func_num_args() is 1 * ? TValue * : TValue|TDefault * ) * @throws \OutOfBoundsException */ public function remove($key, $default = null) { } /** * @return Map */ public function reversed(): Map { } /** * @return Map */ public function slice(int $offset, ?int $length = null): Map { } /** * @param (callable(TValue, TValue): int)|null $comparator */ public function sort(callable $comparator = null) { } /** * @param (callable(TValue, TValue): int)|null $comparator * @return Map */ public function sorted(callable $comparator = null): Map { } /** * @param (callable(TKey, TKey): int)|null $comparator */ public function ksort(callable $comparator = null) { } /** * @param (callable(TKey, TKey): int)|null $comparator * @return Map */ public function ksorted(callable $comparator = null): Map { } /** * @return array */ public function toArray(): array { } /** * @return Sequence */ public function values(): Sequence { } /** * @template TKey2 * @template TValue2 * @param Map $map * @return Map */ public function union(Map $map): Map { } /** * @template TKey2 * @template TValue2 * @param Map $map * @return Map */ public function xor(Map $map): Map { } } /** * @template-covariant TKey * @template-covariant TValue */ final class Pair implements JsonSerializable { /** * @var TKey */ public $key; /** * @var TValue */ public $value; /** * @param TKey $key * @param TValue $value */ public function __construct($key = null, $value = null) { } /** * @return Pair */ public function copy(): Pair { } } /** * @template TValue * @extends Collection */ interface Sequence extends Collection { /** * @param callable(TValue): TValue $callback */ public function apply(callable $callback): void; /** * @param TValue ...$values */ public function contains(...$values): bool; /** * @param (callable(TValue): bool)|null $callback * @return Sequence */ public function filter(callable $callback = null): Sequence; /** * @param TValue $value * @return int|false */ public function find($value); /** * @return TValue * @throws \UnderflowException */ public function first(); /** * @return TValue * @throws \OutOfRangeException */ public function get(int $index); /** * @param TValue ...$values * @throws \OutOfRangeException */ public function insert(int $index, ...$values); /** * @param string $glue * @return string */ public function join(string $glue = null): string; /** * @return TValue * @throws \UnderflowException */ public function last(); /** * @template TNewValue * @param callable(TValue): TNewValue $callback * @return Sequence */ public function map(callable $callback): Sequence; /** * @template TValue2 * @param iterable $values * @return Sequence */ public function merge(iterable $values): Sequence; /** * @return TValue * @throws \UnderflowException */ public function pop(); /** * @param TValue ...$values */ public function push(...$values); /** * @template TCarry * @param callable(TCarry, TValue): TCarry $callback * @param TCarry $initial * @return TCarry */ public function reduce(callable $callback, $initial = null); /** * @return TValue * @throws \OutOfRangeException */ public function remove(int $index); /** * @return Sequence */ public function reversed(): Sequence; /** * @param TValue $value * @throws \OutOfRangeException */ public function set(int $index, $value); /** * @return TValue * @throws \UnderflowException */ public function shift(); /** * @return Sequence */ public function slice(int $index, ?int $length = null): Sequence; /** * @param (callable(TValue, TValue): int)|null $comparator */ public function sort(callable $comparator = null); /** * @param (callable(TValue, TValue): int)|null $comparator * @return Sequence */ public function sorted(callable $comparator = null): Sequence; /** * @param TValue ...$values */ public function unshift(...$values); } /** * @template TValue * @implements Sequence */ final class Vector implements Sequence { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Vector */ public function copy(): Vector { } /** * @return list */ public function toArray(): array { } /** * @return TValue * @throws \UnderflowException */ public function first() { } /** * @return TValue * @throws \OutOfRangeException */ public function get(int $index) { } /** * @return TValue * @throws \UnderflowException */ public function last() { } /** * @return TValue * @throws \UnderflowException */ public function pop() { } /** * @template TCarry * @param callable(TCarry, TValue): TCarry $callback * @param TCarry $initial * @return TCarry */ public function reduce(callable $callback, $initial = null) { } /** * @return TValue * @throws \OutOfRangeException */ public function remove(int $index) { } /** * @return TValue * @throws \UnderflowException */ public function shift() { } /** * @return Vector */ public function reversed(): Vector { } /** * @return Vector */ public function slice(int $offset, ?int $length = null): Vector { } /** * @param (callable(TValue, TValue): int)|null $comparator * @return Vector */ public function sorted(callable $comparator = null): Vector { } /** * @param (callable(TValue): bool)|null $callback * @return Vector */ public function filter(callable $callback = null): Vector { } /** * @template TNewValue * @param callable(TValue): TNewValue $callback * @return Vector */ public function map(callable $callback): Vector { } /** * @template TValue2 * @param iterable $values * @return Vector */ public function merge(iterable $values): Sequence { } } /** * @template TValue * @implements Collection */ final class Set implements Collection { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @param TValue ...$values */ public function add(...$values): void { } /** * @param TValue ...$values */ public function contains(...$values): bool { } /** * @return Set */ public function copy(): Set { } /** * @template TValue2 * @param Set $set * @return Set */ public function diff(Set $set): Set { } /** * @param (callable(TValue): bool)|null $callback * @return Set */ public function filter(callable $callback = null): Set { } /** * @return TValue * @throws \UnderflowException */ public function first() { } /** * @return TValue * @throws \OutOfRangeException */ public function get(int $index) { } /** * @template TValue2 * @param Set $set * @return Set */ public function intersect(Set $set): Set { } /** * @return TValue * @throws \UnderflowException */ public function last() { } /** * @template TValue2 * @param iterable $values * @return Set */ public function merge(iterable $values): Set { } /** * @param TValue ...$values */ public function remove(...$values): void { } /** * @return Set */ public function reversed(): Set { } /** * @return Set */ public function slice(int $index, ?int $length = null): Set { } /** * @param (callable(TValue, TValue): int)|null $comparator */ public function sort(callable $comparator = null): void { } /** * @param (callable(TValue, TValue): int)|null $comparator * @return Set */ public function sorted(callable $comparator = null): Set { } /** * @return list */ public function toArray(): array { } /** * @template TValue2 * @param Set $set * @return Set */ public function union(Set $set): Set { } /** * @template TValue2 * @param Set $set * @return Set */ public function xor(Set $set): Set { } } /** * @template TValue * @implements Collection */ final class Stack implements Collection { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Stack */ public function copy(): Stack { } /** * @return TValue * @throws UnderflowException */ public function peek() { } /** * @return TValue * @throws UnderflowException */ public function pop() { } /** * @param TValue ...$values */ public function push(...$values): void { } /** * @return list */ public function toArray(): array { } } /** * @template TValue * @implements Collection */ final class Queue implements Collection { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Queue */ public function copy(): Queue { } /** * @return TValue * @throws UnderflowException */ public function peek() { } /** * @return TValue * @throws UnderflowException */ public function pop() { } /** * @param TValue ...$values */ public function push(...$values): void { } /** * @return list */ public function toArray(): array { } } /** * @template TValue * @implements Collection */ final class PriorityQueue implements Collection { /** * @return PriorityQueue */ public function copy(): PriorityQueue { } /** * @return TValue * @throws UnderflowException */ public function peek() { } /** * @return TValue * @throws UnderflowException */ public function pop() { } /** * @param TValue $value */ public function push($value, int $priority): void { } /** * @return list */ public function toArray(): array { } } */ interface IteratorAggregate extends Traversable { /** * Retrieve an external iterator * @link http://php.net/manual/en/iteratoraggregate.getiterator.php * * @return Traversable An instance of an object implementing Iterator or Traversable * * @since 5.0.0 */ public function getIterator(); } /** * Interface for external iterators or objects that can be iterated * themselves internally. * @link http://php.net/manual/en/class.iterator.php * * @template-covariant TKey * @template-covariant TValue * * @template-extends Traversable */ interface Iterator extends Traversable { /** * Return the current element * @link http://php.net/manual/en/iterator.current.php * * @return TValue Can return any type. * * @since 5.0.0 */ public function current(); /** * Move forward to next element * @link http://php.net/manual/en/iterator.next.php * * @return void Any returned value is ignored. * * @since 5.0.0 */ public function next(); /** * Return the key of the current element * @link http://php.net/manual/en/iterator.key.php * * @return TKey scalar on success, or null on failure. * * @since 5.0.0 */ public function key(); /** * Checks if current position is valid * @link http://php.net/manual/en/iterator.valid.php * * @return bool The return value will be casted to boolean and then evaluated. * Returns true on success or false on failure. * * @since 5.0.0 */ public function valid(); /** * Rewind the Iterator to the first element * @link http://php.net/manual/en/iterator.rewind.php * * @return void Any returned value is ignored. * * @since 5.0.0 */ public function rewind(); } /** * @template-covariant TKey * @template-covariant TValue * * @template-extends Iterator */ interface OuterIterator extends Iterator { /** * @return Iterator */ public function getInnerIterator(); } /** * @template-covariant TKey * @template-covariant TValue * @template TIterator as Traversable * * @template-implements OuterIterator * * @mixin TIterator */ class IteratorIterator implements OuterIterator { /** * @param TIterator $iterator */ public function __construct(Traversable $iterator) {} /** * @return TIterator */ public function getInnerIterator() {} /** * Return the current element * @link http://php.net/manual/en/iterator.current.php * * @return TValue Can return any type. * * @since 5.0.0 */ public function current() {} /** * Move forward to next element * @link http://php.net/manual/en/iterator.next.php * * @return void Any returned value is ignored. * * @since 5.0.0 */ public function next() {} /** * Return the key of the current element * @link http://php.net/manual/en/iterator.key.php * * @return TKey scalar on success, or null on failure. * * @since 5.0.0 */ public function key() {} /** * @return bool The return value will be casted to boolean and then evaluated. * Returns true on success or false on failure. * * @since 5.0.0 */ public function valid() {} /** * Rewind the Iterator to the first element * @link http://php.net/manual/en/iterator.rewind.php * * @return void Any returned value is ignored. * * @since 5.0.0 */ public function rewind() {} } /** * @template TIterator as RecursiveIterator|IteratorAggregate * @mixin TIterator */ class RecursiveIteratorIterator implements OuterIterator { /** * @param TIterator $iterator * @param int $mode * @param int $flags * * @return void */ public function __construct($iterator, $mode = 0, $flags = 0) {} } /** * @template-covariant TKey * @template-covariant TValue * * @template-extends IteratorIterator */ class FilterIterator extends IteratorIterator { /** @return bool */ public abstract function accept () {} } /** * @template-covariant TKey * @template-covariant TValue * * @template-implements OuterIterator * @template-implements ArrayAccess * * @template-extends IteratorIterator */ class CachingIterator extends IteratorIterator implements OuterIterator , ArrayAccess , Countable { /** * @param Iterator $iterator */ public function __construct(Iterator $iterator, int $flags = self::CALL_TOSTRING) {} /** @return bool */ public function hasNext () {} /** * @return TValue Can return any type. */ public function current() {} /** * @return TKey scalar on success, or null on failure. */ public function key() {} } /** * @template-covariant TKey * @template-covariant TValue * * @template-implements OuterIterator * * @template-extends IteratorIterator */ class InfiniteIterator extends IteratorIterator implements OuterIterator { /** * @param Iterator $iterator */ public function __construct(Iterator $iterator) {} /** * @return TValue Can return any type. */ public function current() {} /** * @return TKey scalar on success, or null on failure. */ public function key() {} } /** * @template-covariant TKey * @template-covariant TValue * * @template-implements OuterIterator * * @template-extends IteratorIterator */ class LimitIterator extends IteratorIterator implements OuterIterator { /** * @param Iterator $iterator */ public function __construct(Iterator $iterator, int $offset = 0, int $count = -1) {} /** * @return TValue Can return any type. */ public function current() {} /** * @return TKey scalar on success, or null on failure. */ public function key() {} } /** * @template-covariant TKey * @template-covariant TValue * * @template-implements OuterIterator * * @template-extends FilterIterator */ class CallbackFilterIterator extends FilterIterator implements OuterIterator { /** * @param Iterator $iterator * @param callable(TValue, TKey, Iterator): bool $callback */ public function __construct(Iterator $iterator, callable $callback) {} /** * @return TValue Can return any type. */ public function current() {} /** * @return TKey scalar on success, or null on failure. */ public function key() {} } /** * @template-covariant TKey * @template-covariant TValue * * @template-extends IteratorIterator */ class NoRewindIterator extends IteratorIterator { /** * @param Iterator $iterator */ public function __construct(Iterator $iterator) {} /** * @return TValue Can return any type. */ public function current() {} /** * @return TKey scalar on success, or null on failure. */ public function key() {} } /** * @template-covariant TKey * @template-covariant TValue * @template TSend * @template-covariant TReturn * * @template-implements Traversable */ class Generator implements Traversable { /** * @return TValue Can return any type. */ public function current() {} /** * @return void Any returned value is ignored. */ public function next() {} /** * @return TKey scalar on success, or null on failure. */ public function key() {} /** * @return bool The return value will be casted to boolean and then evaluated. */ public function valid() {} /** * @return void Any returned value is ignored. */ public function rewind() {} /** * @return TReturn Can return any type. */ public function getReturn() {} /** * @param TSend $value * @return TValue Can return any type. */ public function send($value) {} /** * @return TValue Can return any type. */ public function throw(Throwable $exception) {} } /** * Interface to provide accessing objects as arrays. * @link http://php.net/manual/en/class.arrayaccess.php * * @template TKey * @template TValue */ interface ArrayAccess { /** * Whether a offset exists * @link http://php.net/manual/en/arrayaccess.offsetexists.php * * @param TKey $offset An offset to check for. * @return bool true on success or false on failure. * The return value will be casted to boolean if non-boolean was returned. * * @since 5.0.0 */ public function offsetExists($offset); /** * Offset to retrieve * @link http://php.net/manual/en/arrayaccess.offsetget.php * * @param TKey $offset The offset to retrieve. * @return TValue|null Can return all value types. * @psalm-ignore-nullable-return * * @since 5.0.0 */ public function offsetGet($offset); /** * Offset to set * @link http://php.net/manual/en/arrayaccess.offsetset.php * * @param TKey $offset The offset to assign the value to. * @param TValue $value The value to set. * @return void * * @since 5.0.0 */ public function offsetSet($offset, $value); /** * Offset to unset * @link http://php.net/manual/en/arrayaccess.offsetunset.php * * @param TKey $offset The offset to unset. * @return void * * @since 5.0.0 */ public function offsetUnset($offset); } /** * This class allows objects to work as arrays. * @link http://php.net/manual/en/class.arrayobject.php * * @template TKey * @template TValue * @template-implements IteratorAggregate * @template-implements ArrayAccess */ class ArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable { /** * Properties of the object have their normal functionality when accessed as list (var_dump, foreach, etc.). */ const STD_PROP_LIST = 1; /** * Entries can be accessed as properties (read and write). */ const ARRAY_AS_PROPS = 2; /** * Construct a new array object * @link http://php.net/manual/en/arrayobject.construct.php * * @param array|object $input The input parameter accepts an array or an Object. * @param int $flags Flags to control the behaviour of the ArrayObject object. * @param string $iterator_class Specify the class that will be used for iteration of the ArrayObject object. ArrayIterator is the default class used. * @psalm-param class-string>|class-string> $iterator_class * * @since 5.0.0 */ public function __construct($input = null, $flags = 0, $iterator_class = "ArrayIterator") { } /** * Returns whether the requested index exists * @link http://php.net/manual/en/arrayobject.offsetexists.php * * @param TKey $index The index being checked. * @return bool true if the requested index exists, otherwise false * * @since 5.0.0 */ public function offsetExists($index) { } /** * Returns the value at the specified index * @link http://php.net/manual/en/arrayobject.offsetget.php * * @param TKey $index The index with the value. * @return TValue The value at the specified index or false. * * @since 5.0.0 */ public function offsetGet($index) { } /** * Sets the value at the specified index to newval * @link http://php.net/manual/en/arrayobject.offsetset.php * * @param TKey $index The index being set. * @param TValue $newval The new value for the index. * @return void * * @since 5.0.0 */ public function offsetSet($index, $newval) { } /** * Unsets the value at the specified index * @link http://php.net/manual/en/arrayobject.offsetunset.php * * @param TKey $index The index being unset. * @return void * * @since 5.0.0 */ public function offsetUnset($index) { } /** * Appends the value * @link http://php.net/manual/en/arrayobject.append.php * * @param TValue $value The value being appended. * @return void * * @since 5.0.0 */ public function append($value) { } /** * Creates a copy of the ArrayObject. * @link http://php.net/manual/en/arrayobject.getarraycopy.php * * @return array a copy of the array. When the ArrayObject refers to an object * an array of the public properties of that object will be returned. * * @since 5.0.0 */ public function getArrayCopy() { } /** * Get the number of public properties in the ArrayObject * When the ArrayObject is constructed from an array all properties are public. * @link http://php.net/manual/en/arrayobject.count.php * * @return int The number of public properties in the ArrayObject. * * @since 5.0.0 */ public function count() { } /** * Gets the behavior flags. * @link http://php.net/manual/en/arrayobject.getflags.php * * @return int the behavior flags of the ArrayObject. * * @since 5.1.0 */ public function getFlags() { } /** * Sets the behavior flags. * * It takes on either a bitmask, or named constants. Using named * constants is strongly encouraged to ensure compatibility for future * versions. * * The available behavior flags are listed below. The actual * meanings of these flags are described in the * predefined constants. * * * ArrayObject behavior flags * * * * * * * * * * * * *
valueconstant
1 * ArrayObject::STD_PROP_LIST *
2 * ArrayObject::ARRAY_AS_PROPS *
* * @link http://php.net/manual/en/arrayobject.setflags.php * * @param int $flags The new ArrayObject behavior. * @return void * * @since 5.1.0 */ public function setFlags($flags) { } /** * Sort the entries by value * @link http://php.net/manual/en/arrayobject.asort.php * * @return void * * @since 5.2.0 */ public function asort() { } /** * Sort the entries by key * @link http://php.net/manual/en/arrayobject.ksort.php * * @return void * * @since 5.2.0 */ public function ksort() { } /** * Sort the entries with a user-defined comparison function and maintain key association * @link http://php.net/manual/en/arrayobject.uasort.php * * Function cmp_function should accept two * parameters which will be filled by pairs of entries. * The comparison function must return an integer less than, equal * to, or greater than zero if the first argument is considered to * be respectively less than, equal to, or greater than the * second. * * @param callable(TValue, TValue):int $cmp_function * @return void * * @since 5.2.0 */ public function uasort($cmp_function) { } /** * Sort the entries by keys using a user-defined comparison function * @link http://php.net/manual/en/arrayobject.uksort.php * * Function cmp_function should accept two * parameters which will be filled by pairs of entry keys. * The comparison function must return an integer less than, equal * to, or greater than zero if the first argument is considered to * be respectively less than, equal to, or greater than the * second. * * @param callable(TKey, TKey):int $cmp_function The callable comparison function. * @return void * * @since 5.2.0 */ public function uksort($cmp_function) { } /** * Sort entries using a "natural order" algorithm * @link http://php.net/manual/en/arrayobject.natsort.php * * @return void * * @since 5.2.0 */ public function natsort() { } /** * Sort an array using a case insensitive "natural order" algorithm * @link http://php.net/manual/en/arrayobject.natcasesort.php * * @return void * * @since 5.2.0 */ public function natcasesort() { } /** * Unserialize an ArrayObject * @link http://php.net/manual/en/arrayobject.unserialize.php * * @param string $serialized The serialized ArrayObject * @return void The unserialized ArrayObject * * @since 5.3.0 */ public function unserialize($serialized) { } /** * Serialize an ArrayObject * @link http://php.net/manual/en/arrayobject.serialize.php * * @return string The serialized representation of the ArrayObject. * * @since 5.3.0 */ public function serialize() { } /** * Create a new iterator from an ArrayObject instance * @link http://php.net/manual/en/arrayobject.getiterator.php * * @return ArrayIterator An iterator from an ArrayObject. * * @since 5.0.0 */ public function getIterator() { } /** * Exchange the array for another one. * @link http://php.net/manual/en/arrayobject.exchangearray.php * * @param mixed $input The new array or object to exchange with the current array. * @return array the old array. * * @since 5.1.0 */ public function exchangeArray($input) { } /** * Sets the iterator classname for the ArrayObject. * @link http://php.net/manual/en/arrayobject.setiteratorclass.php * * @param string $iterator_class The classname of the array iterator to use when iterating over this object. * @psalm-param class-string>|class-string> $iterator_class * @return void * * @since 5.1.0 */ public function setIteratorClass($iterator_class) { } /** * Gets the iterator classname for the ArrayObject. * @link http://php.net/manual/en/arrayobject.getiteratorclass.php * * @return string the iterator class name that is used to iterate over this object. * @psalm-return class-string>|class-string> * * @since 5.1.0 */ public function getIteratorClass() { } } /** * The Seekable iterator. * @link https://php.net/manual/en/class.seekableiterator.php * * @template-covariant TKey * @template-covariant TValue * @template-extends Iterator */ interface SeekableIterator extends Iterator { /** * Seeks to a position * @link https://php.net/manual/en/seekableiterator.seek.php * * @param int $position The position to seek to. * @return void * * @since 5.1.0 */ public function seek($position); } /** * This iterator allows to unset and modify values and keys while iterating * over Arrays and Objects. * @link http://php.net/manual/en/class.arrayiterator.php * * @template TKey as array-key * @template TValue * @template-implements SeekableIterator * @template-implements ArrayAccess */ class ArrayIterator implements SeekableIterator, ArrayAccess, Serializable, Countable { const STD_PROP_LIST = 1; const ARRAY_AS_PROPS = 2; /** * Construct an ArrayIterator * @link http://php.net/manual/en/arrayiterator.construct.php * * @param array $array The array or object to be iterated on. * @param int $flags Flags to control the behaviour of the ArrayObject object. * * @see ArrayObject::setFlags() * @since 5.0.0 */ public function __construct($array = array(), $flags = 0) { } /** * Check if offset exists * @link http://php.net/manual/en/arrayiterator.offsetexists.php * * @param TKey $index The offset being checked. * @return bool true if the offset exists, otherwise false * * @since 5.0.0 */ public function offsetExists($index) { } /** * Get value for an offset * @link http://php.net/manual/en/arrayiterator.offsetget.php * * @param TKey $index The offset to get the value from. * @return TValue The value at offset index. * * @since 5.0.0 */ public function offsetGet($index) { } /** * Set value for an offset * @link http://php.net/manual/en/arrayiterator.offsetset.php * * @param TKey $index The index to set for. * @param TValue $newval The new value to store at the index. * @return void * * @since 5.0.0 */ public function offsetSet($index, $newval) { } /** * Unset value for an offset * @link http://php.net/manual/en/arrayiterator.offsetunset.php * * @param TKey $index The offset to unset. * @return void * * @since 5.0.0 */ public function offsetUnset($index) { } /** * Append an element * @link http://php.net/manual/en/arrayiterator.append.php * * @param TValue $value The value to append. * @return void * * @since 5.0.0 */ public function append($value) { } /** * Get array copy * @link http://php.net/manual/en/arrayiterator.getarraycopy.php * * @return array A copy of the array, or array of public properties * if ArrayIterator refers to an object. * * @since 5.0.0 */ public function getArrayCopy() { } /** * Count elements * @link http://php.net/manual/en/arrayiterator.count.php * * @return int The number of elements or public properties in the associated * array or object, respectively. * * @since 5.0.0 */ public function count() { } /** * Get flags * @link http://php.net/manual/en/arrayiterator.getflags.php * * @return string The current flags. * * @since 5.1.0 */ public function getFlags() { } /** * Set behaviour flags * * A bitmask as follows: * 0 = Properties of the object have their normal functionality * when accessed as list (var_dump, foreach, etc.). * 1 = Array indices can be accessed as properties in read/write. * * @link http://php.net/manual/en/arrayiterator.setflags.php * * @param string $flags bitmask * @return void * * @since 5.1.0 */ public function setFlags($flags) { } /** * Sort array by values * @link http://php.net/manual/en/arrayiterator.asort.php * * @return void * * @since 5.2.0 */ public function asort() { } /** * Sort array by keys * @link http://php.net/manual/en/arrayiterator.ksort.php * * @return void * * @since 5.2.0 */ public function ksort() { } /** * User defined sort * @link http://php.net/manual/en/arrayiterator.uasort.php * * @param callable(TValue,TValue):int $cmp_function The compare function used for the sort. * @return void * * @since 5.2.0 */ public function uasort($cmp_function) { } /** * User defined sort * @link http://php.net/manual/en/arrayiterator.uksort.php * * @param callable(TKey,TKey):int $cmp_function The compare function used for the sort. * @return void * * @since 5.2.0 */ public function uksort($cmp_function) { } /** * Sort an array naturally * @link http://php.net/manual/en/arrayiterator.natsort.php * * @return void * * @since 5.2.0 */ public function natsort() { } /** * Sort an array naturally, case insensitive * @link http://php.net/manual/en/arrayiterator.natcasesort.php * * @return void * * @since 5.2.0 */ public function natcasesort() { } /** * Unserialize * @link http://php.net/manual/en/arrayiterator.unserialize.php * * @param string $serialized The serialized ArrayIterator object to be unserialized. * @return void * * @since 5.3.0 */ public function unserialize($serialized) { } /** * Serialize * @link http://php.net/manual/en/arrayiterator.serialize.php * * @return string The serialized ArrayIterator * * @since 5.3.0 */ public function serialize() { } /** * Rewind array back to the start * @link http://php.net/manual/en/arrayiterator.rewind.php * * @return void * * @since 5.0.0 */ public function rewind() { } /** * Return current array entry * @link http://php.net/manual/en/arrayiterator.current.php * * @return TValue The current array entry. * * @since 5.0.0 */ public function current() { } /** * Return current array key * @link http://php.net/manual/en/arrayiterator.key.php * * @return TKey The current array key. * * @since 5.0.0 */ public function key() { } /** * Move to next entry * @link http://php.net/manual/en/arrayiterator.next.php * * @return void * * @since 5.0.0 */ public function next() { } /** * Check whether array contains more entries * @link http://php.net/manual/en/arrayiterator.valid.php * * @return bool * * @since 5.0.0 */ public function valid() { } /** * Seek to position * @link http://php.net/manual/en/arrayiterator.seek.php * * @param int $position The position to seek to. * @return void * * @since 5.0.0 */ public function seek($position) { } } /** * The DOMElement class * @link http://php.net/manual/en/class.domelement.php */ class DOMDocument extends DOMNode { /** * @return DOMNodeList */ public function getElementsByTagName($name) {} /** * @return DOMNodeList */ public function getElementsByTagNameNS($namespaceURI, $localName) {} } /** * The DOMElement class * @link http://php.net/manual/en/class.domelement.php */ class DOMElement extends DOMNode { public function __construct(string $name, string $value = '', string $namespaceURI = '') {} /** * @return DOMNodeList */ public function getElementsByTagName($name) {} /** * @return DOMNodeList */ public function getElementsByTagNameNS($namespaceURI, $localName) {} } /** * @template-covariant TNode as DOMNode * @template-implements Traversable */ class DOMNodeList implements Traversable, Countable { /** * The number of nodes in the list. The range of valid child node indices is 0 to length - 1 inclusive. * * @var int * * @since 5.0 * @link http://php.net/manual/en/class.domnodelist.php#domnodelist.props.length */ public $length; /** * @param int $index * @return TNode|null * @psalm-ignore-nullable-return */ public function item($index) {} } /** * @template-covariant TNode as DOMNode * @template-implements Traversable */ class DOMNamedNodeMap implements Traversable, Countable { /** * @var int */ public $length; /** * @return TNode|null */ public function getNamedItem(string $name): ?DOMNode {} /** * @return TNode|null */ public function getNamedItemNS(string $namespaceURI, string $localName): ?DOMNode {} /** * @return TNode|null * @psalm-ignore-nullable-return */ public function item(int $index): ?DOMNode {} } /** * The SplDoublyLinkedList class provides the main functionalities of a doubly linked list. * @link https://php.net/manual/en/class.spldoublylinkedlist.php * * @template TKey * @template TValue * @template-implements Iterator * @template-implements ArrayAccess */ class SplDoublyLinkedList implements Iterator, Countable, ArrayAccess, Serializable { public function __construct() {} /** * Add/insert a new value at the specified index * * @param TKey $index The index where the new value is to be inserted. * @param TValue $newval The new value for the index. * @return void * * @link https://php.net/spldoublylinkedlist.add * @since 5.5.0 */ public function add($index, $newval) {} /** * Pops a node from the end of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.pop.php * * @return TValue The value of the popped node. * * @since 5.3.0 */ public function pop() {} /** * Shifts a node from the beginning of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.shift.php * * @return TValue The value of the shifted node. * * @since 5.3.0 */ public function shift() {} /** * Pushes an element at the end of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.push.php * * @param TValue $value The value to push. * @return void * * @since 5.3.0 */ public function push($value) {} /** * Prepends the doubly linked list with an element * @link https://php.net/manual/en/spldoublylinkedlist.unshift.php * * @param TValue $value The value to unshift. * @return void * * @since 5.3.0 */ public function unshift($value) {} /** * Peeks at the node from the end of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.top.php * * @return TValue The value of the last node. * * @since 5.3.0 */ public function top() {} /** * Peeks at the node from the beginning of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.bottom.php * * @return TValue The value of the first node. * * @since 5.3.0 */ public function bottom() {} /** * Counts the number of elements in the doubly linked list. * @link https://php.net/manual/en/spldoublylinkedlist.count.php * * @return int the number of elements in the doubly linked list. * * @since 5.3.0 */ public function count() {} /** * Checks whether the doubly linked list is empty. * @link https://php.net/manual/en/spldoublylinkedlist.isempty.php * * @return bool whether the doubly linked list is empty. * * @since 5.3.0 */ public function isEmpty() {} /** * Returns whether the requested $index exists * @link https://php.net/manual/en/spldoublylinkedlist.offsetexists.php * * @param TKey $index The index being checked. * @return bool true if the requested index exists, otherwise false * * @since 5.3.0 */ public function offsetExists($index) {} /** * Returns the value at the specified $index * @link https://php.net/manual/en/spldoublylinkedlist.offsetget.php * * @param TKey $index The index with the value. * @return TValue The value at the specified index. * * @since 5.3.0 */ public function offsetGet($index) {} /** * Sets the value at the specified $index to $newval * @link https://php.net/manual/en/spldoublylinkedlist.offsetset.php * * @param TKey $index The index being set. * @param TValue $newval The new value for the index. * @return void * * @since 5.3.0 */ public function offsetSet($index, $newval) {} /** * Unsets the value at the specified $index * @link https://php.net/manual/en/spldoublylinkedlist.offsetunset.php * * @param TKey $index The index being unset. * @return void * * @since 5.3.0 */ public function offsetUnset($index) {} /** * Return current array entry * @link https://php.net/manual/en/spldoublylinkedlist.current.php * * @return TValue The current node value. * * @since 5.3.0 */ public function current() {} /** * Return current node index * @link https://php.net/manual/en/spldoublylinkedlist.key.php * * @return TKey The current node index. * * @since 5.3.0 */ public function key() {} } /** * The SplFixedArray class provides the main functionalities of array. * The main differences between a SplFixedArray and a normal PHP array is that * the SplFixedArray is of fixed length and allows only integers within the range as indexes. * The advantage is that it uses less memory than a standard array. * * @link https://php.net/manual/en/class.splfixedarray.php * * @template TValue * @template-implements ArrayAccess * @template-implements Iterator */ class SplFixedArray implements Iterator, ArrayAccess, Countable { /** * Constructs a new fixed array * * Initializes a fixed array with a number of NULL values equal to size. * @link https://php.net/manual/en/splfixedarray.construct.php * * @param int $size The size of the fixed array. This expects a number between 0 and PHP_INT_MAX. * @since 5.3.0 */ public function __construct(int $size = 0) {} /** * Import a PHP array in a new SplFixedArray instance * @link https://php.net/manual/en/splfixedarray.fromarray.php * * @template TInValue * @param array $array The array to import * @param bool $save_indexes [optional] Try to save the numeric indexes used in the original array. * * @return SplFixedArray Instance of SplFixedArray containing the array content * @since 5.3.0 */ public static function fromArray(array $array, bool $save_indexes = true): SplFixedArray {} /** * Returns a PHP array from the fixed array * @link https://php.net/manual/en/splfixedarray.toarray.php * * @return array * @since 5.3.0 */ public function toArray(): array {} /** * Returns the size of the array. * @link https://php.net/manual/en/splfixedarray.getsize.php * * @return int The size of the array * @see SplFixedArray::count() * * @since 5.3.0 */ public function getSize(): int {} /** * Returns the size of the array. * @link https://php.net/manual/en/splfixedarray.count.php * * @return int The size of the array * * @since 5.3.0 */ public function count(): int {} /** * Rewind the iterator back to the start * @link https://php.net/manual/en/splfixedarray.rewind.php * * @return void * * @since 5.3.0 */ public function rewind(): void {} /** * Check whether the array contains more elements * @link https://php.net/manual/en/splfixedarray.valid.php * * @return bool true if the array contains any more elements, false otherwise. * * @since 5.3.0 */ public function valid(): bool {} /** * Returns current array index * @link https://php.net/manual/en/splfixedarray.key.php * * @return int The current array index * * @since 5.3.0 */ public function key(): int {} /** * Returns the current array entry * @link https://php.net/manual/en/splfixedarray.current.php * * @return TValue The current element value * * @since 5.3.0 */ public function current() {} /** * Move to the next entry * @link https://php.net/manual/en/splfixedarray.next.php * * @return void * * @since 5.3.0 */ public function next(): void {} /** * Returns whether the specified index exists * @link https://php.net/manual/en/splfixedarray.offsetexists.php * * @param int $index The index being checked. * @return bool true if the requested index exists, and false otherwise. * * @since 5.3.0 */ public function offsetExists(int $index): bool {} /** * Sets a new value at a specified index * @link https://php.net/manual/en/splfixedarray.offsetset.php * * @param int $index The index being sent. * @param TValue $newval The new value for the index * @return void * * @since 5.3.0 */ public function offsetSet(int $index, $newval): void {} /** * Unsets the value at the specified $index * @link https://php.net/manual/en/splfixedarray.offsetunset.php * * @param int $index The index being unset * @return void * * @since 5.3.0 */ public function offsetUnset(int $index): void {} /** * Returns the value at the specified index * @link https://php.net/manual/en/splfixedarray.offsetget.php * * @param int $index The index with the value * @return TValue The value at the specified index * * @since 5.3.0 */ public function offsetGet(int $index) {} } /** * The SplStack class provides the main functionalities of a stack implemented using a doubly linked list. * @link https://php.net/manual/en/class.splstack.php * * @template TValue * @template-extends SplDoublyLinkedList */ class SplStack extends SplDoublyLinkedList { } /** * The SplQueue class provides the main functionalities of a queue implemented using a doubly linked list. * @link https://php.net/manual/en/class.splqueue.php * * @template TValue * @template-extends SplDoublyLinkedList */ class SplQueue extends SplDoublyLinkedList { /** * Adds an element to the queue. * @link https://php.net/manual/en/splqueue.enqueue.php * * @param TValue $value The value to enqueue. * @return void * * @since 5.3.0 */ public function enqueue($value) {} /** * Dequeues a node from the queue * @link https://php.net/manual/en/splqueue.dequeue.php * * @return TValue The value of the dequeued node. * * @since 5.3.0 */ public function dequeue() {} } /** * The SplHeap class provides the main functionalities of a Heap. * @link https://php.net/manual/en/class.splheap.php * * @template TValue * @template-implements Iterator */ class SplHeap implements Iterator, Countable { public function __construct() {} /** * Compare elements in order to place them correctly in the heap while sifting up * @link https://php.net/manual/en/splheap.compare.php * * @param TValue $value1 The value of the first node being compared. * @param TValue $value2 The value of the second node being compared. * @return int Positive integer if value1 is greater than value2, 0 if they are equal, negative integer otherwise. * * @since 5.3.0 */ protected abstract function compare($value1, $value2): int {} /** * Counts the number of elements in the heap * @link https://php.net/manual/en/splheap.count.php * * @return int The number of elements in the heap. * * @since 5.3.0 */ public function count(): int {} /** * Get the current datastructure node. * @link https://php.net/manual/en/splheap.current.php * * @return TValue The current node value * * @since 5.3.0 */ public function current() {} /** * Extracts a node from top of the heap and sift up * @link https://php.net/manual/en/splheap.extract.php * * @return TValue The current node value * * @since 5.3.0 */ public function extract() {} /** * Inserts an element in the heap by sifting it up * @link https://php.net/manual/en/splheap.insert.php * * @param TValue $value The value to insert. * @return void * * @since 5.3.0 */ public function insert($value): void {} /** * Tells if the heap is in a corrupted state * @link https://php.net/manual/en/splheap.isCorrupted.php * * @return bool true if the heap is corrupted, false otherwise. * * @since 7.0.0 */ public function isCorrupted(): bool {} /** * Checks whether the heap is empty * @link https://php.net/manual/en/splheap.isEmpty.php * * @return bool Whether the heap is empty * * @since 5.3.0 */ public function isEmpty(): bool {} /** * Return current node index * @link https://php.net/manual/en/splheap.key.php * * @return int The current node index * * @since 5.3.0 */ public function key() {} /** * Move to the next node. This will delete the top node of the heap. * @link https://php.net/manual/en/splheap.next.php * * @return void * * @since 5.3.0 */ public function next(): void {} /** * Recover from the corrupted state and allow further actions on the heap * @link https://php.net/manual/en/splheap.recoverFromCorruption.php * * @return void * * @since 5.3.0 */ public function recoverFromCorruption(): void {} /** * Rewind iterator back to the start (no-op) * @link https://php.net/manual/en/splheap.rewind.php * * @return void * * @since 5.3.0 */ public function rewind(): void {} /** * Peeks at the node from the top of the heap * @link https://php.net/manual/en/splheap.top.php * * @return TValue The value of the node on the top. * * @since 5.3.0 */ public function top() {} /** * Check whether the heap contains any more nodes * @link https://php.net/manual/en/splheap.valid.php * * @return bool Returns true if the heap contains any more nodes, false otherwise. * * @since 5.3.0 */ public function valid(): bool {} } /** * The SplMaxHeap class provides the main functionalities of a heap, keeping the maximum on the top. * @link https://php.net/manual/en/class.splmaxheap.php * * @template TValue * @template-extends SplHeap */ class SplMaxHeap extends SplHeap { } /** * The SplMinHeap class provides the main functionalities of a heap, keeping the maximum on the top. * @link https://php.net/manual/en/class.splminheap.php * * @template TValue * @template-extends SplHeap */ class SplMinHeap extends SplHeap { } /** * The SplPriorityQueue class provides the main functionalities of a prioritized queue, implemented using a max heap. * @link https://php.net/manual/en/class.splpriorityqueue.php * * @template TPriority * @template TValue * @template-implements Iterator */ class SplPriorityQueue implements Iterator, Countable { /** * Extract the data */ const EXTR_DATA = 0x00000001; /** * Extract the priority */ const EXTR_PRIORITY = 0x00000002; /** * Extract an array containing both */ const EXTR_BOTH = 0x00000003; public function __construct() {} /** * Compare priorities in order to place them correctly in the queue while sifting up * @link https://php.net/manual/en/splpriorityqueue.compare.php * * @param TValue $priority1 The priority of the first node being compared. * @param TValue $priority2 The priority of the second node being compared. * @return int Positive integer if priority1 is greater than priority2, 0 if they are equal, negative integer otherwise. * * @since 5.3.0 */ public function compare($priority1, $priority2): int {} /** * Counts the number of elements in the queue * @link https://php.net/manual/en/splpriorityqueue.count.php * * @return int The number of elements in the queue. * * @since 5.3.0 */ public function count(): int {} /** * Get the current datastructure node. * @link https://php.net/manual/en/splpriorityqueue.current.php * * @return TValue The current node value * * @since 5.3.0 */ public function current() {} /** * Extracts a node from top of the queue and sift up * @link https://php.net/manual/en/splpriorityqueue.extract.php * * @return TValue The current node value * * @since 5.3.0 */ public function extract() {} /** * Get the flags of extraction * @link https://php.net/manual/en/splpriorityqueue.getextractflags.php * * @return SplPriorityQueue::EXTR_* Returns the current extraction mode * * @see SplPriorityQueue::setExtractFlags * * @since 5.3.0 */ public function getExtractFlags(): int {} /** * Inserts an element in the queue by sifting it up * @link https://php.net/manual/en/splpriorityqueue.insert.php * * @param TValue $value The value to insert. * @param TPriority $priority The associated priority. * @return true * * @since 5.3.0 */ public function insert($value, $priority): bool {} /** * Tells if the queue is in a corrupted state * @link https://php.net/manual/en/splpriorityqueue.isCorrupted.php * * @return bool true if the queue is corrupted, false otherwise. * * @since 7.0.0 */ public function isCorrupted(): bool {} /** * Checks whether the queue is empty * @link https://php.net/manual/en/splpriorityqueue.isEmpty.php * * @return bool Whether the queue is empty * * @since 5.3.0 */ public function isEmpty(): bool {} /** * Return current node index * @link https://php.net/manual/en/splpriorityqueue.key.php * * @return int The current node index * * @since 5.3.0 */ public function key() {} /** * Move to the next node. * @link https://php.net/manual/en/splpriorityqueue.next.php * * @return void * * @since 5.3.0 */ public function next(): void {} /** * Recover from the corrupted state and allow further actions on the queue * @link https://php.net/manual/en/splpriorityqueue.recoverFromCorruption.php * * @return void * * @since 5.3.0 */ public function recoverFromCorruption(): void {} /** * Rewind iterator back to the start (no-op) * @link https://php.net/manual/en/splpriorityqueue.rewind.php * * @return void * * @since 5.3.0 */ public function rewind(): void {} /** * Sets the mode of extraction * @link https://php.net/manual/en/splpriorityqueue.setextractflags.php * * @param SplPriorityQueue::EXTR_* $flags Defines what is extracted by SplPriorityQueue::current(), SplPriorityQueue::top() and SplPriorityQueue::extract(). * * @return void * * @since 5.3.0 */ public function setExtractFlags(int $flags): void {} /** * Peeks at the node from the top of the queue * @link https://php.net/manual/en/splpriorityqueue.top.php * * @return TValue The value of the node on the top. * * @since 5.3.0 */ public function top() {} /** * Check whether the queue contains any more nodes * @link https://php.net/manual/en/splpriorityqueue.valid.php * * @return bool Returns true if the queue contains any more nodes, false otherwise. * * @since 5.3.0 */ public function valid(): bool {} } /** * The SplObjectStorage class provides a map from objects to data or, by * ignoring data, an object set. This dual purpose can be useful in many * cases involving the need to uniquely identify objects. * @link https://php.net/manual/en/class.splobjectstorage.php * * @template TObject as object * @template TArrayValue * @template-implements ArrayAccess * @template-implements Iterator */ class SplObjectStorage implements Countable, Iterator, Serializable, ArrayAccess { public function __construct() {} /** * Adds an object in the storage * @link https://php.net/manual/en/splobjectstorage.attach.php * * @param TObject $object The object to add. * @param TArrayValue|null $data [optional] The data to associate with the object. * @return void * * @since 5.1.0 */ public function attach($object, $data = null) {} /** * Removes an object from the storage * @link https://php.net/manual/en/splobjectstorage.detach.php * * @param TObject $object The object to remove. * @return void * * @since 5.1.0 */ public function detach($object) {} /** * Checks if the storage contains a specific object * @link https://php.net/manual/en/splobjectstorage.contains.php * * @param TObject $object The object to look for. * @return bool true if the object is in the storage, false otherwise. * * @since 5.1.0 */ public function contains($object) {} /** * Adds all objects from another storage * @link https://php.net/manual/en/splobjectstorage.addall.php * * @param SplObjectStorage $storage The storage you want to import. * @return void * * @since 5.3.0 */ public function addAll($storage) {} /** * Removes objects contained in another storage from the current storage * @link https://php.net/manual/en/splobjectstorage.removeall.php * * @param SplObjectStorage $storage The storage containing the elements to remove. * @return void * * @since 5.3.0 */ public function removeAll($storage) {} /** * Removes all objects except for those contained in another storage from the current storage * @link https://php.net/manual/en/splobjectstorage.removeallexcept.php * * @param SplObjectStorage $storage The storage containing the elements to retain in the current storage. * @return void * * @since 5.3.6 */ public function removeAllExcept($storage) {} /** * Returns the data associated with the current iterator entry * @link https://php.net/manual/en/splobjectstorage.getinfo.php * * @return TArrayValue The data associated with the current iterator position. * * @since 5.3.0 */ public function getInfo() {} /** * Sets the data associated with the current iterator entry * @link https://php.net/manual/en/splobjectstorage.setinfo.php * * @param TArrayValue $data The data to associate with the current iterator entry. * @return void * * @since 5.3.0 */ public function setInfo($data) {} /** * Returns the number of objects in the storage * @link https://php.net/manual/en/splobjectstorage.count.php * * @return int The number of objects in the storage. * * @since 5.1.0 */ public function count() {} /** * Rewind the iterator to the first storage element * @link https://php.net/manual/en/splobjectstorage.rewind.php * * @return void * * @since 5.1.0 */ public function rewind() {} /** * Returns if the current iterator entry is valid * @link https://php.net/manual/en/splobjectstorage.valid.php * * @return bool true if the iterator entry is valid, false otherwise. * * @since 5.1.0 */ public function valid() {} /** * Returns the index at which the iterator currently is * @link https://php.net/manual/en/splobjectstorage.key.php * * @return int The index corresponding to the position of the iterator. * * @since 5.1.0 */ public function key() {} /** * Returns the current storage entry * @link https://php.net/manual/en/splobjectstorage.current.php * * @return TObject The object at the current iterator position. * * @since 5.1.0 */ public function current() {} /** * Move to the next entry * @link https://php.net/manual/en/splobjectstorage.next.php * * @return void * * @since 5.1.0 */ public function next() {} /** * Unserializes a storage from its string representation * @link https://php.net/manual/en/splobjectstorage.unserialize.php * * @param string $serialized The serialized representation of a storage. * @return void * * @since 5.2.2 */ public function unserialize($serialized) {} /** * Serializes the storage * @link https://php.net/manual/en/splobjectstorage.serialize.php * * @return string A string representing the storage. * * @since 5.2.2 */ public function serialize() {} /** * Checks whether an object exists in the storage * @link https://php.net/manual/en/splobjectstorage.offsetexists.php * * @param TObject $object The object to look for. * @return bool true if the object exists in the storage, and false otherwise. * * @since 5.3.0 */ public function offsetExists($object) {} /** * Associates data to an object in the storage * @link https://php.net/manual/en/splobjectstorage.offsetset.php * * @param TObject $object The object to associate data with. * @param TArrayValue|null $data [optional] The data to associate with the object. * @return void * * @since 5.3.0 */ public function offsetSet($object, $data = null) {} /** * Removes an object from the storage * @link https://php.net/manual/en/splobjectstorage.offsetunset.php * * @param TObject $object The object to remove. * @return void * * @since 5.3.0 */ public function offsetUnset($object) {} /** * Returns the data associated with an object * @link https://php.net/manual/en/splobjectstorage.offsetget.php * * @param TObject $object The object to look for. * @return TArrayValue The data previously associated with the object in the storage. * * @since 5.3.0 */ public function offsetGet($object) {} /** * Calculate a unique identifier for the contained objects * @link https://php.net/manual/en/splobjectstorage.gethash.php * * @param object $object object whose identifier is to be calculated. * @return string A string with the calculated identifier. * * @since 5.4.0 */ public function getHash($object) {} } /** * @template-covariant T as object * * @property-read class-string $name */ class ReflectionClass implements Reflector { /** * @var class-string */ public $name; /** * @param T|class-string|trait-string $argument */ public function __construct($argument) {} /** * @return class-string */ public function getName(): string; /** * @param mixed ...$args * * @return T */ public function newInstance(...$args): object {} /** * @param array $args * * @return T */ public function newInstanceArgs(array $args): object {} /** * @return T */ public function newInstanceWithoutConstructor(): object; /** * @return ?array * @psalm-ignore-nullable-return */ public function getTraitNames(): array {} } /** * @template-covariant T as object * @psalm-immutable */ final class WeakReference { // always fail public function __construct(); /** * @template TIn as object * @param TIn $referent * @return WeakReference */ public static function create(object $referent): WeakReference; /** @return ?T */ public function get(): ?object; } runAndCollect(function () use($current_dir, $options, $vendor_dir) : ?\Composer\Autoload\ClassLoader { return requireAutoloaders($current_dir, isset($options['r']), $vendor_dir); }); // If Xdebug is enabled, restart without it (new \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\XdebugHandler('PSALTER'))->check(); $path_to_config = get_path_to_config($options); $args = getArguments(); $operation = null; $last_arg = null; $to_refactor = []; foreach ($args as $arg) { if ($arg === '--move') { $operation = 'move'; continue; } if ($arg === '--into') { if ($operation !== 'move' || !$last_arg) { die('--into is not expected here' . \PHP_EOL); } $operation = 'move_into'; continue; } if ($arg === '--rename') { $operation = 'rename'; continue; } if ($arg === '--to') { if ($operation !== 'rename' || !$last_arg) { die('--to is not expected here' . \PHP_EOL); } $operation = 'rename_to'; continue; } if ($arg[0] === '-') { $operation = null; continue; } if ($operation === 'move_into' || $operation === 'rename_to') { if (!$last_arg) { die('Expecting a previous argument' . \PHP_EOL); } if ($operation === 'move_into') { $last_arg_parts = \preg_split('/, ?/', $last_arg); foreach ($last_arg_parts as $last_arg_part) { if (\strpos($last_arg_part, '::')) { [, $identifier_name] = \explode('::', $last_arg_part); $to_refactor[$last_arg_part] = $arg . '::' . $identifier_name; } else { $namespace_parts = \explode('\\', $last_arg_part); $class_name = \end($namespace_parts); $to_refactor[$last_arg_part] = $arg . '\\' . $class_name; } } } else { $to_refactor[$last_arg] = $arg; } $last_arg = null; $operation = null; continue; } if ($operation === 'move' || $operation === 'rename') { $last_arg = $arg; continue; } die('Unexpected argument "' . $arg . '"' . \PHP_EOL); } if (!$to_refactor) { die('No --move or --rename arguments supplied' . \PHP_EOL); } $config = initialiseConfig($path_to_config, $current_dir, \Psalm\Report::TYPE_CONSOLE, $first_autoloader); $config->setIncludeCollector($include_collector); if ($config->resolve_from_config_file) { $current_dir = $config->base_dir; \chdir($current_dir); } $threads = isset($options['threads']) ? (int) $options['threads'] : \max(1, \Psalm\Internal\Analyzer\ProjectAnalyzer::getCpuCount() - 2); $providers = new \Psalm\Internal\Provider\Providers(new \Psalm\Internal\Provider\FileProvider(), new \Psalm\Internal\Provider\ParserCacheProvider($config, \false), new \Psalm\Internal\Provider\FileStorageCacheProvider($config), new \Psalm\Internal\Provider\ClassLikeStorageCacheProvider($config), null, new \Psalm\Internal\Provider\ProjectCacheProvider(\Psalm\Internal\Composer::getLockFilePath($current_dir))); $debug = \array_key_exists('debug', $options) || \array_key_exists('debug-by-line', $options); $progress = $debug ? new \Psalm\Progress\DebugProgress() : new \Psalm\Progress\DefaultProgress(); if (\array_key_exists('debug-emitted-issues', $options)) { $config->debug_emitted_issues = \true; } $project_analyzer = new \Psalm\Internal\Analyzer\ProjectAnalyzer($config, $providers, new \Psalm\Report\ReportOptions(), [], $threads, $progress); if (\array_key_exists('debug-by-line', $options)) { $project_analyzer->debug_lines = \true; } $config->visitComposerAutoloadFiles($project_analyzer); $project_analyzer->refactorCodeAfterCompletion($to_refactor); $start_time = \microtime(\true); $project_analyzer->check($current_dir); \Psalm\IssueBuffer::finish($project_analyzer, \false, $start_time); 0 && $memLimit < 8 * 1024 * 1024 * 1024) { \ini_set('memory_limit', (string) (8 * 1024 * 1024 * 1024)); } \gc_collect_cycles(); \gc_disable(); require_once __DIR__ . '/Psalm/Internal/exception_handler.php'; $args = \array_slice($argv, 1); $valid_short_options = ['f:', 'm', 'h', 'r:', 'c:']; $valid_long_options = ['help', 'debug', 'debug-by-line', 'debug-emitted-issues', 'config:', 'file:', 'root:', 'plugin:', 'issues:', 'list-supported-issues', 'php-version:', 'dry-run', 'safe-types', 'find-unused-code', 'threads:', 'codeowner:', 'allow-backwards-incompatible-changes:', 'add-newline-between-docblock-annotations:', 'no-cache']; // get options from command line $options = \getopt(\implode('', $valid_short_options), $valid_long_options); \array_map( /** * @param string $arg */ function ($arg) use($valid_long_options, $valid_short_options) : void { if (\substr($arg, 0, 2) === '--' && $arg !== '--') { $arg_name = \preg_replace('/=.*$/', '', \substr($arg, 2)); if ($arg_name === 'alter') { // valid option for psalm, ignored by psalter return; } if (!\in_array($arg_name, $valid_long_options) && !\in_array($arg_name . ':', $valid_long_options) && !\in_array($arg_name . '::', $valid_long_options)) { \fwrite(\STDERR, 'Unrecognised argument "--' . $arg_name . '"' . \PHP_EOL . 'Type --help to see a list of supported arguments' . \PHP_EOL); exit(1); } } }, $args ); if (\array_key_exists('help', $options)) { $options['h'] = \false; } if (\array_key_exists('monochrome', $options)) { $options['m'] = \false; } if (isset($options['config'])) { $options['c'] = $options['config']; } if (isset($options['c']) && \is_array($options['c'])) { die('Too many config files provided' . \PHP_EOL); } if (\array_key_exists('h', $options)) { echo <<runAndCollect(function () use($current_dir, $options, $vendor_dir) : ?\Composer\Autoload\ClassLoader { return requireAutoloaders($current_dir, isset($options['r']), $vendor_dir); }); // If Xdebug is enabled, restart without it (new \_HumbugBoxd02f763d3c56\Composer\XdebugHandler\XdebugHandler('PSALTER'))->check(); $paths_to_check = getPathsToCheck(isset($options['f']) ? $options['f'] : null); $path_to_config = get_path_to_config($options); $config = initialiseConfig($path_to_config, $current_dir, \Psalm\Report::TYPE_CONSOLE, $first_autoloader); $config->setIncludeCollector($include_collector); if ($config->resolve_from_config_file) { $current_dir = $config->base_dir; \chdir($current_dir); } $threads = isset($options['threads']) ? (int) $options['threads'] : 1; if (isset($options['no-cache'])) { $providers = new \Psalm\Internal\Provider\Providers(new \Psalm\Internal\Provider\FileProvider()); } else { $providers = new \Psalm\Internal\Provider\Providers(new \Psalm\Internal\Provider\FileProvider(), new \Psalm\Internal\Provider\ParserCacheProvider($config, \false), new \Psalm\Internal\Provider\FileStorageCacheProvider($config), new \Psalm\Internal\Provider\ClassLikeStorageCacheProvider($config), null, new \Psalm\Internal\Provider\ProjectCacheProvider(\Psalm\Internal\Composer::getLockFilePath($current_dir))); } if (\array_key_exists('list-supported-issues', $options)) { echo \implode(',', \Psalm\Internal\Analyzer\ProjectAnalyzer::getSupportedIssuesToFix()) . \PHP_EOL; exit; } $debug = \array_key_exists('debug', $options) || \array_key_exists('debug-by-line', $options); $progress = $debug ? new \Psalm\Progress\DebugProgress() : new \Psalm\Progress\DefaultProgress(); $stdout_report_options = new \Psalm\Report\ReportOptions(); $stdout_report_options->use_color = !\array_key_exists('m', $options); $project_analyzer = new \Psalm\Internal\Analyzer\ProjectAnalyzer($config, $providers, $stdout_report_options, [], $threads, $progress); if (\array_key_exists('debug-by-line', $options)) { $project_analyzer->debug_lines = \true; } if (\array_key_exists('debug-emitted-issues', $options)) { $config->debug_emitted_issues = \true; } $config->visitComposerAutoloadFiles($project_analyzer); if (\array_key_exists('issues', $options)) { if (!\is_string($options['issues']) || !$options['issues']) { die('Expecting a comma-separated list of issues' . \PHP_EOL); } $issues = \explode(',', $options['issues']); $keyed_issues = []; foreach ($issues as $issue) { $keyed_issues[$issue] = \true; } } else { $keyed_issues = []; } if (isset($options['php-version'])) { if (!\is_string($options['php-version'])) { die('Expecting a version number in the format x.y' . \PHP_EOL); } $project_analyzer->setPhpVersion($options['php-version']); } if (isset($options['codeowner'])) { if (\file_exists('CODEOWNERS')) { $codeowners_file_path = \realpath('CODEOWNERS'); } elseif (\file_exists('.github/CODEOWNERS')) { $codeowners_file_path = \realpath('.github/CODEOWNERS'); } elseif (\file_exists('docs/CODEOWNERS')) { $codeowners_file_path = \realpath('docs/CODEOWNERS'); } else { die('Cannot use --codeowner without a CODEOWNERS file' . \PHP_EOL); } $codeowners_file = \file_get_contents($codeowners_file_path); $codeowner_lines = \array_map(function (string $line) : array { $line_parts = \preg_split('/\\s+/', $line); $file_selector = \substr(\array_shift($line_parts), 1); return [$file_selector, $line_parts]; }, \array_filter(\explode("\n", $codeowners_file), function (string $line) : bool { $line = \trim($line); // currently we don’t match wildcard files or files that could appear anywhere // in the repo return $line && $line[0] === '/' && \strpos($line, '*') === \false; })); $codeowner_files = []; foreach ($codeowner_lines as [$path, $owners]) { if (!\file_exists($path)) { continue; } foreach ($owners as $i => $owner) { $owners[$i] = \strtolower($owner); } if (!\is_dir($path)) { if (\pathinfo($path, \PATHINFO_EXTENSION) === 'php') { $codeowner_files[$path] = $owners; } } else { foreach ($providers->file_provider->getFilesInDir($path, ['php']) as $php_file_path) { $codeowner_files[$php_file_path] = $owners; } } } if (!$codeowner_files) { die('Could not find any available entries in CODEOWNERS' . \PHP_EOL); } $desired_codeowners = \is_array($options['codeowner']) ? $options['codeowner'] : [$options['codeowner']]; /** @psalm-suppress MixedAssignment */ foreach ($desired_codeowners as $desired_codeowner) { if (!\is_string($desired_codeowner)) { die('Invalid --codeowner ' . (string) $desired_codeowner . \PHP_EOL); } if ($desired_codeowner[0] !== '@') { die('--codeowner option must start with @' . \PHP_EOL); } $matched_file = \false; foreach ($codeowner_files as $file_path => $owners) { if (\in_array(\strtolower($desired_codeowner), $owners)) { $paths_to_check[] = $file_path; $matched_file = \true; } } if (!$matched_file) { die('User/group ' . $desired_codeowner . ' does not own any PHP files' . \PHP_EOL); } } } if (isset($options['allow-backwards-incompatible-changes'])) { $allow_backwards_incompatible_changes = \filter_var($options['allow-backwards-incompatible-changes'], \FILTER_VALIDATE_BOOLEAN, ['flags' => \FILTER_NULL_ON_FAILURE]); if ($allow_backwards_incompatible_changes === null) { die('--allow-backwards-incompatible-changes expects a boolean value [true|false|1|0]' . \PHP_EOL); } $project_analyzer->getCodebase()->allow_backwards_incompatible_changes = $allow_backwards_incompatible_changes; } if (isset($options['add-newline-between-docblock-annotations'])) { $doc_block_add_new_line_before_return = \filter_var($options['add-newline-between-docblock-annotations'], \FILTER_VALIDATE_BOOLEAN, ['flags' => \FILTER_NULL_ON_FAILURE]); if ($doc_block_add_new_line_before_return === null) { die('--add-newline-between-docblock-annotations expects a boolean value [true|false|1|0]' . \PHP_EOL); } \Psalm\Internal\Scanner\ParsedDocblock::addNewLineBetweenAnnotations($doc_block_add_new_line_before_return); } $plugins = []; if (isset($options['plugin'])) { $plugins = $options['plugin']; if (!\is_array($plugins)) { $plugins = [$plugins]; } } /** @var string $plugin_path */ foreach ($plugins as $plugin_path) { \Psalm\Config::getInstance()->addPluginPath($current_dir . $plugin_path); } $find_unused_code = \array_key_exists('find-unused-code', $options); foreach ($keyed_issues as $issue_name => $_) { // MissingParamType requires the scanning of all files to inform possible params if (\strpos($issue_name, 'Unused') !== \false || $issue_name === 'MissingParamType' || $issue_name === 'UnnecessaryVarAnnotation' || $issue_name === 'all') { $find_unused_code = \true; break; } } if ($find_unused_code) { $project_analyzer->getCodebase()->reportUnusedCode(); } $project_analyzer->alterCodeAfterCompletion(\array_key_exists('dry-run', $options), \array_key_exists('safe-types', $options)); if ($keyed_issues === ['all' => \true]) { $project_analyzer->setAllIssuesToFix(); } else { try { $project_analyzer->setIssuesToFix($keyed_issues); } catch (\Psalm\Exception\UnsupportedIssueToFixException $e) { \fwrite(\STDERR, $e->getMessage() . \PHP_EOL); exit(1); } } $start_time = \microtime(\true); if ($paths_to_check === null || \count($paths_to_check) > 1 || $find_unused_code) { if ($paths_to_check) { $files_to_update = []; foreach ($paths_to_check as $path_to_check) { if (!\is_dir($path_to_check)) { $files_to_update[] = (string) \realpath($path_to_check); } else { foreach ($providers->file_provider->getFilesInDir($path_to_check, ['php']) as $php_file_path) { $files_to_update[] = $php_file_path; } } } $project_analyzer->getCodebase()->analyzer->setFilesToUpdate($files_to_update); } $project_analyzer->check($current_dir); } elseif ($paths_to_check) { foreach ($paths_to_check as $path_to_check) { if (\is_dir($path_to_check)) { $project_analyzer->checkDir($path_to_check); } else { $project_analyzer->checkFile($path_to_check); } } } \Psalm\IssueBuffer::finish($project_analyzer, \false, $start_time); runAndCollect(function () use($current_dir, $options, $vendor_dir) : ?\Composer\Autoload\ClassLoader { return requireAutoloaders($current_dir, isset($options['r']), $vendor_dir); }); if (\array_key_exists('v', $options)) { echo 'Psalm ' . PSALM_VERSION . \PHP_EOL; exit; } $output_format = isset($options['output-format']) && \is_string($options['output-format']) ? $options['output-format'] : \Psalm\Report::TYPE_CONSOLE; $init_level = null; $init_source_dir = null; if (isset($options['i'])) { if (\file_exists($current_dir . 'psalm.xml')) { die('A config file already exists in the current directory' . \PHP_EOL); } $args = \array_values(\array_filter($args, function (string $arg) : bool { return $arg !== '--ansi' && $arg !== '--no-ansi' && $arg !== '-i' && $arg !== '--init' && $arg !== '--debug' && $arg !== '--debug-by-line' && $arg !== '--debug-emitted-issues' && \strpos($arg, '--disable-extension=') !== 0 && \strpos($arg, '--root=') !== 0 && \strpos($arg, '--r=') !== 0; })); if (\count($args)) { if (\count($args) > 2) { die('Too many arguments provided for psalm --init' . \PHP_EOL); } if (isset($args[1])) { if (!\preg_match('/^[1-8]$/', $args[1])) { die('Config strictness must be a number between 1 and 8 inclusive' . \PHP_EOL); } $init_level = (int) $args[1]; } $init_source_dir = $args[0]; } $vendor_dir = \Psalm\getVendorDir($current_dir); if ($init_level === null) { echo "Calculating best config level based on project files\n"; \Psalm\Config\Creator::createBareConfig($current_dir, $init_source_dir, $vendor_dir); $config = \Psalm\Config::getInstance(); } else { try { $template_contents = \Psalm\Config\Creator::getContents($current_dir, $init_source_dir, $init_level, $vendor_dir); } catch (\Psalm\Exception\ConfigCreationException $e) { die($e->getMessage() . \PHP_EOL); } if (!\file_put_contents($current_dir . 'psalm.xml', $template_contents)) { die('Could not write to psalm.xml' . \PHP_EOL); } exit('Config file created successfully. Please re-run psalm.' . \PHP_EOL); } } else { $config = initialiseConfig($path_to_config, $current_dir, $output_format, $first_autoloader); if (isset($options['error-level']) && \is_numeric($options['error-level'])) { $config_level = (int) $options['error-level']; if (!\in_array($config_level, [1, 2, 3, 4, 5, 6, 7, 8], \true)) { throw new \Psalm\Exception\ConfigException('Invalid error level ' . $config_level); } $config->level = $config_level; } } $config->setIncludeCollector($include_collector); if ($config->resolve_from_config_file) { $current_dir = $config->base_dir; \chdir($current_dir); } $in_ci = isset($_SERVER['TRAVIS']) || isset($_SERVER['CIRCLECI']) || isset($_SERVER['APPVEYOR']) || isset($_SERVER['JENKINS_URL']) || isset($_SERVER['SCRUTINIZER']) || isset($_SERVER['GITLAB_CI']) || isset($_SERVER['GITHUB_WORKFLOW']); // disable progressbar on CI if ($in_ci) { $options['long-progress'] = \true; } if (isset($options['threads'])) { $threads = (int) $options['threads']; } elseif (isset($options['debug']) || $in_ci) { $threads = 1; } else { $threads = \max(1, \Psalm\Internal\Analyzer\ProjectAnalyzer::getCpuCount() - 1); } if (!isset($options['threads']) && !isset($options['debug']) && $threads === 1 && \ini_get('pcre.jit') === '1' && \PHP_OS === 'Darwin' && \version_compare(\PHP_VERSION, '7.3.0') >= 0 && \version_compare(\PHP_VERSION, '7.4.0') < 0) { echo 'If you want to run Psalm as a language server, or run Psalm with' . \PHP_EOL . 'multiple processes (--threads=4), beware:' . \PHP_EOL . \Psalm\Internal\Fork\Pool::MAC_PCRE_MESSAGE . \PHP_EOL . \PHP_EOL; } $ini_handler = new \Psalm\Internal\Fork\PsalmRestarter('PSALM'); if (isset($options['disable-extension'])) { if (\is_array($options['disable-extension'])) { /** @psalm-suppress MixedAssignment */ foreach ($options['disable-extension'] as $extension) { if (\is_string($extension)) { $ini_handler->disableExtension($extension); } } } elseif (\is_string($options['disable-extension'])) { $ini_handler->disableExtension($options['disable-extension']); } } if ($threads > 1) { $ini_handler->disableExtension('grpc'); } $ini_handler->disableExtension('uopz'); $type_map_location = null; if (isset($options['generate-json-map']) && \is_string($options['generate-json-map'])) { $type_map_location = $options['generate-json-map']; } $stubs_location = null; if (isset($options['generate-stubs']) && \is_string($options['generate-stubs'])) { $stubs_location = $options['generate-stubs']; } // If Xdebug is enabled, restart without it $ini_handler->check(); if ($config->load_xdebug_stub === null && '' !== $ini_handler->getSkippedVersion()) { $config->load_xdebug_stub = \true; } if (isset($options['debug-emitted-issues'])) { $config->debug_emitted_issues = \true; } \setlocale(\LC_CTYPE, 'C'); if (isset($options['set-baseline'])) { if (\is_array($options['set-baseline'])) { die('Only one baseline file can be created at a time' . \PHP_EOL); } } $paths_to_check = \Psalm\getPathsToCheck(isset($options['f']) ? $options['f'] : null); $plugins = []; if (isset($options['plugin'])) { $plugins = $options['plugin']; if (!\is_array($plugins)) { $plugins = [$plugins]; } } $show_info = isset($options['show-info']) ? $options['show-info'] === 'true' || $options['show-info'] === '1' : \false; $is_diff = !isset($options['no-diff']) && !isset($options['set-baseline']) && !isset($options['update-baseline']); /** @var false|'always'|'auto' $find_unused_code */ $find_unused_code = \false; if (isset($options['find-dead-code'])) { $options['find-unused-code'] = $options['find-dead-code']; } if (isset($options['find-unused-code'])) { if ($options['find-unused-code'] === 'always') { $find_unused_code = 'always'; } else { $find_unused_code = 'auto'; } } $find_unused_variables = isset($options['find-unused-variables']); $find_references_to = isset($options['find-references-to']) && \is_string($options['find-references-to']) ? $options['find-references-to'] : null; if (isset($options['shepherd'])) { if (\is_string($options['shepherd'])) { $config->shepherd_host = $options['shepherd']; } $shepherd_plugin = __DIR__ . '/Psalm/Plugin/Shepherd.php'; if (!\file_exists($shepherd_plugin)) { die('Could not find Shepherd plugin location ' . $shepherd_plugin . \PHP_EOL); } $plugins[] = $shepherd_plugin; } if (isset($options['clear-cache'])) { $cache_directory = $config->getCacheDirectory(); if ($cache_directory !== null) { \Psalm\Config::removeCacheDirectory($cache_directory); } echo 'Cache directory deleted' . \PHP_EOL; exit; } if (isset($options['clear-global-cache'])) { $cache_directory = $config->getGlobalCacheDirectory(); if ($cache_directory) { \Psalm\Config::removeCacheDirectory($cache_directory); echo 'Global cache directory deleted' . \PHP_EOL; } exit; } $debug = \array_key_exists('debug', $options) || \array_key_exists('debug-by-line', $options); if ($debug) { $progress = new \Psalm\Progress\DebugProgress(); } elseif (isset($options['no-progress'])) { $progress = new \Psalm\Progress\VoidProgress(); } else { $show_errors = !$config->error_baseline || isset($options['ignore-baseline']); if (isset($options['long-progress'])) { $progress = new \Psalm\Progress\LongProgress($show_errors, $show_info); } else { $progress = new \Psalm\Progress\DefaultProgress($show_errors, $show_info); } } if (isset($options['no-cache']) || isset($options['i'])) { $providers = new \Psalm\Internal\Provider\Providers(new \Psalm\Internal\Provider\FileProvider()); } else { $no_reflection_cache = isset($options['no-reflection-cache']); $no_file_cache = isset($options['no-file-cache']); $file_storage_cache_provider = $no_reflection_cache ? null : new \Psalm\Internal\Provider\FileStorageCacheProvider($config); $classlike_storage_cache_provider = $no_reflection_cache ? null : new \Psalm\Internal\Provider\ClassLikeStorageCacheProvider($config); $providers = new \Psalm\Internal\Provider\Providers(new \Psalm\Internal\Provider\FileProvider(), new \Psalm\Internal\Provider\ParserCacheProvider($config, !$no_file_cache), $file_storage_cache_provider, $classlike_storage_cache_provider, new \Psalm\Internal\Provider\FileReferenceCacheProvider($config), new \Psalm\Internal\Provider\ProjectCacheProvider(\Psalm\Internal\Composer::getLockFilePath($current_dir))); } $stdout_report_options = new \Psalm\Report\ReportOptions(); $stdout_report_options->use_color = !\array_key_exists('m', $options); $stdout_report_options->show_info = $show_info; $stdout_report_options->show_suggestions = !\array_key_exists('no-suggestions', $options); /** * @psalm-suppress PropertyTypeCoercion */ $stdout_report_options->format = $output_format; $stdout_report_options->show_snippet = !isset($options['show-snippet']) || $options['show-snippet'] !== "false"; $stdout_report_options->pretty = isset($options['pretty-print']) && $options['pretty-print'] !== "false"; /** @var list|string $report_file_paths type guaranteed by argument to getopt() */ $report_file_paths = $options['report'] ?? []; if (\is_string($report_file_paths)) { $report_file_paths = [$report_file_paths]; } $project_analyzer = new \Psalm\Internal\Analyzer\ProjectAnalyzer($config, $providers, $stdout_report_options, \Psalm\Internal\Analyzer\ProjectAnalyzer::getFileReportOptions($report_file_paths, isset($options['report-show-info']) ? $options['report-show-info'] !== 'false' && $options['report-show-info'] !== '0' : \true), $threads, $progress); if (!isset($options['php-version'])) { $options['php-version'] = $config->getPhpVersion(); } if (isset($options['php-version'])) { if (!\is_string($options['php-version'])) { die('Expecting a version number in the format x.y' . \PHP_EOL); } $project_analyzer->setPhpVersion($options['php-version']); } if ($type_map_location) { $project_analyzer->getCodebase()->store_node_types = \true; } $start_time = \microtime(\true); if (\array_key_exists('debug-by-line', $options)) { $project_analyzer->debug_lines = \true; } if (\array_key_exists('debug-performance', $options)) { $project_analyzer->debug_performance = \true; } if ($config->find_unused_code) { $find_unused_code = 'auto'; } if ($find_references_to !== null) { $project_analyzer->getCodebase()->collectLocations(); $project_analyzer->show_issues = \false; } if ($find_unused_code) { $project_analyzer->getCodebase()->reportUnusedCode($find_unused_code); } if ($config->find_unused_variables || $find_unused_variables) { $project_analyzer->getCodebase()->reportUnusedVariables(); } if ($config->run_taint_analysis || (isset($options['track-tainted-input']) || isset($options['security-analysis']) || isset($options['taint-analysis']))) { $project_analyzer->trackTaintedInputs(); } if ($config->find_unused_psalm_suppress || isset($options['find-unused-psalm-suppress'])) { $project_analyzer->trackUnusedSuppressions(); } /** @var string $plugin_path */ foreach ($plugins as $plugin_path) { $config->addPluginPath($plugin_path); } if ($paths_to_check === null) { $project_analyzer->check($current_dir, $is_diff); } elseif ($paths_to_check) { $project_analyzer->checkPaths($paths_to_check); } if ($find_references_to) { $project_analyzer->findReferencesTo($find_references_to); } if (isset($options['set-baseline']) && \is_string($options['set-baseline'])) { \fwrite(\STDERR, 'Writing error baseline to file...' . \PHP_EOL); \Psalm\ErrorBaseline::create(new \Psalm\Internal\Provider\FileProvider(), $options['set-baseline'], \Psalm\IssueBuffer::getIssuesData(), $config->include_php_versions_in_error_baseline || isset($options['include-php-versions'])); \fwrite(\STDERR, "Baseline saved to {$options['set-baseline']}."); update_config_file($config, $path_to_config ?? $current_dir, $options['set-baseline']); \fwrite(\STDERR, \PHP_EOL); } $issue_baseline = []; if (isset($options['update-baseline'])) { $baselineFile = \Psalm\Config::getInstance()->error_baseline; if (empty($baselineFile)) { die('Cannot update baseline, because no baseline file is configured.' . \PHP_EOL); } try { $issue_current_baseline = \Psalm\ErrorBaseline::read(new \Psalm\Internal\Provider\FileProvider(), $baselineFile); $total_issues_current_baseline = \Psalm\ErrorBaseline::countTotalIssues($issue_current_baseline); $issue_baseline = \Psalm\ErrorBaseline::update(new \Psalm\Internal\Provider\FileProvider(), $baselineFile, \Psalm\IssueBuffer::getIssuesData(), $config->include_php_versions_in_error_baseline || isset($options['include-php-versions'])); $total_issues_updated_baseline = \Psalm\ErrorBaseline::countTotalIssues($issue_baseline); $total_fixed_issues = $total_issues_current_baseline - $total_issues_updated_baseline; if ($total_fixed_issues > 0) { echo \str_repeat('-', 30) . "\n"; echo $total_fixed_issues . ' errors fixed' . "\n"; } } catch (\Psalm\Exception\ConfigException $exception) { \fwrite(\STDERR, 'Could not update baseline file: ' . $exception->getMessage() . \PHP_EOL); exit(1); } } if (isset($options['use-baseline'])) { if (!\is_string($options['use-baseline'])) { \fwrite(\STDERR, '--use-baseline must be a string' . \PHP_EOL); exit(1); } $baseline_file_path = $options['use-baseline']; } else { $baseline_file_path = \Psalm\Config::getInstance()->error_baseline; } if ($baseline_file_path && !isset($options['ignore-baseline'])) { try { $issue_baseline = \Psalm\ErrorBaseline::read(new \Psalm\Internal\Provider\FileProvider(), $baseline_file_path); } catch (\Psalm\Exception\ConfigException $exception) { \fwrite(\STDERR, 'Error while reading baseline: ' . $exception->getMessage() . \PHP_EOL); exit(1); } } if ($type_map_location) { $file_map = $providers->file_reference_provider->getFileMaps(); $name_file_map = []; $expected_references = []; foreach ($file_map as $file_path => $map) { $file_name = $config->shortenFileName($file_path); foreach ($map[0] as $map_parts) { $expected_references[$map_parts[1]] = \true; } $map[2] = []; $name_file_map[$file_name] = $map; } $reference_dictionary = \Psalm\Internal\Codebase\ReferenceMapGenerator::getReferenceMap($providers->classlike_storage_provider, $expected_references); $type_map_string = \json_encode(['files' => $name_file_map, 'references' => $reference_dictionary]); $providers->file_provider->setContents($type_map_location, $type_map_string); } if ($stubs_location) { $providers->file_provider->setContents($stubs_location, \Psalm\Internal\Stubs\Generator\StubsGenerator::getAll($project_analyzer->getCodebase(), $providers->classlike_storage_provider, $providers->file_storage_provider)); } if (!isset($options['i'])) { \Psalm\IssueBuffer::finish($project_analyzer, !$paths_to_check, $start_time, isset($options['stats']), $issue_baseline); } else { $issues_by_file = \Psalm\IssueBuffer::getIssuesData(); if (!$issues_by_file) { $init_level = 1; } else { $codebase = $project_analyzer->getCodebase(); $mixed_counts = $codebase->analyzer->getTotalTypeCoverage($codebase); $init_level = \Psalm\Config\Creator::getLevel(\array_merge(...\array_values($issues_by_file)), (int) \array_sum($mixed_counts)); } echo "\n" . 'Detected level ' . $init_level . ' as a suitable initial default' . "\n"; try { $template_contents = \Psalm\Config\Creator::getContents($current_dir, $init_source_dir, $init_level, $vendor_dir); } catch (\Psalm\Exception\ConfigCreationException $e) { die($e->getMessage() . \PHP_EOL); } if (!\file_put_contents($current_dir . 'psalm.xml', $template_contents)) { die('Could not write to psalm.xml' . \PHP_EOL); } exit('Config file created successfully. Please re-run psalm.' . \PHP_EOL); } addCommands([new \Psalm\Internal\PluginManager\Command\ShowCommand($plugin_list_factory), new \Psalm\Internal\PluginManager\Command\EnableCommand($plugin_list_factory), new \Psalm\Internal\PluginManager\Command\DisableCommand($plugin_list_factory)]); $app->getDefinition()->addOption(new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption('config', 'c', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED, 'Path to Psalm config file')); $app->setDefaultCommand('show'); $app->run(); runAndCollect(function () use($current_dir, $options, $vendor_dir) : ?\Composer\Autoload\ClassLoader { return \Psalm\requireAutoloaders($current_dir, isset($options['r']), $vendor_dir); }); $ini_handler = new \Psalm\Internal\Fork\PsalmRestarter('PSALM'); $ini_handler->disableExtension('grpc'); // If Xdebug is enabled, restart without it $ini_handler->check(); \setlocale(\LC_CTYPE, 'C'); $path_to_config = \Psalm\get_path_to_config($options); if (isset($options['tcp'])) { if (!\is_string($options['tcp'])) { \fwrite(\STDERR, 'tcp url should be a string' . \PHP_EOL); exit(1); } } $find_unused_code = isset($options['find-dead-code']) ? 'auto' : null; $config = \Psalm\initialiseConfig($path_to_config, $current_dir, \Psalm\Report::TYPE_CONSOLE, $first_autoloader); $config->setIncludeCollector($include_collector); if ($config->resolve_from_config_file) { $current_dir = $config->base_dir; \chdir($current_dir); } $config->setServerMode(); if (isset($options['clear-cache'])) { $cache_directory = $config->getCacheDirectory(); if ($cache_directory !== null) { \Psalm\Config::removeCacheDirectory($cache_directory); } echo 'Cache directory deleted' . \PHP_EOL; exit; } $providers = new \Psalm\Internal\Provider\Providers(new \Psalm\Internal\Provider\FileProvider(), new \Psalm\Internal\Provider\ParserCacheProvider($config), new \Psalm\Internal\Provider\FileStorageCacheProvider($config), new \Psalm\Internal\Provider\ClassLikeStorageCacheProvider($config), new \Psalm\Internal\Provider\FileReferenceCacheProvider($config), new \Psalm\Internal\Provider\ProjectCacheProvider(\Psalm\Internal\Composer::getLockFilePath($current_dir))); $project_analyzer = new \Psalm\Internal\Analyzer\ProjectAnalyzer($config, $providers); if ($config->find_unused_variables) { $project_analyzer->getCodebase()->reportUnusedVariables(); } if ($config->find_unused_code) { $find_unused_code = 'auto'; } if (isset($options['disable-on-change'])) { $project_analyzer->onchange_line_limit = (int) $options['disable-on-change']; } $project_analyzer->provide_completion = !isset($options['enable-autocomplete']) || !\is_string($options['enable-autocomplete']) || \strtolower($options['enable-autocomplete']) !== 'false'; $config->visitComposerAutoloadFiles($project_analyzer); if ($find_unused_code) { $project_analyzer->getCodebase()->reportUnusedCode($find_unused_code); } if (isset($options['use-extended-diagnostic-codes'])) { $project_analyzer->language_server_use_extended_diagnostic_codes = \true; } if (isset($options['verbose'])) { $project_analyzer->language_server_verbose = \true; } $project_analyzer->server($options['tcp'] ?? null, isset($options['tcp-server']) ? \true : \false); isUserDefined()) { /** * See https://github.com/runkit7/runkit_object_id for a faster native version for php <= 7.1 * * @param object $object * @return int The object id */ function spl_object_id($object) : int { return runkit_object_id($object); } } elseif (PHP_INT_SIZE === 8) { /** * See https://github.com/runkit7/runkit_object_id for a faster native version for php <= 7.1 * * @param object $object * @return int (The object id, XORed with a random number) */ function spl_object_id($object) : int { $hash = spl_object_hash($object); // Fit this into a php long (32-bit or 64-bit signed int). // The first 16 hex digits (64 bytes) vary, the last 16 don't. // Values are usually padded with 0s at the front. return intval(substr($hash, 1, 15), 16); } } else { /** * See https://github.com/runkit7/runkit_object_id for a faster native version for php <= 7.1 * * @param object $object * @return int (The object id, XORed with a random number) */ function spl_object_id($object) : int { $hash = spl_object_hash($object); // Fit this into a php long (32-bit or 64-bit signed int). // The first 16 hex digits (64 bytes) vary, the last 16 don't. // Values are usually padded with 0s at the front. return intval(substr($hash, 9, 7), 16); } } } */ function getArguments() : array { global $argv; if (!$argv) { return []; } $filtered_input_paths = []; for ($i = 0, $iMax = \count($argv); $i < $iMax; ++$i) { $input_path = $argv[$i]; if (\realpath($input_path) !== \false) { continue; } if ($input_path[0] === '-' && \strlen($input_path) === 2) { if ($input_path[1] === 'c' || $input_path[1] === 'f') { ++$i; } continue; } if ($input_path[0] === '-' && $input_path[2] === '=') { continue; } $filtered_input_paths[] = $input_path; } return $filtered_input_paths; } /** * @param string|array|null|false $f_paths * * @return list|null */ function getPathsToCheck($f_paths) : ?array { global $argv; $paths_to_check = []; if ($f_paths) { $input_paths = \is_array($f_paths) ? $f_paths : [$f_paths]; } else { $input_paths = $argv ? $argv : null; } if ($input_paths) { $filtered_input_paths = []; for ($i = 0, $iMax = \count($input_paths); $i < $iMax; ++$i) { /** @var string */ $input_path = $input_paths[$i]; if (\realpath($input_path) === \realpath(\dirname(__DIR__) . \DIRECTORY_SEPARATOR . 'psalm') || \realpath($input_path) === \realpath(\dirname(__DIR__) . \DIRECTORY_SEPARATOR . 'psalter') || \realpath($input_path) === \realpath(\Phar::running(\false))) { continue; } if ($input_path[0] === '-' && \strlen($input_path) === 2) { if ($input_path[1] === 'c' || $input_path[1] === 'f') { ++$i; } continue; } if ($input_path[0] === '-' && $input_path[2] === '=') { continue; } if (\substr($input_path, 0, 2) === '--' && \strlen($input_path) > 2) { continue; } $filtered_input_paths[] = $input_path; } if ($filtered_input_paths === ['-']) { $meta = \stream_get_meta_data(\STDIN); \stream_set_blocking(\STDIN, \false); if ($stdin = \fgets(\STDIN)) { $filtered_input_paths = \preg_split('/\\s+/', \trim($stdin)); } $blocked = $meta['blocked']; \stream_set_blocking(\STDIN, $blocked); } foreach ($filtered_input_paths as $path_to_check) { if ($path_to_check[0] === '-') { \fwrite(\STDERR, 'Invalid usage, expecting psalm [options] [file...]' . \PHP_EOL); exit(1); } if (!\file_exists($path_to_check)) { \fwrite(\STDERR, 'Cannot locate ' . $path_to_check . \PHP_EOL); exit(1); } $path_to_check = \realpath($path_to_check); if (!$path_to_check) { \fwrite(\STDERR, 'Error getting realpath for file' . \PHP_EOL); exit(1); } $paths_to_check[] = $path_to_check; } if (!$paths_to_check) { $paths_to_check = null; } } return $paths_to_check; } /** * @psalm-pure */ function getPsalmHelpText() : string { return <<getMessage() . \PHP_EOL); exit(1); } $config->setComposerClassLoader($first_autoloader); return $config; } function update_config_file(\Psalm\Config $config, string $config_file_path, string $baseline_path) : void { if ($config->error_baseline === $baseline_path) { return; } $configFile = $config_file_path; if (\is_dir($config_file_path)) { $configFile = \Psalm\Config::locateConfigFile($config_file_path); } if (!$configFile) { \fwrite(\STDERR, "Don't forget to set errorBaseline=\"{$baseline_path}\" to your config."); return; } $configFileContents = \file_get_contents($configFile); if ($config->error_baseline) { $amendedConfigFileContents = \preg_replace('/errorBaseline=".*?"/', "errorBaseline=\"{$baseline_path}\"", $configFileContents); } else { $endPsalmOpenTag = \strpos($configFileContents, '>', (int) \strpos($configFileContents, '", $endPsalmOpenTag, 1); } else { $amendedConfigFileContents = \substr_replace($configFileContents, " errorBaseline=\"{$baseline_path}\">", $endPsalmOpenTag, 1); } } \file_put_contents($configFile, $amendedConfigFileContents); } function get_path_to_config(array $options) : ?string { $path_to_config = isset($options['c']) && \is_string($options['c']) ? \realpath($options['c']) : null; if ($path_to_config === \false) { \fwrite(\STDERR, 'Could not resolve path to config ' . (string) ($options['c'] ?? '') . \PHP_EOL); exit(1); } return $path_to_config; } /** * @psalm-pure */ function getMemoryLimitInBytes() : int { $limit = \ini_get('memory_limit'); // for unlimited = -1 if ($limit < 0) { return -1; } if (\preg_match('/^(\\d+)(\\D?)$/', $limit, $matches)) { $limit = (int) $matches[1]; switch (\strtoupper($matches[2] ?? '')) { case 'G': $limit *= 1024 * 1024 * 1024; break; case 'M': $limit *= 1024 * 1024; break; case 'K': $limit *= 1024; break; } } return (int) $limit; } */ public $vars_in_scope = []; /** * @var array */ public $vars_possibly_in_scope = []; /** * Whether or not we're inside the conditional of an if/where etc. * * This changes whether or not the context is cloned * * @var bool */ public $inside_conditional = \false; /** * Whether or not we're inside a __construct function * * @var bool */ public $inside_constructor = \false; /** * Whether or not we're inside an isset call * * Inside issets Psalm is more lenient about certain things * * @var bool */ public $inside_isset = \false; /** * Whether or not we're inside an unset call, where * we don't care about possibly undefined variables * * @var bool */ public $inside_unset = \false; /** * Whether or not we're inside an class_exists call, where * we don't care about possibly undefined classes * * @var bool */ public $inside_class_exists = \false; /** * Whether or not we're inside a function/method call * * @var bool */ public $inside_call = \false; /** * Whether or not we're inside any other situation that treats a variable as used * * @var bool */ public $inside_use = \false; /** * Whether or not we're inside a throw * * @var bool */ public $inside_throw = \false; /** * Whether or not we're inside an assignment * * @var bool */ public $inside_assignment = \false; /** * @var null|CodeLocation */ public $include_location = null; /** * @var string|null */ public $self; /** * @var string|null */ public $parent; /** * @var bool */ public $check_classes = \true; /** * @var bool */ public $check_variables = \true; /** * @var bool */ public $check_methods = \true; /** * @var bool */ public $check_consts = \true; /** * @var bool */ public $check_functions = \true; /** * A list of classes checked with class_exists * * @var array */ public $phantom_classes = []; /** * A list of files checked with file_exists * * @var array */ public $phantom_files = []; /** * A list of clauses in Conjunctive Normal Form * * @var list */ public $clauses = []; /** * A list of hashed clauses that have already been factored in * * @var list */ public $reconciled_expression_clauses = []; /** * Whether or not to do a deep analysis and collect mutations to this context * * @var bool */ public $collect_mutations = \false; /** * Whether or not to do a deep analysis and collect initializations from private or final methods * * @var bool */ public $collect_initializations = \false; /** * Whether or not to do a deep analysis and collect initializations from public non-final methods * * @var bool */ public $collect_nonprivate_initializations = \false; /** * Stored to prevent re-analysing methods when checking for initialised properties * * @var array|null */ public $initialized_methods = null; /** * @var array */ public $constants = []; /** * Whether or not to track exceptions * * @var bool */ public $collect_exceptions = \false; /** * A list of variables that have been referenced * * @var array */ public $referenced_var_ids = []; /** * A list of variables that have been passed by reference (where we know their type) * * @var array */ public $byref_constraints = []; /** * If this context inherits from a context, it is here * * @var Context|null */ public $parent_context; /** * @var array */ public $possible_param_types = []; /** * A list of vars that have been assigned to * * @var array */ public $assigned_var_ids = []; /** * A list of vars that have been may have been assigned to * * @var array */ public $possibly_assigned_var_ids = []; /** * A list of classes or interfaces that may have been thrown * * @var array> */ public $possibly_thrown_exceptions = []; /** * @var bool */ public $is_global = \false; /** * @var array */ public $protected_var_ids = []; /** * If we've branched from the main scope, a byte offset for where that branch happened * * @var int|null */ public $branch_point; /** * What does break mean in this context? * * 'loop' means we're breaking out of a loop, * 'switch' means we're breaking out of a switch * * @var list<'loop'|'switch'> */ public $break_types = []; /** * @var bool */ public $inside_loop = \false; /** * @var Internal\Scope\LoopScope|null */ public $loop_scope = null; /** * @var Internal\Scope\CaseScope|null */ public $case_scope = null; /** * @var Internal\Scope\FinallyScope|null */ public $finally_scope = null; /** * @var Context|null */ public $if_context = null; /** * @var \Psalm\Internal\Scope\IfScope|null */ public $if_scope = null; /** * @var bool */ public $strict_types = \false; /** * @var string|null */ public $calling_function_id; /** * @var lowercase-string|null */ public $calling_method_id; /** * @var bool */ public $inside_negation = \false; /** * @var bool */ public $ignore_variable_property = \false; /** * @var bool */ public $ignore_variable_method = \false; /** * @var bool */ public $pure = \false; /** * @var bool */ public $mutation_free = \false; /** * @var bool */ public $external_mutation_free = \false; /** * @var bool */ public $error_suppressing = \false; /** * @var bool */ public $has_returned = \false; public function __construct(?string $self = null) { $this->self = $self; } public function __destruct() { $this->case_scope = null; $this->parent_context = null; } public function __clone() { foreach ($this->clauses as &$clause) { $clause = clone $clause; } foreach ($this->constants as &$constant) { $constant = clone $constant; } } /** * Updates the parent context, looking at the changes within a block and then applying those changes, where * necessary, to the parent context * * @param bool $has_leaving_statements whether or not the parent scope is abandoned between * $start_context and $end_context * @param array $updated_vars * */ public function update(\Psalm\Context $start_context, \Psalm\Context $end_context, bool $has_leaving_statements, array $vars_to_update, array &$updated_vars) : void { foreach ($start_context->vars_in_scope as $var_id => $old_type) { // this is only true if there was some sort of type negation if (\in_array($var_id, $vars_to_update, \true)) { // if we're leaving, we're effectively deleting the possibility of the if types $new_type = !$has_leaving_statements && $end_context->hasVariable($var_id) ? $end_context->vars_in_scope[$var_id] : null; $existing_type = isset($this->vars_in_scope[$var_id]) ? $this->vars_in_scope[$var_id] : null; if (!$existing_type) { if ($new_type) { $this->vars_in_scope[$var_id] = clone $new_type; $updated_vars[$var_id] = \true; } continue; } $existing_type = clone $existing_type; // if the type changed within the block of statements, process the replacement // also never allow ourselves to remove all types from a union if ((!$new_type || !$old_type->equals($new_type)) && ($new_type || \count($existing_type->getAtomicTypes()) > 1)) { $existing_type->substitute($old_type, $new_type); if ($new_type && $new_type->from_docblock) { $existing_type->setFromDocblock(); } $updated_vars[$var_id] = \true; } $this->vars_in_scope[$var_id] = $existing_type; } } } /** * @param array $new_vars_in_scope * * @return array */ public function getRedefinedVars(array $new_vars_in_scope, bool $include_new_vars = \false) : array { $redefined_vars = []; foreach ($this->vars_in_scope as $var_id => $this_type) { if (!isset($new_vars_in_scope[$var_id])) { if ($include_new_vars) { $redefined_vars[$var_id] = $this_type; } continue; } $new_type = $new_vars_in_scope[$var_id]; if (!$this_type->isEmpty() && !$new_type->isEmpty() && !$this_type->equals($new_type)) { $redefined_vars[$var_id] = $this_type; } } return $redefined_vars; } /** * @return list */ public static function getNewOrUpdatedVarIds(\Psalm\Context $original_context, \Psalm\Context $new_context) : array { $redefined_var_ids = []; foreach ($new_context->vars_in_scope as $var_id => $context_type) { if (!isset($original_context->vars_in_scope[$var_id]) || !$original_context->vars_in_scope[$var_id]->equals($context_type)) { $redefined_var_ids[] = $var_id; } } return $redefined_var_ids; } public function remove(string $remove_var_id) : void { unset($this->referenced_var_ids[$remove_var_id], $this->vars_possibly_in_scope[$remove_var_id]); if (isset($this->vars_in_scope[$remove_var_id])) { $existing_type = $this->vars_in_scope[$remove_var_id]; unset($this->vars_in_scope[$remove_var_id]); $this->removeDescendents($remove_var_id, $existing_type); } } /** * @param Clause[] $clauses * @param array $changed_var_ids * * @return array{0: list, list} * * @psalm-pure */ public static function removeReconciledClauses(array $clauses, array $changed_var_ids) : array { $included_clauses = []; $rejected_clauses = []; foreach ($clauses as $c) { if ($c->wedge) { $included_clauses[] = $c; continue; } foreach ($c->possibilities as $key => $_) { if (isset($changed_var_ids[$key])) { $rejected_clauses[] = $c; continue 2; } } $included_clauses[] = $c; } return [$included_clauses, $rejected_clauses]; } /** * @param Clause[] $clauses * * @return list */ public static function filterClauses(string $remove_var_id, array $clauses, ?\Psalm\Type\Union $new_type = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null) : array { $new_type_string = $new_type ? $new_type->getId() : ''; $clauses_to_keep = []; foreach ($clauses as $clause) { $clause = $clause->calculateNegation(); $quoted_remove_var_id = \preg_quote($remove_var_id, '/'); foreach ($clause->possibilities as $var_id => $_) { if (\preg_match('/' . $quoted_remove_var_id . '[\\]\\[\\-]/', $var_id)) { break 2; } } if (!isset($clause->possibilities[$remove_var_id]) || $clause->possibilities[$remove_var_id] === [$new_type_string]) { $clauses_to_keep[] = $clause; } elseif ($statements_analyzer && $new_type && !$new_type->hasMixed()) { $type_changed = \false; // if the clause contains any possibilities that would be altered // by the new type foreach ($clause->possibilities[$remove_var_id] as $type) { // if we're negating a type, we generally don't need the clause anymore if ($type[0] === '!' && $type !== '!falsy' && $type !== '!empty') { $type_changed = \true; break; } // empty and !empty are not definitive for arrays and scalar types if (($type === '!falsy' || $type === 'falsy') && ($new_type->hasArray() || $new_type->hasPossiblyNumericType())) { $type_changed = \true; break; } $result_type = \Psalm\Internal\Type\AssertionReconciler::reconcile($type, clone $new_type, null, $statements_analyzer, \false, [], null, [], $failed_reconciliation); if ($result_type->getId() !== $new_type_string) { $type_changed = \true; break; } } if (!$type_changed) { $clauses_to_keep[] = $clause; } } } return $clauses_to_keep; } public function removeVarFromConflictingClauses(string $remove_var_id, ?\Psalm\Type\Union $new_type = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null) : void { $this->clauses = self::filterClauses($remove_var_id, $this->clauses, $new_type, $statements_analyzer); if ($this->parent_context) { $this->parent_context->removeVarFromConflictingClauses($remove_var_id); } } public function removeDescendents(string $remove_var_id, ?\Psalm\Type\Union $existing_type = null, ?\Psalm\Type\Union $new_type = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null) : void { if (!$existing_type && isset($this->vars_in_scope[$remove_var_id])) { $existing_type = $this->vars_in_scope[$remove_var_id]; } if (!$existing_type) { return; } $this->removeVarFromConflictingClauses($remove_var_id, $existing_type->hasMixed() || $new_type && $existing_type->from_docblock !== $new_type->from_docblock ? null : $new_type, $statements_analyzer); foreach ($this->vars_in_scope as $var_id => $_) { if (\preg_match('/' . \preg_quote($remove_var_id, '/') . '[\\]\\[\\-]/', $var_id)) { unset($this->vars_in_scope[$var_id]); } } } public function removeAllObjectVars() : void { $vars_to_remove = []; foreach ($this->vars_in_scope as $var_id => $_) { if (\strpos($var_id, '->') !== \false || \strpos($var_id, '::') !== \false) { $vars_to_remove[] = $var_id; } } if (!$vars_to_remove) { return; } foreach ($vars_to_remove as $var_id) { unset($this->vars_in_scope[$var_id], $this->vars_possibly_in_scope[$var_id]); } $clauses_to_keep = []; foreach ($this->clauses as $clause) { $abandon_clause = \false; foreach (\array_keys($clause->possibilities) as $key) { if (\strpos($key, '->') !== \false || \strpos($key, '::') !== \false) { $abandon_clause = \true; break; } } if (!$abandon_clause) { $clauses_to_keep[] = $clause; } } $this->clauses = $clauses_to_keep; } public function updateChecks(\Psalm\Context $op_context) : void { $this->check_classes = $this->check_classes && $op_context->check_classes; $this->check_variables = $this->check_variables && $op_context->check_variables; $this->check_methods = $this->check_methods && $op_context->check_methods; $this->check_functions = $this->check_functions && $op_context->check_functions; $this->check_consts = $this->check_consts && $op_context->check_consts; } public function isPhantomClass(string $class_name) : bool { return isset($this->phantom_classes[\strtolower($class_name)]); } public function hasVariable(?string $var_name) : bool { if (!$var_name) { return \false; } $stripped_var = \preg_replace('/(->|\\[).*$/', '', $var_name); if ($stripped_var !== '$this' || $var_name !== $stripped_var) { $this->referenced_var_ids[$var_name] = \true; if (!isset($this->vars_possibly_in_scope[$var_name]) && !isset($this->vars_in_scope[$var_name])) { return \false; } } return isset($this->vars_in_scope[$var_name]); } public function getScopeSummary() : string { $summary = []; foreach ($this->vars_possibly_in_scope as $k => $_) { $summary[$k] = \true; } foreach ($this->vars_in_scope as $k => $v) { $summary[$k] = $v->getId(); } return \json_encode($summary); } public function defineGlobals() : void { $globals = ['$argv' => new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), \Psalm\Type::getString()])]), '$argc' => \Psalm\Type::getInt()]; $config = \Psalm\Config::getInstance(); foreach ($config->globals as $global_id => $type_string) { $globals[$global_id] = \Psalm\Type::parseString($type_string); } foreach ($globals as $global_id => $type) { $this->vars_in_scope[$global_id] = $type; $this->vars_possibly_in_scope[$global_id] = \true; } } public function mergeExceptions(\Psalm\Context $other_context) : void { foreach ($other_context->possibly_thrown_exceptions as $possibly_thrown_exception => $codelocations) { foreach ($codelocations as $hash => $codelocation) { $this->possibly_thrown_exceptions[$possibly_thrown_exception][$hash] = $codelocation; } } } public function isSuppressingExceptions(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer) : bool { if (!$this->collect_exceptions) { return \true; } $issue_type = $this->is_global ? 'UncaughtThrowInGlobalScope' : 'MissingThrowsDocblock'; $suppressed_issues = $statements_analyzer->getSuppressedIssues(); $suppressed_issue_position = \array_search($issue_type, $suppressed_issues, \true); if ($suppressed_issue_position !== \false) { if (\is_int($suppressed_issue_position)) { $file = $statements_analyzer->getFileAnalyzer()->getFilePath(); \Psalm\IssueBuffer::addUsedSuppressions([$file => [$suppressed_issue_position => \true]]); } return \true; } return \false; } public function mergeFunctionExceptions(\Psalm\Storage\FunctionLikeStorage $function_storage, \Psalm\CodeLocation $codelocation) : void { $hash = $codelocation->getHash(); foreach ($function_storage->throws as $possibly_thrown_exception => $_) { $this->possibly_thrown_exceptions[$possibly_thrown_exception][$hash] = $codelocation; } } } > */ protected static $issues_data = []; /** * @var array */ protected static $console_issues = []; /** * @var array */ protected static $fixable_issue_counts = []; /** * @var int */ protected static $error_count = 0; /** * @var array */ protected static $emitted = []; /** @var int */ protected static $recording_level = 0; /** @var array> */ protected static $recorded_issues = []; /** * @var array> */ protected static $unused_suppressions = []; /** * @var array> */ protected static $used_suppressions = []; /** * @param string[] $suppressed_issues * */ public static function accepts(\Psalm\Issue\CodeIssue $e, array $suppressed_issues = [], bool $is_fixable = \false) : bool { if (self::isSuppressed($e, $suppressed_issues)) { return \false; } return self::add($e, $is_fixable); } public static function addUnusedSuppression(string $file_path, int $offset, string $issue_type) : void { if ($issue_type === 'TaintedInput') { return; } if (isset(self::$used_suppressions[$file_path][$offset])) { return; } if (!isset(self::$unused_suppressions[$file_path])) { self::$unused_suppressions[$file_path] = []; } self::$unused_suppressions[$file_path][$offset] = $offset + \strlen($issue_type) - 1; } /** * @param string[] $suppressed_issues * */ public static function isSuppressed(\Psalm\Issue\CodeIssue $e, array $suppressed_issues = []) : bool { $config = \Psalm\Config::getInstance(); $fqcn_parts = \explode('\\', \get_class($e)); $issue_type = \array_pop($fqcn_parts); $file_path = $e->getFilePath(); if (!$config->reportIssueInFile($issue_type, $file_path)) { return \true; } $suppressed_issue_position = \array_search($issue_type, $suppressed_issues); if ($suppressed_issue_position !== \false) { if (\is_int($suppressed_issue_position)) { self::$used_suppressions[$file_path][$suppressed_issue_position] = \true; } return \true; } $parent_issue_type = \Psalm\Config::getParentIssueType($issue_type); if ($parent_issue_type) { $suppressed_issue_position = \array_search($parent_issue_type, $suppressed_issues); if ($suppressed_issue_position !== \false) { if (\is_int($suppressed_issue_position)) { self::$used_suppressions[$file_path][$suppressed_issue_position] = \true; } return \true; } } $suppress_all_position = \array_search('all', $suppressed_issues); if ($suppress_all_position !== \false) { if (\is_int($suppress_all_position)) { self::$used_suppressions[$file_path][$suppress_all_position] = \true; } return \true; } $reporting_level = $config->getReportingLevelForIssue($e); if ($reporting_level === \Psalm\Config::REPORT_SUPPRESS) { return \true; } if ($e->code_location->getLineNumber() === -1) { return \true; } if (self::$recording_level > 0) { self::$recorded_issues[self::$recording_level][] = $e; return \true; } return \false; } /** * @throws Exception\CodeException */ public static function add(\Psalm\Issue\CodeIssue $e, bool $is_fixable = \false) : bool { $config = \Psalm\Config::getInstance(); $fqcn_parts = \explode('\\', \get_class($e)); $issue_type = \array_pop($fqcn_parts); $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); if (!$project_analyzer->show_issues) { return \false; } if ($project_analyzer->getCodebase()->taint_flow_graph && $issue_type !== 'TaintedInput') { return \false; } $reporting_level = $config->getReportingLevelForIssue($e); if ($reporting_level === \Psalm\Config::REPORT_SUPPRESS) { return \false; } if ($config->debug_emitted_issues) { \ob_start(); \debug_print_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); $trace = \ob_get_clean(); \fwrite(\STDERR, "\nEmitting {$e->getShortLocation()} {$issue_type} {$e->message}\n{$trace}\n"); } $emitted_key = $issue_type . '-' . $e->getShortLocation() . ':' . $e->code_location->getColumn() . ' ' . $e->dupe_key; if ($reporting_level === \Psalm\Config::REPORT_INFO) { if ($issue_type === 'TaintedInput' || !self::alreadyEmitted($emitted_key)) { self::$issues_data[$e->getFilePath()][] = $e->toIssueData(\Psalm\Config::REPORT_INFO); if ($is_fixable) { self::addFixableIssue($issue_type); } } return \false; } if ($config->throw_exception) { \Psalm\Internal\Analyzer\FileAnalyzer::clearCache(); $message = $e instanceof \Psalm\Issue\TaintedInput ? $e->getJourneyMessage() : $e->message; throw new \Psalm\Exception\CodeException($issue_type . ' - ' . $e->getShortLocationWithPrevious() . ':' . $e->code_location->getColumn() . ' - ' . $message); } if ($issue_type === 'TaintedInput' || !self::alreadyEmitted($emitted_key)) { ++self::$error_count; self::$issues_data[$e->getFilePath()][] = $e->toIssueData(\Psalm\Config::REPORT_ERROR); if ($is_fixable) { self::addFixableIssue($issue_type); } } return \true; } public static function remove(string $file_path, string $issue_type, int $file_offset) : void { if (!isset(self::$issues_data[$file_path])) { return; } $filtered_issues = []; foreach (self::$issues_data[$file_path] as $issue) { if ($issue->type !== $issue_type || $issue->from !== $file_offset) { $filtered_issues[] = $issue; } } if (empty($filtered_issues)) { unset(self::$issues_data[$file_path]); } else { self::$issues_data[$file_path] = $filtered_issues; } } public static function addFixableIssue(string $issue_type) : void { if (isset(self::$fixable_issue_counts[$issue_type])) { self::$fixable_issue_counts[$issue_type]++; } else { self::$fixable_issue_counts[$issue_type] = 1; } } /** * @return array> */ public static function getIssuesData() : array { return self::$issues_data; } /** * @return list */ public static function getIssuesDataForFile(string $file_path) : array { return self::$issues_data[$file_path] ?? []; } /** * @return array */ public static function getFixableIssues() : array { return self::$fixable_issue_counts; } /** * @param array $fixable_issue_counts */ public static function addFixableIssues(array $fixable_issue_counts) : void { foreach ($fixable_issue_counts as $issue_type => $count) { if (isset(self::$fixable_issue_counts[$issue_type])) { self::$fixable_issue_counts[$issue_type] += $count; } else { self::$fixable_issue_counts[$issue_type] = $count; } } } /** * @return array> */ public static function getUnusedSuppressions() : array { return self::$unused_suppressions; } /** * @return array> */ public static function getUsedSuppressions() : array { return self::$used_suppressions; } /** * @param array> $unused_suppressions */ public static function addUnusedSuppressions(array $unused_suppressions) : void { self::$unused_suppressions += $unused_suppressions; } /** * @param array> $used_suppressions */ public static function addUsedSuppressions(array $used_suppressions) : void { foreach ($used_suppressions as $file => $offsets) { if (!isset(self::$used_suppressions[$file])) { self::$used_suppressions[$file] = $offsets; } else { self::$used_suppressions[$file] += $offsets; } } } public static function processUnusedSuppressions(\Psalm\Internal\Provider\FileProvider $file_provider) : void { $config = \Psalm\Config::getInstance(); foreach (self::$unused_suppressions as $file_path => $offsets) { if (!$offsets) { continue; } $file_contents = $file_provider->getContents($file_path); foreach ($offsets as $start => $end) { if (isset(self::$used_suppressions[$file_path][$start])) { continue; } self::add(new \Psalm\Issue\UnusedPsalmSuppress('This suppression is never used', new \Psalm\CodeLocation\Raw($file_contents, $file_path, $config->shortenFileName($file_path), $start, $end))); } } } public static function getErrorCount() : int { return self::$error_count; } /** * @param array> $issues_data * */ public static function addIssues(array $issues_data) : void { foreach ($issues_data as $file_path => $file_issues) { foreach ($file_issues as $issue) { $emitted_key = $issue->type . '-' . $issue->file_name . ':' . $issue->line_from . ':' . $issue->column_from . ' ' . $issue->dupe_key; if (!self::alreadyEmitted($emitted_key)) { self::$issues_data[$file_path][] = $issue; } } } } /** * @param array}>> $issue_baseline * */ public static function finish(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, bool $is_full, float $start_time, bool $add_stats = \false, array $issue_baseline = []) : void { if (!$project_analyzer->stdout_report_options) { throw new \UnexpectedValueException('Cannot finish without stdout report options'); } $codebase = $project_analyzer->getCodebase(); $error_count = 0; $info_count = 0; $issues_data = []; if (self::$issues_data) { if (\in_array($project_analyzer->stdout_report_options->format, [\Psalm\Report::TYPE_CONSOLE, \Psalm\Report::TYPE_PHP_STORM])) { echo "\n"; } \ksort(self::$issues_data); foreach (self::$issues_data as $file_path => $file_issues) { \usort($file_issues, function (\Psalm\Internal\Analyzer\IssueData $d1, \Psalm\Internal\Analyzer\IssueData $d2) : int { if ($d1->file_path === $d2->file_path) { if ($d1->line_from === $d2->line_from) { if ($d1->column_from === $d2->column_from) { return 0; } return $d1->column_from > $d2->column_from ? 1 : -1; } return $d1->line_from > $d2->line_from ? 1 : -1; } return $d1->file_path > $d2->file_path ? 1 : -1; }); self::$issues_data[$file_path] = $file_issues; } // 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 (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($issue_data->selected_text, $issue_baseline[$file][$type]['s'], \true); if ($position !== \false) { $issue_data->severity = \Psalm\Config::REPORT_INFO; \array_splice($issue_baseline[$file][$type]['s'], $position, 1); $issue_baseline[$file][$type]['o'] = $issue_baseline[$file][$type]['o'] - 1; } } else { $issue_baseline[$file][$type]['s'] = []; $issue_data->severity = \Psalm\Config::REPORT_INFO; $issue_baseline[$file][$type]['o'] = $issue_baseline[$file][$type]['o'] - 1; } } /** @psalm-suppress PropertyTypeCoercion due to Psalm bug */ $issues_data[$file_path][$key] = $issue_data; } } } } echo self::getOutput($issues_data, $project_analyzer->stdout_report_options, $codebase->analyzer->getTotalTypeCoverage($codebase)); foreach ($issues_data as $file_issues) { foreach ($file_issues as $issue_data) { if ($issue_data->severity === \Psalm\Config::REPORT_ERROR) { ++$error_count; } else { ++$info_count; } } } $after_analysis_hooks = $codebase->config->after_analysis; if ($after_analysis_hooks) { $source_control_info = null; $build_info = (new \Psalm\Internal\ExecutionEnvironment\BuildInfoCollector($_SERVER))->collect(); try { $source_control_info = (new \Psalm\Internal\ExecutionEnvironment\GitInfoCollector())->collect(); } catch (\RuntimeException $e) { // do nothing } foreach ($after_analysis_hooks as $after_analysis_hook) { /** @psalm-suppress ArgumentTypeCoercion due to Psalm bug */ $after_analysis_hook::afterAnalysis($codebase, $issues_data, $build_info, $source_control_info); } } foreach ($project_analyzer->generated_report_options as $report_options) { if (!$report_options->output_path) { throw new \UnexpectedValueException('Output path should not be null here'); } $folder = \dirname($report_options->output_path); if (!\is_dir($folder) && !\mkdir($folder, 0777, \true) && !\is_dir($folder)) { throw new \RuntimeException(\sprintf('Directory "%s" was not created', $folder)); } \file_put_contents($report_options->output_path, self::getOutput($issues_data, $report_options, $codebase->analyzer->getTotalTypeCoverage($codebase))); } if (\in_array($project_analyzer->stdout_report_options->format, [\Psalm\Report::TYPE_CONSOLE, \Psalm\Report::TYPE_PHP_STORM])) { echo \str_repeat('-', 30) . "\n"; if ($error_count) { echo ($project_analyzer->stdout_report_options->use_color ? "\33[0;31m" . $error_count . " errors\33[0m" : $error_count . ' errors') . ' found' . "\n"; } else { echo 'No errors found!' . "\n"; } $show_info = $project_analyzer->stdout_report_options->show_info; $show_suggestions = $project_analyzer->stdout_report_options->show_suggestions; if ($info_count && ($show_info || $show_suggestions)) { echo \str_repeat('-', 30) . "\n"; echo $info_count . ' other issues found.' . "\n"; if (!$show_info) { echo 'You can display them with ' . ($project_analyzer->stdout_report_options->use_color ? "\33[30;48;5;195m--show-info=true\33[0m" : '--show-info=true') . "\n"; } } if (self::$fixable_issue_counts && $show_suggestions && !$codebase->taint_flow_graph) { echo \str_repeat('-', 30) . "\n"; $total_count = \array_sum(self::$fixable_issue_counts); $command = '--alter --issues=' . \implode(',', \array_keys(self::$fixable_issue_counts)); $command .= ' --dry-run'; echo 'Psalm can automatically fix ' . $total_count . ($show_info ? ' issues' : ' of these issues') . ".\n" . 'Run Psalm again with ' . "\n" . ($project_analyzer->stdout_report_options->use_color ? "\33[30;48;5;195m" . $command . "\33[0m" : $command) . "\n" . 'to see what it can fix.' . "\n"; } echo \str_repeat('-', 30) . "\n" . "\n"; if ($start_time) { echo 'Checks took ' . \number_format(\microtime(\true) - $start_time, 2) . ' seconds'; echo ' and used ' . \number_format(\memory_get_peak_usage() / (1024 * 1024), 3) . 'MB of memory' . "\n"; $analysis_summary = $codebase->analyzer->getTypeInferenceSummary($codebase); echo $analysis_summary . "\n"; if ($add_stats) { echo '-----------------' . "\n"; echo $codebase->analyzer->getNonMixedStats(); echo "\n"; } if ($project_analyzer->debug_performance) { echo '-----------------' . "\n"; echo 'Slow-to-analyze functions' . "\n"; echo '-----------------' . "\n\n"; $function_timings = $codebase->analyzer->getFunctionTimings(); \arsort($function_timings); $i = 0; foreach ($function_timings as $function_id => $time) { if (++$i > 10) { break; } echo $function_id . ': ' . \round(1000 * $time, 2) . 'ms per node' . "\n"; } echo "\n"; } } } if ($is_full && $start_time) { $codebase->file_reference_provider->removeDeletedFilesFromReferences(); if ($project_analyzer->project_cache_provider) { $project_analyzer->project_cache_provider->processSuccessfulRun($start_time); } if ($codebase->statements_provider->parser_cache_provider) { $codebase->statements_provider->parser_cache_provider->processSuccessfulRun(); } } if ($error_count) { exit(1); } } /** * @param array> $issues_data * @param array{int, int} $mixed_counts * */ public static function getOutput(array $issues_data, \Psalm\Report\ReportOptions $report_options, array $mixed_counts = [0, 0]) : string { $total_expression_count = $mixed_counts[0] + $mixed_counts[1]; $mixed_expression_count = $mixed_counts[0]; $normalized_data = $issues_data === [] ? [] : \array_merge(...\array_values($issues_data)); switch ($report_options->format) { case \Psalm\Report::TYPE_COMPACT: $output = new \Psalm\Report\CompactReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_EMACS: $output = new \Psalm\Report\EmacsReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_TEXT: $output = new \Psalm\Report\TextReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_JSON: $output = new \Psalm\Report\JsonReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_JSON_SUMMARY: $output = new \Psalm\Report\JsonSummaryReport($normalized_data, self::$fixable_issue_counts, $report_options, $mixed_expression_count, $total_expression_count); break; case \Psalm\Report::TYPE_SONARQUBE: $output = new \Psalm\Report\SonarqubeReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_PYLINT: $output = new \Psalm\Report\PylintReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_CHECKSTYLE: $output = new \Psalm\Report\CheckstyleReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_XML: $output = new \Psalm\Report\XmlReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_JUNIT: $output = new \Psalm\Report\JunitReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_CONSOLE: $output = new \Psalm\Report\ConsoleReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_GITHUB_ACTIONS: $output = new \Psalm\Report\GithubActionsReport($normalized_data, self::$fixable_issue_counts, $report_options); break; case \Psalm\Report::TYPE_PHP_STORM: $output = new \Psalm\Report\PhpStormReport($normalized_data, self::$fixable_issue_counts, $report_options); break; } return $output->create(); } protected static function alreadyEmitted(string $message) : bool { $sham = \sha1($message); if (isset(self::$emitted[$sham])) { return \true; } self::$emitted[$sham] = \true; return \false; } public static function clearCache() : void { self::$issues_data = []; self::$emitted = []; self::$error_count = 0; self::$recording_level = 0; self::$recorded_issues = []; self::$console_issues = []; self::$unused_suppressions = []; self::$used_suppressions = []; } /** * @return array> */ public static function clear() : array { $current_data = self::$issues_data; self::$issues_data = []; self::$emitted = []; return $current_data; } public static function isRecording() : bool { return self::$recording_level > 0; } public static function startRecording() : void { ++self::$recording_level; self::$recorded_issues[self::$recording_level] = []; } public static function stopRecording() : void { if (self::$recording_level === 0) { throw new \UnexpectedValueException('Cannot stop recording - already at base level'); } --self::$recording_level; } /** * @return array */ public static function clearRecordingLevel() : array { if (self::$recording_level === 0) { throw new \UnexpectedValueException('Not currently recording'); } $recorded_issues = self::$recorded_issues[self::$recording_level]; self::$recorded_issues[self::$recording_level] = []; return $recorded_issues; } public static function bubbleUp(\Psalm\Issue\CodeIssue $e) : void { if (self::$recording_level === 0) { self::add($e); return; } self::$recorded_issues[self::$recording_level][] = $e; } } path = $path; $this->config = $config; $this->codebase = $codebase; } /** * @psalm-suppress PossiblyUnusedParam */ public function __invoke(\Psalm\Plugin\RegistrationInterface $registration, ?\SimpleXMLElement $config = null) : void { $fq_class_name = $this->getPluginClassForPath($this->path); /** @psalm-suppress UnresolvableInclude */ require_once $this->path; $registration->registerHooksFromClass($fq_class_name); } private function getPluginClassForPath(string $path) : string { $codebase = $this->codebase; $path = \str_replace(['/', '\\'], \DIRECTORY_SEPARATOR, $path); $file_storage = $codebase->createFileStorageForPath($path); $file_to_scan = new \Psalm\Internal\Scanner\FileScanner($path, $this->config->shortenFileName($path), \true); $file_to_scan->scan($codebase, $file_storage); $declared_classes = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getClassesForFile($codebase, $path); $fq_class_name = \reset($declared_classes); return $fq_class_name; } } > $template_type_map */ public static function parseString(string $type_string, ?array $php_version = null, array $template_type_map = []) : \Psalm\Type\Union { return \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::tokenize($type_string), $php_version, $template_type_map); } public static function getFQCLNFromString(string $class, \Psalm\Aliases $aliases) : string { if ($class === '') { throw new \InvalidArgumentException('$class cannot be empty'); } if ($class[0] === '\\') { return \substr($class, 1); } $imported_namespaces = $aliases->uses; if (\strpos($class, '\\') !== \false) { $class_parts = \explode('\\', $class); $first_namespace = \array_shift($class_parts); if (isset($imported_namespaces[\strtolower($first_namespace)])) { return $imported_namespaces[\strtolower($first_namespace)] . '\\' . \implode('\\', $class_parts); } } elseif (isset($imported_namespaces[\strtolower($class)])) { return $imported_namespaces[\strtolower($class)]; } $namespace = $aliases->namespace; return ($namespace ? $namespace . '\\' : '') . $class; } /** * @param array $aliased_classes * * @psalm-pure */ public static function getStringFromFQCLN(string $value, ?string $namespace, array $aliased_classes, ?string $this_class, bool $allow_self = \false) : string { if ($allow_self && $value === $this_class) { return 'self'; } if (isset($aliased_classes[\strtolower($value)])) { return $aliased_classes[\strtolower($value)]; } if ($namespace && \stripos($value, $namespace . '\\') === 0) { $candidate = \preg_replace('/^' . \preg_quote($namespace . '\\') . '/i', '', $value); $candidate_parts = \explode('\\', $candidate); if (!isset($aliased_classes[\strtolower($candidate_parts[0])])) { return $candidate; } } elseif (!$namespace && \strpos($value, '\\') === \false) { return $value; } if (\strpos($value, '\\')) { $parts = \explode('\\', $value); $suffix = \array_pop($parts); while ($parts) { $left = \implode('\\', $parts); if (isset($aliased_classes[\strtolower($left)])) { return $aliased_classes[\strtolower($left)] . '\\' . $suffix; } $suffix = \array_pop($parts) . '\\' . $suffix; } } return '\\' . $value; } public static function getInt(bool $from_calculation = \false, ?int $value = null) : \Psalm\Type\Union { if ($value !== null) { $union = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralInt($value)]); } else { $union = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt()]); } $union->from_calculation = $from_calculation; return $union; } /** * @param int|null $value * */ public static function getPositiveInt(bool $from_calculation = \false) : \Psalm\Type\Union { $union = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TPositiveInt()]); $union->from_calculation = $from_calculation; return $union; } public static function getNumeric() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TNumeric(); return new \Psalm\Type\Union([$type]); } public static function getString(?string $value = null) : \Psalm\Type\Union { $type = null; if ($value !== null) { $config = \Psalm\Config::getInstance(); if ($config->string_interpreters) { foreach ($config->string_interpreters as $string_interpreter) { if ($type = $string_interpreter::getTypeFromValue($value)) { break; } } } if (!$type) { if (\strlen($value) < $config->max_string_length) { $type = new \Psalm\Type\Atomic\TLiteralString($value); } else { $type = new \Psalm\Type\Atomic\TNonEmptyString(); } } } if (!$type) { $type = new \Psalm\Type\Atomic\TString(); } return new \Psalm\Type\Union([$type]); } public static function getSingleLetter() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TSingleLetter(); return new \Psalm\Type\Union([$type]); } public static function getClassString(string $extends = 'object') : \Psalm\Type\Union { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClassString($extends, $extends === 'object' ? null : new \Psalm\Type\Atomic\TNamedObject($extends))]); } public static function getLiteralClassString(string $class_type) : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TLiteralClassString($class_type); return new \Psalm\Type\Union([$type]); } public static function getNull() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TNull(); return new \Psalm\Type\Union([$type]); } public static function getMixed(bool $from_loop_isset = \false) : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TMixed($from_loop_isset); return new \Psalm\Type\Union([$type]); } public static function getScalar() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TScalar(); return new \Psalm\Type\Union([$type]); } public static function getEmpty() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TEmpty(); return new \Psalm\Type\Union([$type]); } public static function getBool() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TBool(); return new \Psalm\Type\Union([$type]); } public static function getFloat(?float $value = null) : \Psalm\Type\Union { if ($value !== null) { $type = new \Psalm\Type\Atomic\TLiteralFloat($value); } else { $type = new \Psalm\Type\Atomic\TFloat(); } return new \Psalm\Type\Union([$type]); } public static function getObject() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TObject(); return new \Psalm\Type\Union([$type]); } public static function getClosure() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TClosure('Closure'); return new \Psalm\Type\Union([$type]); } public static function getArrayKey() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TArrayKey(); return new \Psalm\Type\Union([$type]); } public static function getArray() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArrayKey()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TMixed()])]); return new \Psalm\Type\Union([$type]); } public static function getEmptyArray() : \Psalm\Type\Union { $array_type = new \Psalm\Type\Atomic\TArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()])]); return new \Psalm\Type\Union([$array_type]); } public static function getList() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TList(new \Psalm\Type\Union([new \Psalm\Type\Atomic\TMixed()])); return new \Psalm\Type\Union([$type]); } public static function getNonEmptyList() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TNonEmptyList(new \Psalm\Type\Union([new \Psalm\Type\Atomic\TMixed()])); return new \Psalm\Type\Union([$type]); } public static function getVoid() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TVoid(); return new \Psalm\Type\Union([$type]); } public static function getFalse() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TFalse(); return new \Psalm\Type\Union([$type]); } public static function getTrue() : \Psalm\Type\Union { $type = new \Psalm\Type\Atomic\TTrue(); return new \Psalm\Type\Union([$type]); } public static function getResource() : \Psalm\Type\Union { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TResource()]); } /** * @param non-empty-list $union_types */ public static function combineUnionTypeArray(array $union_types, ?\Psalm\Codebase $codebase) : \Psalm\Type\Union { $first_type = \array_pop($union_types); foreach ($union_types as $type) { $first_type = self::combineUnionTypes($first_type, $type, $codebase); } return $first_type; } /** * Combines two union types into one * * @param int $literal_limit any greater number of literal types than this * will be merged to a scalar * */ public static function combineUnionTypes(\Psalm\Type\Union $type_1, \Psalm\Type\Union $type_2, ?\Psalm\Codebase $codebase = null, bool $overwrite_empty_array = \false, bool $allow_mixed_union = \true, int $literal_limit = 500) : \Psalm\Type\Union { if ($type_1 === $type_2) { return $type_1; } if ($type_1->isVanillaMixed() && $type_2->isVanillaMixed()) { $combined_type = \Psalm\Type::getMixed(); } else { $both_failed_reconciliation = \false; if ($type_1->failed_reconciliation) { if ($type_2->failed_reconciliation) { $both_failed_reconciliation = \true; } else { $type_2 = clone $type_2; $type_2->parent_nodes += $type_1->parent_nodes; return $type_2; } } elseif ($type_2->failed_reconciliation) { $type_1 = clone $type_1; $type_1->parent_nodes += $type_2->parent_nodes; return $type_1; } $combined_type = \Psalm\Internal\Type\TypeCombination::combineTypes(\array_merge(\array_values($type_1->getAtomicTypes()), \array_values($type_2->getAtomicTypes())), $codebase, $overwrite_empty_array, $allow_mixed_union, $literal_limit); if (!$type_1->initialized || !$type_2->initialized) { $combined_type->initialized = \false; } if ($type_1->possibly_undefined_from_try || $type_2->possibly_undefined_from_try) { $combined_type->possibly_undefined_from_try = \true; } if ($type_1->from_docblock || $type_2->from_docblock) { $combined_type->from_docblock = \true; } if ($type_1->from_calculation || $type_2->from_calculation) { $combined_type->from_calculation = \true; } if ($type_1->ignore_nullable_issues || $type_2->ignore_nullable_issues) { $combined_type->ignore_nullable_issues = \true; } if ($type_1->ignore_falsable_issues || $type_2->ignore_falsable_issues) { $combined_type->ignore_falsable_issues = \true; } if ($type_1->had_template && $type_2->had_template) { $combined_type->had_template = \true; } if ($type_1->reference_free && $type_2->reference_free) { $combined_type->reference_free = \true; } if ($both_failed_reconciliation) { $combined_type->failed_reconciliation = \true; } } if ($type_1->possibly_undefined || $type_2->possibly_undefined) { $combined_type->possibly_undefined = \true; } if ($type_1->parent_nodes || $type_2->parent_nodes) { $combined_type->parent_nodes = $type_1->parent_nodes + $type_2->parent_nodes; } if ($type_1->by_ref || $type_2->by_ref) { $combined_type->by_ref = \true; } return $combined_type; } /** * Combines two union types into one via an intersection * * */ public static function intersectUnionTypes(\Psalm\Type\Union $type_1, \Psalm\Type\Union $type_2, \Psalm\Codebase $codebase) : ?\Psalm\Type\Union { $intersection_performed = \false; if ($type_1->isMixed() && $type_2->isMixed()) { $combined_type = \Psalm\Type::getMixed(); } else { $both_failed_reconciliation = \false; if ($type_1->failed_reconciliation) { if ($type_2->failed_reconciliation) { $both_failed_reconciliation = \true; } else { return $type_2; } } elseif ($type_2->failed_reconciliation) { return $type_1; } if ($type_1->isMixed() && !$type_2->isMixed()) { $combined_type = clone $type_2; $intersection_performed = \true; } elseif (!$type_1->isMixed() && $type_2->isMixed()) { $combined_type = clone $type_1; $intersection_performed = \true; } else { $combined_type = clone $type_1; foreach ($combined_type->getAtomicTypes() as $t1_key => $type_1_atomic) { foreach ($type_2->getAtomicTypes() as $t2_key => $type_2_atomic) { if ($type_1_atomic instanceof \Psalm\Type\Atomic\TNamedObject && $type_2_atomic instanceof \Psalm\Type\Atomic\TNamedObject) { if (\Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $type_2_atomic, $type_1_atomic)) { $combined_type->removeType($t1_key); $combined_type->addType(clone $type_2_atomic); $intersection_performed = \true; } elseif (\Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $type_1_atomic, $type_2_atomic)) { $combined_type->removeType($t2_key); $combined_type->addType(clone $type_1_atomic); $intersection_performed = \true; } } if (($type_1_atomic instanceof \Psalm\Type\Atomic\TIterable || $type_1_atomic instanceof \Psalm\Type\Atomic\TNamedObject || $type_1_atomic instanceof \Psalm\Type\Atomic\TTemplateParam || $type_1_atomic instanceof \Psalm\Type\Atomic\TObjectWithProperties) && ($type_2_atomic instanceof \Psalm\Type\Atomic\TIterable || $type_2_atomic instanceof \Psalm\Type\Atomic\TNamedObject || $type_2_atomic instanceof \Psalm\Type\Atomic\TTemplateParam || $type_2_atomic instanceof \Psalm\Type\Atomic\TObjectWithProperties)) { if (!$type_1_atomic->extra_types) { $type_1_atomic->extra_types = []; } $intersection_performed = \true; $type_2_atomic_clone = clone $type_2_atomic; $type_2_atomic_clone->extra_types = []; $type_1_atomic->extra_types[$type_2_atomic_clone->getKey()] = $type_2_atomic_clone; $type_2_atomic_intersection_types = $type_2_atomic->getIntersectionTypes(); if ($type_2_atomic_intersection_types) { foreach ($type_2_atomic_intersection_types as $type_2_intersection_type) { $type_1_atomic->extra_types[$type_2_intersection_type->getKey()] = clone $type_2_intersection_type; } } } if ($type_1_atomic instanceof \Psalm\Type\Atomic\TObject && $type_2_atomic instanceof \Psalm\Type\Atomic\TNamedObject) { $combined_type->removeType($t1_key); $combined_type->addType(clone $type_2_atomic); $intersection_performed = \true; } elseif ($type_2_atomic instanceof \Psalm\Type\Atomic\TObject && $type_1_atomic instanceof \Psalm\Type\Atomic\TNamedObject) { $combined_type->removeType($t2_key); $combined_type->addType(clone $type_1_atomic); $intersection_performed = \true; } } } } if (!$type_1->initialized && !$type_2->initialized) { $combined_type->initialized = \false; } if ($type_1->possibly_undefined_from_try && $type_2->possibly_undefined_from_try) { $combined_type->possibly_undefined_from_try = \true; } if ($type_1->from_docblock && $type_2->from_docblock) { $combined_type->from_docblock = \true; } if ($type_1->from_calculation && $type_2->from_calculation) { $combined_type->from_calculation = \true; } if ($type_1->ignore_nullable_issues && $type_2->ignore_nullable_issues) { $combined_type->ignore_nullable_issues = \true; } if ($type_1->ignore_falsable_issues && $type_2->ignore_falsable_issues) { $combined_type->ignore_falsable_issues = \true; } if ($both_failed_reconciliation) { $combined_type->failed_reconciliation = \true; } } if (!$intersection_performed && $type_1->getId() !== $type_2->getId()) { return null; } if ($type_1->possibly_undefined && $type_2->possibly_undefined) { $combined_type->possibly_undefined = \true; } return $combined_type; } } */ public static $ERROR_LEVELS = [self::REPORT_INFO, self::REPORT_ERROR, self::REPORT_SUPPRESS]; /** * @var array */ private const MIXED_ISSUES = ['MixedArgument', 'MixedArrayAccess', 'MixedArrayAssignment', 'MixedArrayOffset', 'MixedArrayTypeCoercion', 'MixedAssignment', 'MixedFunctionCall', 'MixedInferredReturnType', 'MixedMethodCall', 'MixedOperand', 'MixedPropertyFetch', 'MixedPropertyAssignment', 'MixedReturnStatement', 'MixedStringOffsetAssignment', 'MixedArgumentTypeCoercion', 'MixedPropertyTypeCoercion', 'MixedReturnTypeCoercion']; /** * These are special object classes that allow any and all properties to be get/set on them * @var array */ protected $universal_object_crates = [\stdClass::class, \SimpleXMLElement::class]; /** * @var static|null */ private static $instance; /** * Whether or not to use types as defined in docblocks * * @var bool */ public $use_docblock_types = \true; /** * Whether or not to use types as defined in property docblocks. * This is distinct from the above because you may want to use * property docblocks, but not function docblocks. * * @var bool */ public $use_docblock_property_types = \false; /** * Whether or not to throw an exception on first error * * @var bool */ public $throw_exception = \false; /** * Whether or not to load Xdebug stub * * @var bool|null */ public $load_xdebug_stub = null; /** * The directory to store PHP Parser (and other) caches * * @var string|null */ public $cache_directory; /** * The directory to store all Psalm project caches * * @var string|null */ public $global_cache_directory; /** * Path to the autoader * * @var string|null */ public $autoloader; /** * @var ProjectFileFilter|null */ protected $project_files; /** * @var ProjectFileFilter|null */ protected $extra_files; /** * The base directory of this config file * * @var string */ public $base_dir; /** * The PHP version to assume as declared in the config file * * @var string|null */ private $configured_php_version; /** * @var array */ private $file_extensions = ['php']; /** * @var array> */ private $filetype_scanners = []; /** * @var array> */ private $filetype_analyzers = []; /** * @var array */ private $filetype_scanner_paths = []; /** * @var array */ private $filetype_analyzer_paths = []; /** * @var array */ private $issue_handlers = []; /** * @var array */ private $mock_classes = []; /** * @var array */ private $stub_files = []; /** * @var bool */ public $hide_external_errors = \false; /** @var bool */ public $allow_includes = \true; /** @var 1|2|3|4|5|6|7|8 */ public $level = 1; /** * @var ?bool */ public $show_mixed_issues = null; /** @var bool */ public $strict_binary_operands = \false; /** * @var bool */ public $remember_property_assignments_after_call = \true; /** @var bool */ public $use_igbinary = \false; /** * @var bool */ public $allow_phpstorm_generics = \false; /** * @var bool */ public $allow_string_standin_for_class = \false; /** * @var bool */ public $use_phpdoc_method_without_magic_or_parent = \false; /** * @var bool */ public $use_phpdoc_property_without_magic_or_parent = \false; /** * @var bool */ public $skip_checks_on_unresolvable_includes = \false; /** * @var bool */ public $seal_all_methods = \false; /** * @var bool */ public $memoize_method_calls = \false; /** * @var bool */ public $hoist_constants = \false; /** * @var bool */ public $add_param_default_to_docblock_type = \false; /** * @var bool */ public $check_for_throws_docblock = \false; /** * @var bool */ public $check_for_throws_in_global_scope = \false; /** * @var bool */ public $ignore_internal_falsable_issues = \true; /** * @var bool */ public $ignore_internal_nullable_issues = \true; /** * @var array */ public $ignored_exceptions = []; /** * @var array */ public $ignored_exceptions_in_global_scope = []; /** * @var array */ public $ignored_exceptions_and_descendants = []; /** * @var array */ public $ignored_exceptions_and_descendants_in_global_scope = []; /** * @var bool */ public $infer_property_types_from_constructor = \true; /** * @var bool */ public $ensure_array_string_offsets_exist = \false; /** * @var bool */ public $ensure_array_int_offsets_exist = \false; /** * @var array */ public $forbidden_functions = []; /** * @var bool */ public $forbid_echo = \false; /** * @var bool */ public $find_unused_code = \false; /** * @var bool */ public $find_unused_variables = \false; /** * @var bool */ public $find_unused_psalm_suppress = \false; /** * @var bool */ public $run_taint_analysis = \false; /** @var bool */ public $use_phpstorm_meta_path = \true; /** * @var bool */ public $resolve_from_config_file = \true; /** * @var string[] */ public $plugin_paths = []; /** * @var array */ private $plugin_classes = []; /** * Static methods to be called after method checks have completed * * @var class-string[] */ public $after_method_checks = []; /** * Static methods to be called after project function checks have completed * * Called after function calls to functions defined in the project. * * Allows influencing the return type and adding of modifications. * * @var class-string[] */ public $after_function_checks = []; /** * Static methods to be called after every function call * * Called after each function call, including php internal functions. * * Cannot change the call or influence its return type * * @var class-string[] */ public $after_every_function_checks = []; /** * Static methods to be called after expression checks have completed * * @var class-string[] */ public $after_expression_checks = []; /** * Static methods to be called after statement checks have completed * * @var class-string[] */ public $after_statement_checks = []; /** * Static methods to be called after method checks have completed * * @var class-string[] */ public $string_interpreters = []; /** * Static methods to be called after classlike exists checks have completed * * @var class-string[] */ public $after_classlike_exists_checks = []; /** * Static methods to be called after classlike checks have completed * * @var class-string[] */ public $after_classlike_checks = []; /** * Static methods to be called after classlikes have been scanned * * @var class-string[] */ public $after_visit_classlikes = []; /** * Static methods to be called after codebase has been populated * * @var class-string[] */ public $after_codebase_populated = []; /** * Static methods to be called after codebase has been populated * * @var class-string[] */ public $after_analysis = []; /** * Static methods to be called after a file has been analyzed * @var class-string[] */ public $after_file_checks = []; /** * Static methods to be called before a file is analyzed * @var class-string[] */ public $before_file_checks = []; /** * @var bool */ public $allow_internal_named_arg_calls = \true; /** * @var bool */ public $allow_named_arg_calls = \true; /** * Static methods to be called after functionlike checks have completed * * @var class-string[] */ public $after_functionlike_checks = []; /** @var array */ private $predefined_constants = []; /** @var array */ private $predefined_functions = []; /** @var ClassLoader|null */ private $composer_class_loader; /** * Custom functions that always exit * * @var array */ public $exit_functions = []; /** * @var string */ public $hash = ''; /** @var string|null */ public $error_baseline = null; /** * @var bool */ public $include_php_versions_in_error_baseline = \false; /** @var string */ public $shepherd_host = 'shepherd.dev'; /** * @var array */ public $globals = []; /** * @var int */ public $max_string_length = 1000; /** @var ?IncludeCollector */ private $include_collector; /** * @var TaintAnalysisFileFilter|null */ protected $taint_analysis_ignored_files; /** * @var bool whether to emit a backtrace of emitted issues to stderr */ public $debug_emitted_issues = \false; /** * @var bool */ private $report_info = \true; protected function __construct() { self::$instance = $this; } /** * Gets a Config object from an XML file. * * Searches up a folder hierarchy for the most immediate config. * * @throws ConfigException if a config path is not found * */ public static function getConfigForPath(string $path, string $current_dir, string $output_format) : \Psalm\Config { $config_path = self::locateConfigFile($path); if (!$config_path) { if (\in_array($output_format, [\Psalm\Report::TYPE_CONSOLE, \Psalm\Report::TYPE_PHP_STORM])) { echo 'Could not locate a config XML file in path ' . $path . '. Have you run \'psalm --init\' ?' . \PHP_EOL; exit(1); } throw new \Psalm\Exception\ConfigException('Config not found for path ' . $path); } return self::loadFromXMLFile($config_path, $current_dir); } /** * Searches up a folder hierarchy for the most immediate config. * * @throws ConfigException * */ public static function locateConfigFile(string $path) : ?string { $dir_path = \realpath($path); if ($dir_path === \false) { throw new \Psalm\Exception\ConfigException('Config not found for path ' . $path); } if (!\is_dir($dir_path)) { $dir_path = \dirname($dir_path); } do { $maybe_path = $dir_path . \DIRECTORY_SEPARATOR . \Psalm\Config::DEFAULT_FILE_NAME; if (\file_exists($maybe_path) || \file_exists($maybe_path .= '.dist')) { return $maybe_path; } $dir_path = \dirname($dir_path); } while (\dirname($dir_path) !== $dir_path); return null; } /** * Creates a new config object from the file */ public static function loadFromXMLFile(string $file_path, string $current_dir) : \Psalm\Config { $file_contents = \file_get_contents($file_path); $base_dir = \dirname($file_path) . \DIRECTORY_SEPARATOR; if ($file_contents === \false) { throw new \InvalidArgumentException('Cannot open ' . $file_path); } try { $config = self::loadFromXML($base_dir, $file_contents, $current_dir); $config->hash = \sha1($file_contents . \PSALM_VERSION); } catch (\Psalm\Exception\ConfigException $e) { throw new \Psalm\Exception\ConfigException('Problem parsing ' . $file_path . ":\n" . ' ' . $e->getMessage()); } return $config; } /** * Creates a new config object from an XML string * @param string|null $current_dir Current working directory, if different to $base_dir * * @throws ConfigException */ public static function loadFromXML(string $base_dir, string $file_contents, ?string $current_dir = null) : \Psalm\Config { if ($current_dir === null) { $current_dir = $base_dir; } self::validateXmlConfig($base_dir, $file_contents); return self::fromXmlAndPaths($base_dir, $file_contents, $current_dir); } private static function loadDomDocument(string $base_dir, string $file_contents) : \DOMDocument { $dom_document = new \DOMDocument(); // there's no obvious way to set xml:base for a document when loading it from string // so instead we're changing the current directory instead to be able to process XIncludes $oldpwd = \getcwd(); \chdir($base_dir); $dom_document->loadXML($file_contents, \LIBXML_NONET); $dom_document->xinclude(\LIBXML_NONET); \chdir($oldpwd); return $dom_document; } /** * @throws ConfigException */ private static function validateXmlConfig(string $base_dir, string $file_contents) : void { $schema_path = \dirname(__DIR__, 2) . '/config.xsd'; if (!\file_exists($schema_path)) { throw new \Psalm\Exception\ConfigException('Cannot locate config schema'); } $dom_document = self::loadDomDocument($base_dir, $file_contents); $psalm_nodes = $dom_document->getElementsByTagName('psalm'); /** @var \DomElement|null */ $psalm_node = $psalm_nodes->item(0); if (!$psalm_node) { throw new \Psalm\Exception\ConfigException('Missing psalm node'); } if (!$psalm_node->hasAttribute('xmlns')) { $psalm_node->setAttribute('xmlns', 'https://getpsalm.org/schema/config'); $old_dom_document = $dom_document; $dom_document = self::loadDomDocument($base_dir, $old_dom_document->saveXML()); } // Enable user error handling \libxml_use_internal_errors(\true); if (!$dom_document->schemaValidate($schema_path)) { $errors = \libxml_get_errors(); foreach ($errors as $error) { if ($error->level === \LIBXML_ERR_FATAL || $error->level === \LIBXML_ERR_ERROR) { throw new \Psalm\Exception\ConfigException('Error on line ' . $error->line . ":\n" . ' ' . $error->message); } } \libxml_clear_errors(); } } /** * @psalm-suppress MixedMethodCall * @psalm-suppress MixedAssignment * @psalm-suppress MixedOperand * @psalm-suppress MixedArgument * @psalm-suppress MixedPropertyFetch * * @throws ConfigException */ private static function fromXmlAndPaths(string $base_dir, string $file_contents, string $current_dir) : self { $config = new static(); $dom_document = self::loadDomDocument($base_dir, $file_contents); $config_xml = \simplexml_import_dom($dom_document); $booleanAttributes = ['useDocblockTypes' => 'use_docblock_types', 'useDocblockPropertyTypes' => 'use_docblock_property_types', 'throwExceptionOnError' => 'throw_exception', 'hideExternalErrors' => 'hide_external_errors', 'resolveFromConfigFile' => 'resolve_from_config_file', 'allowFileIncludes' => 'allow_includes', 'strictBinaryOperands' => 'strict_binary_operands', 'rememberPropertyAssignmentsAfterCall' => 'remember_property_assignments_after_call', 'allowPhpStormGenerics' => 'allow_phpstorm_generics', 'allowStringToStandInForClass' => 'allow_string_standin_for_class', 'usePhpDocMethodsWithoutMagicCall' => 'use_phpdoc_method_without_magic_or_parent', 'usePhpDocPropertiesWithoutMagicCall' => 'use_phpdoc_property_without_magic_or_parent', 'memoizeMethodCallResults' => 'memoize_method_calls', 'hoistConstants' => 'hoist_constants', 'addParamDefaultToDocblockType' => 'add_param_default_to_docblock_type', 'checkForThrowsDocblock' => 'check_for_throws_docblock', 'checkForThrowsInGlobalScope' => 'check_for_throws_in_global_scope', 'forbidEcho' => 'forbid_echo', 'ignoreInternalFunctionFalseReturn' => 'ignore_internal_falsable_issues', 'ignoreInternalFunctionNullReturn' => 'ignore_internal_nullable_issues', 'includePhpVersionsInErrorBaseline' => 'include_php_versions_in_error_baseline', 'loadXdebugStub' => 'load_xdebug_stub', 'ensureArrayStringOffsetsExist' => 'ensure_array_string_offsets_exist', 'ensureArrayIntOffsetsExist' => 'ensure_array_int_offsets_exist', 'reportMixedIssues' => 'show_mixed_issues', 'skipChecksOnUnresolvableIncludes' => 'skip_checks_on_unresolvable_includes', 'sealAllMethods' => 'seal_all_methods', 'runTaintAnalysis' => 'run_taint_analysis', 'usePhpStormMetaPath' => 'use_phpstorm_meta_path', 'allowInternalNamedArgumentsCalls' => 'allow_internal_named_arg_calls', 'allowNamedArgumentCalls' => 'allow_named_arg_calls', 'findUnusedPsalmSuppress' => 'find_unused_psalm_suppress', 'reportInfo' => 'report_info']; foreach ($booleanAttributes as $xmlName => $internalName) { if (isset($config_xml[$xmlName])) { $attribute_text = (string) $config_xml[$xmlName]; $config->setBooleanAttribute($internalName, $attribute_text === 'true' || $attribute_text === '1'); } } if ($config->resolve_from_config_file) { $config->base_dir = $base_dir; } else { $config->base_dir = $current_dir; $base_dir = $current_dir; } if (isset($config_xml['phpVersion'])) { $config->configured_php_version = (string) $config_xml['phpVersion']; } if (isset($config_xml['autoloader'])) { $autoloader_path = $config->base_dir . \DIRECTORY_SEPARATOR . $config_xml['autoloader']; if (!\file_exists($autoloader_path)) { throw new \Psalm\Exception\ConfigException('Cannot locate autoloader'); } $config->autoloader = \realpath($autoloader_path); } if (isset($config_xml['cacheDirectory'])) { $config->cache_directory = (string) $config_xml['cacheDirectory']; } elseif ($user_cache_dir = (new \_HumbugBoxd02f763d3c56\XdgBaseDir\Xdg())->getHomeCacheDir()) { $config->cache_directory = $user_cache_dir . '/psalm'; } else { $config->cache_directory = \sys_get_temp_dir() . '/psalm'; } $config->global_cache_directory = $config->cache_directory; $config->cache_directory .= \DIRECTORY_SEPARATOR . \sha1($base_dir); if (\is_dir($config->cache_directory) === \false && @\mkdir($config->cache_directory, 0777, \true) === \false) { \trigger_error('Could not create cache directory: ' . $config->cache_directory, \E_USER_ERROR); } if (isset($config_xml['serializer'])) { $attribute_text = (string) $config_xml['serializer']; $config->use_igbinary = $attribute_text === 'igbinary'; } elseif ($igbinary_version = \phpversion('igbinary')) { $config->use_igbinary = \version_compare($igbinary_version, '2.0.5') >= 0; } if (isset($config_xml['findUnusedCode'])) { $attribute_text = (string) $config_xml['findUnusedCode']; $config->find_unused_code = $attribute_text === 'true' || $attribute_text === '1'; $config->find_unused_variables = $config->find_unused_code; } if (isset($config_xml['findUnusedVariablesAndParams'])) { $attribute_text = (string) $config_xml['findUnusedVariablesAndParams']; $config->find_unused_variables = $attribute_text === 'true' || $attribute_text === '1'; } if (isset($config_xml['errorLevel'])) { $attribute_text = (int) $config_xml['errorLevel']; if (!\in_array($attribute_text, [1, 2, 3, 4, 5, 6, 7, 8], \true)) { throw new \Psalm\Exception\ConfigException('Invalid error level ' . $config_xml['errorLevel']); } $config->level = $attribute_text; } elseif (isset($config_xml['totallyTyped'])) { $totally_typed = (string) $config_xml['totallyTyped']; if ($totally_typed === 'true' || $totally_typed === '1') { $config->level = 1; } else { $config->level = 2; if ($config->show_mixed_issues === null) { $config->show_mixed_issues = \false; } } } else { $config->level = 2; } if (isset($config_xml['errorBaseline'])) { $attribute_text = (string) $config_xml['errorBaseline']; $config->error_baseline = $attribute_text; } if (isset($config_xml['maxStringLength'])) { $attribute_text = \intval($config_xml['maxStringLength']); $config->max_string_length = $attribute_text; } if (isset($config_xml['inferPropertyTypesFromConstructor'])) { $attribute_text = (string) $config_xml['inferPropertyTypesFromConstructor']; $config->infer_property_types_from_constructor = $attribute_text === 'true' || $attribute_text === '1'; } if (isset($config_xml->projectFiles)) { $config->project_files = \Psalm\Config\ProjectFileFilter::loadFromXMLElement($config_xml->projectFiles, $base_dir, \true); } if (isset($config_xml->extraFiles)) { $config->extra_files = \Psalm\Config\ProjectFileFilter::loadFromXMLElement($config_xml->extraFiles, $base_dir, \true); } if (isset($config_xml->taintAnalysis->ignoreFiles)) { $config->taint_analysis_ignored_files = \Psalm\Config\TaintAnalysisFileFilter::loadFromXMLElement($config_xml->taintAnalysis->ignoreFiles, $base_dir, \false); } if (isset($config_xml->fileExtensions)) { $config->file_extensions = []; $config->loadFileExtensions($config_xml->fileExtensions->extension); } if (isset($config_xml->mockClasses) && isset($config_xml->mockClasses->class)) { /** @var \SimpleXMLElement $mock_class */ foreach ($config_xml->mockClasses->class as $mock_class) { $config->mock_classes[] = \strtolower((string) $mock_class['name']); } } if (isset($config_xml->universalObjectCrates) && isset($config_xml->universalObjectCrates->class)) { /** @var \SimpleXMLElement $universal_object_crate */ foreach ($config_xml->universalObjectCrates->class as $universal_object_crate) { /** @var class-string $classString */ $classString = $universal_object_crate['name']; $config->addUniversalObjectCrate($classString); } } if (isset($config_xml->ignoreExceptions)) { if (isset($config_xml->ignoreExceptions->class)) { /** @var \SimpleXMLElement $exception_class */ foreach ($config_xml->ignoreExceptions->class as $exception_class) { $exception_name = (string) $exception_class['name']; $global_attribute_text = (string) $exception_class['onlyGlobalScope']; if ($global_attribute_text !== 'true' && $global_attribute_text !== '1') { $config->ignored_exceptions[$exception_name] = \true; } $config->ignored_exceptions_in_global_scope[$exception_name] = \true; } } if (isset($config_xml->ignoreExceptions->classAndDescendants)) { /** @var \SimpleXMLElement $exception_class */ foreach ($config_xml->ignoreExceptions->classAndDescendants as $exception_class) { $exception_name = (string) $exception_class['name']; $global_attribute_text = (string) $exception_class['onlyGlobalScope']; if ($global_attribute_text !== 'true' && $global_attribute_text !== '1') { $config->ignored_exceptions_and_descendants[$exception_name] = \true; } $config->ignored_exceptions_and_descendants_in_global_scope[$exception_name] = \true; } } } if (isset($config_xml->forbiddenFunctions) && isset($config_xml->forbiddenFunctions->function)) { /** @var \SimpleXMLElement $forbidden_function */ foreach ($config_xml->forbiddenFunctions->function as $forbidden_function) { $config->forbidden_functions[\strtolower((string) $forbidden_function['name'])] = \true; } } if (isset($config_xml->exitFunctions) && isset($config_xml->exitFunctions->function)) { /** @var \SimpleXMLElement $exit_function */ foreach ($config_xml->exitFunctions->function as $exit_function) { $config->exit_functions[\strtolower((string) $exit_function['name'])] = \true; } } if (isset($config_xml->stubs) && isset($config_xml->stubs->file)) { /** @var \SimpleXMLElement $stub_file */ foreach ($config_xml->stubs->file as $stub_file) { $stub_file_name = (string) $stub_file['name']; if (!\_HumbugBoxd02f763d3c56\Webmozart\PathUtil\Path::isAbsolute($stub_file_name)) { $stub_file_name = $config->base_dir . \DIRECTORY_SEPARATOR . $stub_file_name; } $file_path = \realpath($stub_file_name); if (!$file_path) { throw new \Psalm\Exception\ConfigException('Cannot resolve stubfile path ' . $config->base_dir . \DIRECTORY_SEPARATOR . $stub_file['name']); } $config->addStubFile($file_path); } } // this plugin loading system borrows heavily from etsy/phan if (isset($config_xml->plugins)) { if (isset($config_xml->plugins->plugin)) { /** @var \SimpleXMLElement $plugin */ foreach ($config_xml->plugins->plugin as $plugin) { $plugin_file_name = (string) $plugin['filename']; $path = \_HumbugBoxd02f763d3c56\Webmozart\PathUtil\Path::isAbsolute($plugin_file_name) ? $plugin_file_name : $config->base_dir . $plugin_file_name; $config->addPluginPath($path); } } if (isset($config_xml->plugins->pluginClass)) { /** @var \SimpleXMLElement $plugin */ foreach ($config_xml->plugins->pluginClass as $plugin) { $plugin_class_name = $plugin['class']; // any child elements are used as plugin configuration $plugin_config = null; if ($plugin->count()) { $plugin_config = $plugin->children(); } $config->addPluginClass((string) $plugin_class_name, $plugin_config); } } } if (isset($config_xml->issueHandlers)) { /** @var \SimpleXMLElement $issue_handler */ foreach ($config_xml->issueHandlers->children() as $key => $issue_handler) { if ($key === 'PluginIssue') { $custom_class_name = (string) $issue_handler['name']; /** @var string $key */ $config->issue_handlers[$custom_class_name] = \Psalm\Config\IssueHandler::loadFromXMLElement($issue_handler, $base_dir); } else { /** @var string $key */ $config->issue_handlers[$key] = \Psalm\Config\IssueHandler::loadFromXMLElement($issue_handler, $base_dir); } } } if (isset($config_xml->globals) && isset($config_xml->globals->var)) { /** @var \SimpleXMLElement $var */ foreach ($config_xml->globals->var as $var) { $config->globals['$' . (string) $var['name']] = (string) $var['type']; } } return $config; } public static function getInstance() : \Psalm\Config { if (self::$instance) { return self::$instance; } throw new \UnexpectedValueException('No config initialized'); } public function setComposerClassLoader(?\Composer\Autoload\ClassLoader $loader = null) : void { $this->composer_class_loader = $loader; } public function setCustomErrorLevel(string $issue_key, string $error_level) : void { $this->issue_handlers[$issue_key] = new \Psalm\Config\IssueHandler(); $this->issue_handlers[$issue_key]->setErrorLevel($error_level); } /** * @throws ConfigException if a Config file could not be found * */ private function loadFileExtensions(\SimpleXMLElement $extensions) : void { foreach ($extensions as $extension) { $extension_name = \preg_replace('/^\\.?/', '', (string) $extension['name']); $this->file_extensions[] = $extension_name; if (isset($extension['scanner'])) { $path = $this->base_dir . (string) $extension['scanner']; if (!\file_exists($path)) { throw new \Psalm\Exception\ConfigException('Error parsing config: cannot find file ' . $path); } $this->filetype_scanner_paths[$extension_name] = $path; } if (isset($extension['checker'])) { $path = $this->base_dir . (string) $extension['checker']; if (!\file_exists($path)) { throw new \Psalm\Exception\ConfigException('Error parsing config: cannot find file ' . $path); } $this->filetype_analyzer_paths[$extension_name] = $path; } } } public function addPluginPath(string $path) : void { if (!\file_exists($path)) { throw new \InvalidArgumentException('Cannot find plugin file ' . $path); } $this->plugin_paths[] = $path; } public function addPluginClass(string $class_name, ?\SimpleXMLElement $plugin_config = null) : void { $this->plugin_classes[] = ['class' => $class_name, 'config' => $plugin_config]; } /** @return array */ public function getPluginClasses() : array { return $this->plugin_classes; } /** * Initialises all the plugins (done once the config is fully loaded) * * @psalm-suppress MixedAssignment */ public function initializePlugins(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer) : void { $codebase = $project_analyzer->getCodebase(); $project_analyzer->progress->debug('Initializing plugins...' . \PHP_EOL); $socket = new \Psalm\PluginRegistrationSocket($this, $codebase); // initialize plugin classes earlier to let them hook into subsequent load process foreach ($this->plugin_classes as $plugin_class_entry) { $plugin_class_name = $plugin_class_entry['class']; $plugin_config = $plugin_class_entry['config']; try { // Below will attempt to load plugins from the project directory first. // Failing that, it will use registered autoload chain, which will load // plugins from Psalm directory or phar file. If that fails as well, it // will fall back to project autoloader. It may seem that the last step // will always fail, but it's only true if project uses Composer autoloader if ($this->composer_class_loader && ($plugin_class_path = $this->composer_class_loader->findFile($plugin_class_name))) { $project_analyzer->progress->debug('Loading plugin ' . $plugin_class_name . ' via require' . \PHP_EOL); self::requirePath($plugin_class_path); } else { if (!\class_exists($plugin_class_name, \true)) { throw new \UnexpectedValueException($plugin_class_name . ' is not a known class'); } } /** * @psalm-suppress InvalidStringClass * * @var Plugin\PluginEntryPointInterface */ $plugin_object = new $plugin_class_name(); $plugin_object($socket, $plugin_config); } catch (\Throwable $e) { throw new \Psalm\Exception\ConfigException('Failed to load plugin ' . $plugin_class_name, 0, $e); } $project_analyzer->progress->debug('Loaded plugin ' . $plugin_class_name . ' successfully' . \PHP_EOL); } foreach ($this->filetype_scanner_paths as $extension => $path) { $fq_class_name = $this->getPluginClassForPath($codebase, $path, \Psalm\Internal\Scanner\FileScanner::class); self::requirePath($path); $this->filetype_scanners[$extension] = $fq_class_name; } foreach ($this->filetype_analyzer_paths as $extension => $path) { $fq_class_name = $this->getPluginClassForPath($codebase, $path, \Psalm\Internal\Analyzer\FileAnalyzer::class); self::requirePath($path); $this->filetype_analyzers[$extension] = $fq_class_name; } foreach ($this->plugin_paths as $path) { try { $plugin_object = new \Psalm\FileBasedPluginAdapter($path, $this, $codebase); $plugin_object($socket); } catch (\Throwable $e) { throw new \Psalm\Exception\ConfigException('Failed to load plugin ' . $path, 0, $e); } } } private static function requirePath(string $path) : void { /** @psalm-suppress UnresolvableInclude */ require_once $path; } /** * @template T * * @param T::class $must_extend * * @return class-string */ private function getPluginClassForPath(\Psalm\Codebase $codebase, string $path, string $must_extend) : string { $file_storage = $codebase->createFileStorageForPath($path); $file_to_scan = new \Psalm\Internal\Scanner\FileScanner($path, $this->shortenFileName($path), \true); $file_to_scan->scan($codebase, $file_storage); $declared_classes = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getClassesForFile($codebase, $path); if (!\count($declared_classes)) { throw new \InvalidArgumentException('Plugins must have at least one class in the file - ' . $path . ' has ' . \count($declared_classes)); } $fq_class_name = \reset($declared_classes); if (!$codebase->classlikes->classExtends($fq_class_name, $must_extend)) { throw new \InvalidArgumentException('This plugin must extend ' . $must_extend . ' - ' . $path . ' does not'); } /** * @var class-string */ return $fq_class_name; } public function shortenFileName(string $file_name) : string { return \preg_replace('/^' . \preg_quote($this->base_dir, '/') . '/', '', $file_name); } public function reportIssueInFile(string $issue_type, string $file_path) : bool { if (($this->show_mixed_issues === \false || $this->level > 2) && \in_array($issue_type, self::MIXED_ISSUES, \true)) { return \false; } if ($this->mustBeIgnored($file_path)) { return \false; } $dependent_files = [\strtolower($file_path) => $file_path]; $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); if (!$this->hide_external_errors) { try { $file_storage = $codebase->file_storage_provider->get($file_path); $dependent_files += $file_storage->required_by_file_paths; } catch (\InvalidArgumentException $e) { // do nothing } } $any_file_path_matched = \false; foreach ($dependent_files as $dependent_file_path) { if ((!$project_analyzer->full_run && $codebase->analyzer->canReportIssues($dependent_file_path) || $project_analyzer->canReportIssues($dependent_file_path)) && ($file_path === $dependent_file_path || !$this->mustBeIgnored($dependent_file_path))) { $any_file_path_matched = \true; break; } } if (!$any_file_path_matched) { return \false; } if ($this->getReportingLevelForFile($issue_type, $file_path) === self::REPORT_SUPPRESS) { return \false; } return \true; } public function isInProjectDirs(string $file_path) : bool { return $this->project_files && $this->project_files->allows($file_path); } public function isInExtraDirs(string $file_path) : bool { return $this->extra_files && $this->extra_files->allows($file_path); } public function mustBeIgnored(string $file_path) : bool { return $this->project_files && $this->project_files->forbids($file_path); } public function trackTaintsInPath(string $file_path) : bool { return !$this->taint_analysis_ignored_files || $this->taint_analysis_ignored_files->allows($file_path); } public function getReportingLevelForIssue(\Psalm\Issue\CodeIssue $e) : string { $fqcn_parts = \explode('\\', \get_class($e)); $issue_type = \array_pop($fqcn_parts); $reporting_level = null; if ($e instanceof \Psalm\Issue\ClassIssue) { $reporting_level = $this->getReportingLevelForClass($issue_type, $e->fq_classlike_name); } elseif ($e instanceof \Psalm\Issue\MethodIssue) { $reporting_level = $this->getReportingLevelForMethod($issue_type, $e->method_id); } elseif ($e instanceof \Psalm\Issue\FunctionIssue) { $reporting_level = $this->getReportingLevelForFunction($issue_type, $e->function_id); } elseif ($e instanceof \Psalm\Issue\PropertyIssue) { $reporting_level = $this->getReportingLevelForProperty($issue_type, $e->property_id); } elseif ($e instanceof \Psalm\Issue\ArgumentIssue && $e->function_id) { $reporting_level = $this->getReportingLevelForArgument($issue_type, $e->function_id); } elseif ($e instanceof \Psalm\Issue\VariableIssue) { $reporting_level = $this->getReportingLevelForVariable($issue_type, $e->var_name); } if ($reporting_level === null) { $reporting_level = $this->getReportingLevelForFile($issue_type, $e->getFilePath()); } if (!$this->report_info && $reporting_level === self::REPORT_INFO) { $reporting_level = self::REPORT_SUPPRESS; } $parent_issue_type = self::getParentIssueType($issue_type); if ($parent_issue_type && $reporting_level === \Psalm\Config::REPORT_ERROR) { $parent_reporting_level = $this->getReportingLevelForFile($parent_issue_type, $e->getFilePath()); if ($parent_reporting_level !== $reporting_level) { return $parent_reporting_level; } } return $reporting_level; } /** * @psalm-pure */ public static function getParentIssueType(string $issue_type) : ?string { if ($issue_type === 'PossiblyUndefinedIntArrayOffset' || $issue_type === 'PossiblyUndefinedStringArrayOffset') { return 'PossiblyUndefinedArrayOffset'; } if ($issue_type === 'PossiblyNullReference') { return 'NullReference'; } if ($issue_type === 'PossiblyFalseReference') { return null; } if ($issue_type === 'PossiblyUndefinedArrayOffset') { return null; } if (\strpos($issue_type, 'Possibly') === 0) { $stripped_issue_type = \preg_replace('/^Possibly(False|Null)?/', '', $issue_type); if (\strpos($stripped_issue_type, 'Invalid') === \false && \strpos($stripped_issue_type, 'Un') !== 0) { $stripped_issue_type = 'Invalid' . $stripped_issue_type; } return $stripped_issue_type; } if (\preg_match('/^(False|Null)[A-Z]/', $issue_type) && !\strpos($issue_type, 'Reference')) { return \preg_replace('/^(False|Null)/', 'Invalid', $issue_type); } if ($issue_type === 'UndefinedInterfaceMethod') { return 'UndefinedMethod'; } if ($issue_type === 'UndefinedMagicPropertyFetch') { return 'UndefinedPropertyFetch'; } if ($issue_type === 'UndefinedMagicPropertyAssignment') { return 'UndefinedPropertyAssignment'; } if ($issue_type === 'UndefinedMagicMethod') { return 'UndefinedMethod'; } if ($issue_type === 'PossibleRawObjectIteration') { return 'RawObjectIteration'; } if ($issue_type === 'UninitializedProperty') { return 'PropertyNotSetInConstructor'; } if ($issue_type === 'InvalidDocblockParamName') { return 'InvalidDocblock'; } if ($issue_type === 'UnusedClosureParam') { return 'UnusedParam'; } if ($issue_type === 'StringIncrement') { return 'InvalidOperand'; } if ($issue_type === 'InvalidLiteralArgument') { return 'InvalidArgument'; } if ($issue_type === 'TraitMethodSignatureMismatch') { return 'MethodSignatureMismatch'; } if ($issue_type === 'ImplementedParamTypeMismatch') { return 'MoreSpecificImplementedParamType'; } if ($issue_type === 'UndefinedDocblockClass') { return 'UndefinedClass'; } return null; } public function getReportingLevelForFile(string $issue_type, string $file_path) : string { if (isset($this->issue_handlers[$issue_type])) { return $this->issue_handlers[$issue_type]->getReportingLevelForFile($file_path); } // this string is replaced by scoper for Phars, so be careful $issue_class = 'Psalm\\Issue\\' . $issue_type; if (!\class_exists($issue_class) || !\is_a($issue_class, \Psalm\Issue\CodeIssue::class, \true)) { return self::REPORT_ERROR; } /** @var int */ $issue_level = $issue_class::ERROR_LEVEL; if ($issue_level > 0 && $issue_level < $this->level) { return self::REPORT_INFO; } return self::REPORT_ERROR; } public function getReportingLevelForClass(string $issue_type, string $fq_classlike_name) : ?string { if (isset($this->issue_handlers[$issue_type])) { return $this->issue_handlers[$issue_type]->getReportingLevelForClass($fq_classlike_name); } return null; } public function getReportingLevelForMethod(string $issue_type, string $method_id) : ?string { if (isset($this->issue_handlers[$issue_type])) { return $this->issue_handlers[$issue_type]->getReportingLevelForMethod($method_id); } return null; } public function getReportingLevelForFunction(string $issue_type, string $function_id) : ?string { if (isset($this->issue_handlers[$issue_type])) { return $this->issue_handlers[$issue_type]->getReportingLevelForFunction($function_id); } return null; } public function getReportingLevelForArgument(string $issue_type, string $function_id) : ?string { if (isset($this->issue_handlers[$issue_type])) { return $this->issue_handlers[$issue_type]->getReportingLevelForArgument($function_id); } return null; } public function getReportingLevelForProperty(string $issue_type, string $property_id) : ?string { if (isset($this->issue_handlers[$issue_type])) { return $this->issue_handlers[$issue_type]->getReportingLevelForProperty($property_id); } return null; } public function getReportingLevelForVariable(string $issue_type, string $var_name) : ?string { if (isset($this->issue_handlers[$issue_type])) { return $this->issue_handlers[$issue_type]->getReportingLevelForVariable($var_name); } return null; } /** * @return array */ public function getProjectDirectories() : array { if (!$this->project_files) { return []; } return $this->project_files->getDirectories(); } /** * @return array */ public function getProjectFiles() : array { if (!$this->project_files) { return []; } return $this->project_files->getFiles(); } /** * @return array */ public function getExtraDirectories() : array { if (!$this->extra_files) { return []; } return $this->extra_files->getDirectories(); } public function reportTypeStatsForFile(string $file_path) : bool { return $this->project_files && $this->project_files->allows($file_path) && $this->project_files->reportTypeStats($file_path); } public function useStrictTypesForFile(string $file_path) : bool { return $this->project_files && $this->project_files->useStrictTypes($file_path); } /** * @return array */ public function getFileExtensions() : array { return $this->file_extensions; } /** * @return array> */ public function getFiletypeScanners() : array { return $this->filetype_scanners; } /** * @return array> */ public function getFiletypeAnalyzers() : array { return $this->filetype_analyzers; } /** * @return array */ public function getMockClasses() : array { return $this->mock_classes; } public function visitStubFiles(\Psalm\Codebase $codebase, ?\Psalm\Progress\Progress $progress = null) : void { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } $codebase->register_stub_files = \true; // note: don't realpath $generic_stubs_path, or phar version will fail $generic_stubs_path = \dirname(__DIR__, 2) . '/stubs/CoreGenericFunctions.phpstub'; if (!\file_exists($generic_stubs_path)) { throw new \UnexpectedValueException('Cannot locate core generic stubs'); } // note: don't realpath $generic_classes_path, or phar version will fail $generic_classes_path = \dirname(__DIR__, 2) . '/stubs/CoreGenericClasses.phpstub'; if (!\file_exists($generic_classes_path)) { throw new \UnexpectedValueException('Cannot locate core generic classes'); } // note: don't realpath $generic_classes_path, or phar version will fail $immutable_classes_path = \dirname(__DIR__, 2) . '/stubs/CoreImmutableClasses.phpstub'; if (!\file_exists($immutable_classes_path)) { throw new \UnexpectedValueException('Cannot locate core immutable classes'); } $core_generic_files = [$generic_stubs_path, $generic_classes_path, $immutable_classes_path]; if (\extension_loaded('ds')) { $ext_ds_path = \dirname(__DIR__, 2) . '/stubs/ext-ds.php'; if (!\file_exists($ext_ds_path)) { throw new \UnexpectedValueException('Cannot locate core generic classes'); } $core_generic_files[] = $ext_ds_path; } $stub_files = \array_merge($core_generic_files, $this->stub_files); $phpstorm_meta_path = $this->base_dir . \DIRECTORY_SEPARATOR . '.phpstorm.meta.php'; if ($this->use_phpstorm_meta_path) { if (\is_file($phpstorm_meta_path)) { $stub_files[] = $phpstorm_meta_path; } elseif (\is_dir($phpstorm_meta_path)) { $phpstorm_meta_path = \realpath($phpstorm_meta_path); foreach (\glob($phpstorm_meta_path . '/*.meta.php', \GLOB_NOSORT) as $glob) { if (\is_file($glob) && \realpath(\dirname($glob)) === $phpstorm_meta_path) { $stub_files[] = $glob; } } } } if ($this->load_xdebug_stub) { $xdebug_stub_path = \dirname(__DIR__, 2) . '/stubs/Xdebug.php'; if (!\file_exists($xdebug_stub_path)) { throw new \UnexpectedValueException('Cannot locate XDebug stub'); } $stub_files[] = $xdebug_stub_path; } foreach ($stub_files as $file_path) { $file_path = \str_replace(['/', '\\'], \DIRECTORY_SEPARATOR, $file_path); $codebase->scanner->addFileToDeepScan($file_path); } $progress->debug('Registering stub files' . "\n"); $codebase->scanFiles(); $progress->debug('Finished registering stub files' . "\n"); $codebase->register_stub_files = \false; } public function getCacheDirectory() : ?string { return $this->cache_directory; } public function getGlobalCacheDirectory() : ?string { return $this->global_cache_directory; } /** * @return array */ public function getPredefinedConstants() : array { return $this->predefined_constants; } public function collectPredefinedConstants() : void { $this->predefined_constants = \get_defined_constants(); } /** * @return array */ public function getPredefinedFunctions() : array { return $this->predefined_functions; } public function collectPredefinedFunctions() : void { $defined_functions = \get_defined_functions(); if (isset($defined_functions['user'])) { foreach ($defined_functions['user'] as $function_name) { $this->predefined_functions[$function_name] = \true; } } if (isset($defined_functions['internal'])) { foreach ($defined_functions['internal'] as $function_name) { $this->predefined_functions[$function_name] = \true; } } } public function setIncludeCollector(\Psalm\Internal\IncludeCollector $include_collector) : void { $this->include_collector = $include_collector; } /** * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess */ public function visitComposerAutoloadFiles(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, ?\Psalm\Progress\Progress $progress = null) : void { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } if (!$this->include_collector) { throw new \LogicException("IncludeCollector should be set at this point"); } $vendor_autoload_files_path = $this->base_dir . \DIRECTORY_SEPARATOR . 'vendor' . \DIRECTORY_SEPARATOR . 'composer' . \DIRECTORY_SEPARATOR . 'autoload_files.php'; if (\file_exists($vendor_autoload_files_path)) { $this->include_collector->runAndCollect(function () use($vendor_autoload_files_path) { /** * @psalm-suppress UnresolvableInclude * @var string[] */ return require $vendor_autoload_files_path; }); } $codebase = $project_analyzer->getCodebase(); $this->collectPredefinedFunctions(); if ($this->autoloader) { // somee classes that we think are missing may not actually be missing // as they might be autoloadable once we require the autoloader below $codebase->classlikes->forgetMissingClassLikes(); $this->include_collector->runAndCollect(function () { // do this in a separate method so scope does not leak /** @psalm-suppress UnresolvableInclude */ require $this->autoloader; }); } $this->collectPredefinedConstants(); $autoload_included_files = $this->include_collector->getFilteredIncludedFiles(); if ($autoload_included_files) { $codebase->register_autoload_files = \true; $progress->debug('Registering autoloaded files' . "\n"); foreach ($autoload_included_files as $file_path) { $file_path = \str_replace(['/', '\\'], \DIRECTORY_SEPARATOR, $file_path); $progress->debug(' ' . $file_path . "\n"); $codebase->scanner->addFileToDeepScan($file_path); } $codebase->scanner->scanFiles($codebase->classlikes); $progress->debug('Finished registering autoloaded files' . "\n"); $codebase->register_autoload_files = \false; } } /** * @return string|false */ public function getComposerFilePathForClassLike(string $fq_classlike_name) { if (!$this->composer_class_loader) { return \false; } return $this->composer_class_loader->findFile($fq_classlike_name); } public function getPotentialComposerFilePathForClassLike(string $class) : ?string { if (!$this->composer_class_loader) { return null; } /** @var array> */ $psr4_prefixes = $this->composer_class_loader->getPrefixesPsr4(); // PSR-4 lookup $logicalPathPsr4 = \strtr($class, '\\', \DIRECTORY_SEPARATOR) . '.php'; $candidate_path = null; $maxDepth = 0; $subPath = $class; while (\false !== ($lastPos = \strrpos($subPath, '\\'))) { $subPath = \substr($subPath, 0, $lastPos); $search = $subPath . '\\'; if (isset($psr4_prefixes[$search])) { $depth = \substr_count($search, '\\'); $pathEnd = \DIRECTORY_SEPARATOR . \substr($logicalPathPsr4, $lastPos + 1); foreach ($psr4_prefixes[$search] as $dir) { $dir = \realpath($dir); if ($dir && $depth > $maxDepth && $this->isInProjectDirs($dir . \DIRECTORY_SEPARATOR . 'testdummy.php')) { $maxDepth = $depth; $candidate_path = \realpath($dir) . $pathEnd; } } } } return $candidate_path; } public static function removeCacheDirectory(string $dir) : void { if (\is_dir($dir)) { $objects = \scandir($dir, \SCANDIR_SORT_NONE); if ($objects === \false) { throw new \UnexpectedValueException('Not expecting false here'); } foreach ($objects as $object) { if ($object !== '.' && $object !== '..') { if (\filetype($dir . '/' . $object) === 'dir') { self::removeCacheDirectory($dir . '/' . $object); } else { \unlink($dir . '/' . $object); } } } \reset($objects); \rmdir($dir); } } public function setServerMode() : void { $this->cache_directory .= '-s'; } public function addStubFile(string $stub_file) : void { $this->stub_files[$stub_file] = $stub_file; } public function hasStubFile(string $stub_file) : bool { return isset($this->stub_files[$stub_file]); } /** * @return array */ public function getStubFiles() : array { return $this->stub_files; } public function getPhpVersion() : ?string { if (isset($this->configured_php_version)) { return $this->configured_php_version; } return $this->getPHPVersionFromComposerJson(); } private function setBooleanAttribute(string $name, bool $value) : void { $this->{$name} = $value; } /** * @psalm-suppress MixedAssignment * @psalm-suppress MixedArrayAccess */ private function getPHPVersionFromComposerJson() : ?string { $composer_json_path = \Psalm\Internal\Composer::getJsonFilePath($this->base_dir); if (\file_exists($composer_json_path)) { if (!($composer_json = \json_decode(\file_get_contents($composer_json_path), \true))) { throw new \UnexpectedValueException('Invalid composer.json at ' . $composer_json_path); } $php_version = $composer_json['require']['php'] ?? null; if (\is_string($php_version)) { foreach (['5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] as $candidate) { if (\_HumbugBoxd02f763d3c56\Composer\Semver\Semver::satisfies($candidate, $php_version)) { return $candidate; } } } } return null; } /** * @param class-string $class */ public function addUniversalObjectCrate(string $class) : void { $this->universal_object_crates[] = $class; } /** * @return array */ public function getUniversalObjectCrates() : array { return \array_map('strtolower', $this->universal_object_crates); } } dupe_key = $dupe_key; } } var_name = \strtolower($var_name); } } * @readonly */ public $journey = []; /** * @param list $journey */ public function __construct(string $message, \Psalm\CodeLocation $code_location, array $journey, string $journey_text) { parent::__construct($message, $code_location); $this->journey = $journey; $this->journey_text = $journey_text; } /** * @return list */ public function getTaintTrace() : array { $nodes = []; foreach ($this->journey as ['location' => $location, 'label' => $label, 'entry_path_type' => $path_type]) { if ($location) { $nodes[] = self::nodeToDataFlowNodeData($location, $label, $path_type); } else { $nodes[] = ['label' => $label, 'entry_path_type' => $path_type]; } } return $nodes; } private static function nodeToDataFlowNodeData(\Psalm\CodeLocation $location, string $label, string $entry_path_type) : \Psalm\Internal\Analyzer\DataFlowNodeData { $selection_bounds = $location->getSelectionBounds(); $snippet_bounds = $location->getSnippetBounds(); return new \Psalm\Internal\Analyzer\DataFlowNodeData($label, $entry_path_type, null, $location->getLineNumber(), $location->getEndLineNumber(), $location->file_name, $location->file_path, $location->getSnippet(), $location->getSelectedText(), $selection_bounds[0], $selection_bounds[1], $snippet_bounds[0], $snippet_bounds[1], $location->getColumn(), $location->getEndColumn()); } public function getJourneyMessage() : string { return $this->message . ' in path: ' . $this->journey_text; } } property_id = $property_id; } } dupe_key = $dupe_key; } } method_id = \strtolower($method_id); } } code_location = $code_location; $this->message = $message; } /** * @deprecated * @psalm-suppress PossiblyUnusedMethod */ public function getLocation() : \Psalm\CodeLocation { return $this->code_location; } public function getShortLocationWithPrevious() : string { $previous_text = ''; if ($this->code_location->previous_location) { $previous_location = $this->code_location->previous_location; $previous_text = ' from ' . $previous_location->file_name . ':' . $previous_location->getLineNumber(); } return $this->code_location->file_name . ':' . $this->code_location->getLineNumber() . $previous_text; } public function getShortLocation() : string { return $this->code_location->file_name . ':' . $this->code_location->getLineNumber(); } public function getFilePath() : string { return $this->code_location->file_path; } /** * @deprecated * @psalm-suppress PossiblyUnusedMethod for convenience */ public function getFileName() : string { return $this->code_location->file_name; } /** * @deprecated * @psalm-suppress PossiblyUnusedMethod */ public function getMessage() : string { return $this->message; } public function toIssueData(string $severity = \Psalm\Config::REPORT_ERROR) : \Psalm\Internal\Analyzer\IssueData { $location = $this->code_location; $selection_bounds = $location->getSelectionBounds(); $snippet_bounds = $location->getSnippetBounds(); $fqcn_parts = \explode('\\', \get_called_class()); $issue_type = \array_pop($fqcn_parts); return new \Psalm\Internal\Analyzer\IssueData($severity, $location->getLineNumber(), $location->getEndLineNumber(), $issue_type, $this->message, $location->file_name, $location->file_path, $location->getSnippet(), $location->getSelectedText(), $selection_bounds[0], $selection_bounds[1], $snippet_bounds[0], $snippet_bounds[1], $location->getColumn(), $location->getEndColumn(), (int) static::SHORTCODE, (int) static::ERROR_LEVEL, $this instanceof \Psalm\Issue\TaintedInput ? $this->getTaintTrace() : null, $this->dupe_key); } } dupe_key = $dupe_key; } } dupe_key = $dupe_key; } } dupe_key = $dupe_key; } } dupe_key = $property_id; } } function_id = \strtolower($function_id); } } function_id = $function_id ? \strtolower($function_id) : null; } } fq_classlike_name = $fq_classlike_name; } } dupe_key = $dupe_key; } } file_start = (int) $error->getAttributes()['startFilePos']; /** @psalm-suppress PossiblyUndefinedStringArrayOffset */ $this->file_end = (int) $error->getAttributes()['endFilePos']; $this->raw_file_start = $this->file_start; $this->raw_file_end = $this->file_end; $this->file_path = $file_path; $this->file_name = $file_name; $this->single_line = \false; $this->preview_start = $this->file_start; $this->raw_line_number = \substr_count(\substr($file_contents, 0, $this->file_start), "\n") + 1; } } file_start = $file_start; // matches how CodeLocation works $this->file_end = $file_end - 1; $this->raw_file_start = $file_start; $this->raw_file_end = $file_end; $this->raw_line_number = $line_number; $this->file_path = $file_source->getFilePath(); $this->file_name = $file_source->getFileName(); $this->single_line = \false; $this->preview_start = $this->file_start; } } file_start = $file_start; $this->file_end = $file_end; $this->raw_file_start = $this->file_start; $this->raw_file_end = $this->file_end; $this->file_path = $file_path; $this->file_name = $file_name; $this->single_line = \false; $this->preview_start = $this->file_start; $this->raw_line_number = \substr_count(\substr($file_contents, 0, $this->file_start), "\n") + 1; } } > $issues */ public static function afterAnalysis(\Psalm\Codebase $codebase, array $issues, array $build_info, ?\Psalm\SourceControl\SourceControlInfo $source_control_info = null) : void { if (!\function_exists('curl_init')) { \fwrite(\STDERR, 'No curl found, cannot send data to ' . $codebase->config->shepherd_host . \PHP_EOL); return; } $source_control_data = $source_control_info ? $source_control_info->toArray() : []; if (!$source_control_data && isset($build_info['git']) && \is_array($build_info['git'])) { $source_control_data = $build_info['git']; } unset($build_info['git']); if ($build_info) { $normalized_data = $issues === [] ? [] : \array_filter(\array_merge(...\array_values($issues)), static function (\Psalm\Internal\Analyzer\IssueData $i) : bool { return $i->severity === 'error'; }); $data = ['build' => $build_info, 'git' => $source_control_data, 'issues' => $normalized_data, 'coverage' => $codebase->analyzer->getTotalTypeCoverage($codebase)]; $payload = \json_encode($data); $base_address = $codebase->config->shepherd_host; if (\parse_url($base_address, \PHP_URL_SCHEME) === null) { $base_address = 'https://' . $base_address; } // Prepare new cURL resource $ch = \curl_init($base_address . '/hooks/psalm'); \curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true); \curl_setopt($ch, \CURLINFO_HEADER_OUT, \true); \curl_setopt($ch, \CURLOPT_POST, \true); \curl_setopt($ch, \CURLOPT_POSTFIELDS, $payload); // Set HTTP Header for POST request \curl_setopt($ch, \CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Content-Length: ' . \strlen($payload)]); // Submit the POST request $return = \curl_exec($ch); if ($return !== '') { \fwrite(\STDERR, 'Error with Psalm Shepherd:' . \PHP_EOL); if ($return === \false) { \fwrite(\STDERR, self::getCurlErrorMessage($ch) . \PHP_EOL); } else { echo $return . \PHP_EOL; echo 'Git args: ' . \var_export($source_control_data, \true) . \PHP_EOL; echo 'CI args: ' . \var_export($build_info, \true) . \PHP_EOL; } } else { $short_address = \str_replace('https://', '', $base_address); \fwrite(\STDERR, "🐑 results sent to {$short_address} 🐑" . \PHP_EOL); } // Close cURL session handle \curl_close($ch); } } /** * @param mixed $ch * * @psalm-pure */ public static function getCurlErrorMessage($ch) : string { /** * @psalm-suppress MixedArgument * @var array */ $curl_info = \curl_getinfo($ch); if (isset($curl_info['ssl_verify_result']) && $curl_info['ssl_verify_result'] !== 0) { switch ($curl_info['ssl_verify_result']) { case 2: return 'unable to get issuer certificate'; case 3: return 'unable to get certificate CRL'; case 4: return 'unable to decrypt certificate’s signature'; case 5: return 'unable to decrypt CRL’s signature'; case 6: return 'unable to decode issuer public key'; case 7: return 'certificate signature failure'; case 8: return 'CRL signature failure'; case 9: return 'certificate is not yet valid'; case 10: return 'certificate has expired'; case 11: return 'CRL is not yet valid'; case 12: return 'CRL has expired'; case 13: return 'format error in certificate’s notBefore field'; case 14: return 'format error in certificate’s notAfter field'; case 15: return 'format error in CRL’s lastUpdate field'; case 16: return 'format error in CRL’s nextUpdate field'; case 17: return 'out of memory'; case 18: return 'self signed certificate'; case 19: return 'self signed certificate in certificate chain'; case 20: return 'unable to get local issuer certificate'; case 21: return 'unable to verify the first certificate'; case 22: return 'certificate chain too long'; case 23: return 'certificate revoked'; case 24: return 'invalid CA certificate'; case 25: return 'path length constraint exceeded'; case 26: return 'unsupported certificate purpose'; case 27: return 'certificate not trusted'; case 28: return 'certificate rejected'; case 29: return 'subject issuer mismatch'; case 30: return 'authority and subject key identifier mismatch'; case 31: return 'authority and issuer serial number mismatch'; case 32: return 'key usage does not include certificate signing'; case 50: return 'application verification failure'; } return ''; } /** * @psalm-suppress MixedArgument */ return \var_export(\curl_getinfo($ch), \true); } } */ public static function getClassLikeNames() : array; public static function isMethodVisible(\Psalm\StatementsSource $source, string $fq_classlike_name, string $method_name_lowercase, \Psalm\Context $context, ?\Psalm\CodeLocation $code_location = null) : ?bool; } */ public static function getClassLikeNames() : array; /** * Use this hook for informing whether or not a property exists on a given object. If you know the property does * not exist, return false. If you aren't sure if it exists or not, return null and the default analysis will * continue to determine if the property actually exists. * */ public static function doesPropertyExist(string $fq_classlike_name, string $property_name, bool $read_mode, ?\Psalm\StatementsSource $source = null, ?\Psalm\Context $context = null, ?\Psalm\CodeLocation $code_location = null) : ?bool; } */ public static function getFunctionIds() : array; /** * @param array $call_args * * @return ?array */ public static function getFunctionParams(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, ?\Psalm\Context $context = null, ?\Psalm\CodeLocation $code_location = null) : ?array; } */ public static function getClassLikeNames() : array; /** * Use this hook for informing whether or not a method exists on a given object. If you know the method does * not exist, return false. If you aren't sure if it exists or not, return null and the default analysis will * continue to determine if the method actually exists. */ public static function doesMethodExist(string $fq_classlike_name, string $method_name_lowercase, ?\Psalm\StatementsSource $source = null, ?\Psalm\CodeLocation $code_location = null) : ?bool; } */ public static function getClassLikeNames() : array; /** * Use this hook for providing custom return type logic. If this plugin does not know what a method should return * but another plugin may be able to determine the type, return null. Otherwise return a mixed union type if * something should be returned, but can't be more specific. * * @param array $call_args * @param ?array $template_type_parameters * @param lowercase-string $method_name_lowercase * @param lowercase-string $called_method_name_lowercase */ public static function getMethodReturnType(\Psalm\StatementsSource $source, string $fq_classlike_name, string $method_name_lowercase, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location, ?array $template_type_parameters = null, ?string $called_fq_classlike_name = null, ?string $called_method_name_lowercase = null) : ?\Psalm\Type\Union; } */ public static function getClassLikeNames() : array; /** * @param array $call_args * * @return ?array */ public static function getMethodParams(string $fq_classlike_name, string $method_name_lowercase, ?array $call_args = null, ?\Psalm\StatementsSource $statements_source = null, ?\Psalm\Context $context = null, ?\Psalm\CodeLocation $code_location = null) : ?array; } > $issues */ public static function afterAnalysis(\Psalm\Codebase $codebase, array $issues, array $build_info, ?\Psalm\SourceControl\SourceControlInfo $source_control_info = null) : void; } */ public static function getClassLikeNames() : array; public static function isPropertyVisible(\Psalm\StatementsSource $source, string $fq_classlike_name, string $property_name, bool $read_mode, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : ?bool; } */ public static function getClassLikeNames() : array; /** * @param array $call_args * */ public static function getPropertyType(string $fq_classlike_name, string $property_name, bool $read_mode, ?\Psalm\StatementsSource $source = null, ?\Psalm\Context $context = null) : ?\Psalm\Type\Union; } */ public static function getFunctionIds() : array; /** * Use this hook for informing whether or not a global function exists. If you know the function does * not exist, return false. If you aren't sure if it exists or not, return null and the default analysis * will continue to determine if the function actually exists. * */ public static function doesFunctionExist(\Psalm\StatementsSource $statements_source, string $function_id) : ?bool; } */ public static function getFunctionIds() : array; /** * Use this hook for providing custom return type logic. If this plugin does not know what a function should * return but another plugin may be able to determine the type, return null. Otherwise return a mixed union type * if something should be returned, but can't be more specific. * * @param array $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : ?\Psalm\Type\Union; } > $template_type_map * @param array $type_aliases */ public static function create(string $value, ?array $php_version = null, array $template_type_map = [], array $type_aliases = []) : \Psalm\Type\Atomic { switch ($value) { case 'int': return new \Psalm\Type\Atomic\TInt(); case 'float': return new \Psalm\Type\Atomic\TFloat(); case 'string': return new \Psalm\Type\Atomic\TString(); case 'bool': return new \Psalm\Type\Atomic\TBool(); case 'void': if ($php_version === null || $php_version[0] > 7 || $php_version[0] === 7 && $php_version[1] >= 1) { return new \Psalm\Type\Atomic\TVoid(); } break; case 'array-key': return new \Psalm\Type\Atomic\TArrayKey(); case 'iterable': if ($php_version === null || $php_version[0] > 7 || $php_version[0] === 7 && $php_version[1] >= 1) { return new \Psalm\Type\Atomic\TIterable(); } break; case 'never-return': case 'never-returns': case 'no-return': return new \Psalm\Type\Atomic\TNever(); case 'object': if ($php_version === null || $php_version[0] > 7 || $php_version[0] === 7 && $php_version[1] >= 2) { return new \Psalm\Type\Atomic\TObject(); } break; case 'callable': return new \Psalm\Type\Atomic\TCallable(); case 'pure-callable': $type = new \Psalm\Type\Atomic\TCallable(); $type->is_pure = \true; return $type; case 'array': case 'associative-array': return new \Psalm\Type\Atomic\TArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArrayKey()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TMixed()])]); case 'non-empty-array': return new \Psalm\Type\Atomic\TNonEmptyArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArrayKey()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TMixed()])]); case 'callable-array': return new \Psalm\Type\Atomic\TCallableArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArrayKey()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TMixed()])]); case 'list': return new \Psalm\Type\Atomic\TList(\Psalm\Type::getMixed()); case 'non-empty-list': return new \Psalm\Type\Atomic\TNonEmptyList(\Psalm\Type::getMixed()); case 'non-empty-string': return new \Psalm\Type\Atomic\TNonEmptyString(); case 'lowercase-string': return new \Psalm\Type\Atomic\TLowercaseString(); case 'non-empty-lowercase-string': return new \Psalm\Type\Atomic\TNonEmptyLowercaseString(); case 'resource': return $php_version !== null ? new \Psalm\Type\Atomic\TNamedObject($value) : new \Psalm\Type\Atomic\TResource(); case 'resource (closed)': case 'closed-resource': return new \Psalm\Type\Atomic\TClosedResource(); case 'positive-int': return new \Psalm\Type\Atomic\TPositiveInt(); case 'numeric': return $php_version !== null ? new \Psalm\Type\Atomic\TNamedObject($value) : new \Psalm\Type\Atomic\TNumeric(); case 'true': return $php_version !== null ? new \Psalm\Type\Atomic\TNamedObject($value) : new \Psalm\Type\Atomic\TTrue(); case 'false': if ($php_version === null || $php_version[0] >= 8) { return new \Psalm\Type\Atomic\TFalse(); } return new \Psalm\Type\Atomic\TNamedObject($value); case 'empty': return $php_version !== null ? new \Psalm\Type\Atomic\TNamedObject($value) : new \Psalm\Type\Atomic\TEmpty(); case 'scalar': return $php_version !== null ? new \Psalm\Type\Atomic\TNamedObject($value) : new \Psalm\Type\Atomic\TScalar(); case 'null': if ($php_version === null || $php_version[0] >= 8) { return new \Psalm\Type\Atomic\TNull(); } return new \Psalm\Type\Atomic\TNamedObject($value); case 'mixed': if ($php_version === null || $php_version[0] >= 8) { return new \Psalm\Type\Atomic\TMixed(); } return new \Psalm\Type\Atomic\TNamedObject($value); case 'callable-object': return new \Psalm\Type\Atomic\TCallableObject(); case 'class-string': case 'interface-string': return new \Psalm\Type\Atomic\TClassString(); case 'trait-string': return new \Psalm\Type\Atomic\TTraitString(); case 'callable-string': return new \Psalm\Type\Atomic\TCallableString(); case 'numeric-string': return new \Psalm\Type\Atomic\TNumericString(); case 'html-escaped-string': return new \Psalm\Type\Atomic\THtmlEscapedString(); case 'false-y': return new \Psalm\Type\Atomic\TAssertionFalsy(); case '$this': return new \Psalm\Type\Atomic\TNamedObject('static'); } if (\strpos($value, '-') && \substr($value, 0, 4) !== 'OCI-') { throw new \Psalm\Exception\TypeParseTreeException('Unrecognized type ' . $value); } if (\is_numeric($value[0])) { throw new \Psalm\Exception\TypeParseTreeException('First character of type cannot be numeric'); } if (isset($template_type_map[$value])) { $first_class = \array_keys($template_type_map[$value])[0]; return new \Psalm\Type\Atomic\TTemplateParam($value, $template_type_map[$value][$first_class][0], $first_class); } if (isset($type_aliases[$value])) { $type_alias = $type_aliases[$value]; if ($type_alias instanceof \Psalm\Internal\Type\TypeAlias\LinkableTypeAlias) { return new \Psalm\Type\Atomic\TTypeAlias($type_alias->declaring_fq_classlike_name, $type_alias->alias_name); } throw new \UnexpectedValueException('This should never happen'); } return new \Psalm\Type\Atomic\TNamedObject($value); } public abstract function getKey(bool $include_extra = \true) : string; public function isNumericType() : bool { return $this instanceof \Psalm\Type\Atomic\TInt || $this instanceof \Psalm\Type\Atomic\TFloat || $this instanceof \Psalm\Type\Atomic\TNumericString || $this instanceof \Psalm\Type\Atomic\TNumeric || $this instanceof \Psalm\Type\Atomic\TLiteralString && \is_numeric($this->value); } public function isObjectType() : bool { return $this instanceof \Psalm\Type\Atomic\TObject || $this instanceof \Psalm\Type\Atomic\TNamedObject || $this instanceof \Psalm\Type\Atomic\TTemplateParam && $this->as->hasObjectType(); } public function isNamedObjectType() : bool { return $this instanceof \Psalm\Type\Atomic\TNamedObject || $this instanceof \Psalm\Type\Atomic\TTemplateParam && ($this->as->hasNamedObjectType() || \array_filter($this->extra_types ?: [], function ($extra_type) { return $extra_type->isNamedObjectType(); })); } public function isCallableType() : bool { return $this instanceof \Psalm\Type\Atomic\TCallable || $this instanceof \Psalm\Type\Atomic\TCallableObject || $this instanceof \Psalm\Type\Atomic\TCallableString || $this instanceof \Psalm\Type\Atomic\TCallableArray || $this instanceof \Psalm\Type\Atomic\TCallableList || $this instanceof \Psalm\Type\Atomic\TCallableKeyedArray; } public function isIterable(\Psalm\Codebase $codebase) : bool { return $this instanceof \Psalm\Type\Atomic\TIterable || $this->hasTraversableInterface($codebase) || $this instanceof \Psalm\Type\Atomic\TArray || $this instanceof \Psalm\Type\Atomic\TKeyedArray || $this instanceof \Psalm\Type\Atomic\TList; } public function isCountable(\Psalm\Codebase $codebase) : bool { return $this->hasCountableInterface($codebase) || $this instanceof \Psalm\Type\Atomic\TArray || $this instanceof \Psalm\Type\Atomic\TKeyedArray || $this instanceof \Psalm\Type\Atomic\TList; } public function hasTraversableInterface(\Psalm\Codebase $codebase) : bool { return $this instanceof \Psalm\Type\Atomic\TNamedObject && (\strtolower($this->value) === 'traversable' || $codebase->classOrInterfaceExists($this->value) && ($codebase->classExtendsOrImplements($this->value, 'Traversable') || $codebase->interfaceExtends($this->value, 'Traversable')) || $this->extra_types && \array_filter($this->extra_types, function (\Psalm\Type\Atomic $a) use($codebase) : bool { return $a->hasTraversableInterface($codebase); })); } public function hasCountableInterface(\Psalm\Codebase $codebase) : bool { return $this instanceof \Psalm\Type\Atomic\TNamedObject && (\strtolower($this->value) === 'countable' || $codebase->classOrInterfaceExists($this->value) && ($codebase->classExtendsOrImplements($this->value, 'Countable') || $codebase->interfaceExtends($this->value, 'Countable')) || $this->extra_types && \array_filter($this->extra_types, function (\Psalm\Type\Atomic $a) use($codebase) : bool { return $a->hasCountableInterface($codebase); })); } public function isArrayAccessibleWithStringKey(\Psalm\Codebase $codebase) : bool { return $this instanceof \Psalm\Type\Atomic\TArray || $this instanceof \Psalm\Type\Atomic\TKeyedArray || $this instanceof \Psalm\Type\Atomic\TList || $this instanceof \Psalm\Type\Atomic\TClassStringMap || $this->hasArrayAccessInterface($codebase) || $this instanceof \Psalm\Type\Atomic\TNamedObject && $this->value === 'SimpleXMLElement'; } public function isArrayAccessibleWithIntOrStringKey(\Psalm\Codebase $codebase) : bool { return $this instanceof \Psalm\Type\Atomic\TString || $this->isArrayAccessibleWithStringKey($codebase); } public function hasArrayAccessInterface(\Psalm\Codebase $codebase) : bool { return $this instanceof \Psalm\Type\Atomic\TNamedObject && (\strtolower($this->value) === 'arrayaccess' || $codebase->classOrInterfaceExists($this->value) && ($codebase->classExtendsOrImplements($this->value, 'ArrayAccess') || $codebase->interfaceExtends($this->value, 'ArrayAccess')) || $this->extra_types && \array_filter($this->extra_types, function (\Psalm\Type\Atomic $a) use($codebase) : bool { return $a->hasArrayAccessInterface($codebase); })); } public function getChildNodes() : array { return []; } public function replaceClassLike(string $old, string $new) : void { if ($this instanceof \Psalm\Type\Atomic\TNamedObject) { if (\strtolower($this->value) === $old) { $this->value = $new; } } if ($this instanceof \Psalm\Type\Atomic\TNamedObject || $this instanceof \Psalm\Type\Atomic\TIterable || $this instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($this->extra_types) { foreach ($this->extra_types as $extra_type) { $extra_type->replaceClassLike($old, $new); } } } if ($this instanceof \Psalm\Type\Atomic\TScalarClassConstant) { if (\strtolower($this->fq_classlike_name) === $old) { $this->fq_classlike_name = $new; } } if ($this instanceof \Psalm\Type\Atomic\TClassString && $this->as !== 'object') { if (\strtolower($this->as) === $old) { $this->as = $new; } } if ($this instanceof \Psalm\Type\Atomic\TTemplateParam) { $this->as->replaceClassLike($old, $new); } if ($this instanceof \Psalm\Type\Atomic\TLiteralClassString) { if (\strtolower($this->value) === $old) { $this->value = $new; } } if ($this instanceof \Psalm\Type\Atomic\TArray || $this instanceof \Psalm\Type\Atomic\TGenericObject || $this instanceof \Psalm\Type\Atomic\TIterable) { foreach ($this->type_params as $type_param) { $type_param->replaceClassLike($old, $new); } } if ($this instanceof \Psalm\Type\Atomic\TKeyedArray) { foreach ($this->properties as $property_type) { $property_type->replaceClassLike($old, $new); } } if ($this instanceof \Psalm\Type\Atomic\TClosure || $this instanceof \Psalm\Type\Atomic\TCallable) { if ($this->params) { foreach ($this->params as $param) { if ($param->type) { $param->type->replaceClassLike($old, $new); } } } if ($this->return_type) { $this->return_type->replaceClassLike($old, $new); } } } public function __toString() : string { return ''; } public function __clone() { if ($this instanceof \Psalm\Type\Atomic\TNamedObject || $this instanceof \Psalm\Type\Atomic\TTemplateParam || $this instanceof \Psalm\Type\Atomic\TIterable || $this instanceof \Psalm\Type\Atomic\TObjectWithProperties) { if ($this->extra_types) { foreach ($this->extra_types as &$type) { $type = clone $type; } } } if ($this instanceof \Psalm\Type\Atomic\TTemplateParam) { $this->as = clone $this->as; } } public function getId(bool $nested = \false) : string { return $this->__toString(); } public function getAssertionString() : string { return $this->getId(); } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return $this->getKey(); } /** * @param array $aliased_classes */ public abstract function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string; public abstract function canBeFullyExpressedInPhp() : bool; public function replaceTemplateTypesWithStandins(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null, \Psalm\Type\Atomic $input_type = null, ?int $input_arg_offset = null, ?string $calling_class = null, ?string $calling_function = null, bool $replace = \true, bool $add_upper_bound = \false, int $depth = 0) : self { return $this; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { // do nothing } public function equals(\Psalm\Type\Atomic $other_type) : bool { return \get_class($other_type) === \get_class($this); } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version >= 7 ? 'int' : null; } } fq_classlike_name = $fq_classlike_name; $this->const_name = $const_name; } public function getKey(bool $include_extra = \true) : string { return 'key-of<' . $this->fq_classlike_name . '::' . $this->const_name . '>'; } public function __toString() : string { return 'key-of<' . $this->fq_classlike_name . '::' . $this->const_name . '>'; } public function getId(bool $nested = \false) : string { return $this->getKey(); } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($this->fq_classlike_name === 'static') { return 'key-ofconst_name . '>'; } if ($this->fq_classlike_name === $this_class) { return 'key-ofconst_name . '>'; } if ($namespace && \stripos($this->fq_classlike_name, $namespace . '\\') === 0) { return 'key-of<' . \preg_replace('/^' . \preg_quote($namespace . '\\') . '/i', '', $this->fq_classlike_name) . '::' . $this->const_name . '>'; } if (!$namespace && \strpos($this->fq_classlike_name, '\\') === \false) { return 'key-of<' . $this->fq_classlike_name . '::' . $this->const_name . '>'; } if (isset($aliased_classes[\strtolower($this->fq_classlike_name)])) { return 'key-of<' . $aliased_classes[\strtolower($this->fq_classlike_name)] . '::' . $this->const_name . '>'; } return 'key-of<\\' . $this->fq_classlike_name . '::' . $this->const_name . '>'; } public function getAssertionString() : string { return 'mixed'; } } type_param = $type_param; } public function __toString() : string { /** @psalm-suppress MixedOperand */ return static::KEY . '<' . $this->type_param . '>'; } public function getId(bool $nested = \false) : string { /** @psalm-suppress MixedOperand */ return static::KEY . '<' . $this->type_param->getId() . '>'; } public function __clone() { $this->type_param = clone $this->type_param; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($use_phpdoc_format) { return (new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $this->type_param]))->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format); } /** @psalm-suppress MixedOperand */ return static::KEY . '<' . $this->type_param->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format) . '>'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : string { return 'array'; } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getKey(bool $include_extra = \true) : string { return 'array'; } public function replaceTemplateTypesWithStandins(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null, ?\Psalm\Type\Atomic $input_type = null, ?int $input_arg_offset = null, ?string $calling_class = null, ?string $calling_function = null, bool $replace = \true, bool $add_upper_bound = \false, int $depth = 0) : \Psalm\Type\Atomic { $list = clone $this; foreach ([\Psalm\Type::getInt(), $list->type_param] as $offset => $type_param) { $input_type_param = null; if (($input_type instanceof \Psalm\Type\Atomic\TGenericObject || $input_type instanceof \Psalm\Type\Atomic\TIterable || $input_type instanceof \Psalm\Type\Atomic\TArray) && isset($input_type->type_params[$offset])) { $input_type_param = clone $input_type->type_params[$offset]; } elseif ($input_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($offset === 0) { $input_type_param = $input_type->getGenericKeyType(); } else { $input_type_param = $input_type->getGenericValueType(); } } elseif ($input_type instanceof \Psalm\Type\Atomic\TList) { if ($offset === 0) { continue; } $input_type_param = clone $input_type->type_param; } $type_param = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($type_param, $template_result, $codebase, $statements_analyzer, $input_type_param, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth + 1); if ($offset === 1) { $list->type_param = $type_param; } } return $list; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { $this->type_param->replaceTemplateTypesWithArgTypes($template_result, $codebase); } public function equals(\Psalm\Type\Atomic $other_type) : bool { if (\get_class($other_type) !== static::class) { return \false; } if (!$this->type_param->equals($other_type->type_param)) { return \false; } return \true; } public function getAssertionString() : string { return 'list'; } public function getChildNodes() : array { return [$this->type_param]; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : string { return 'callable'; } public function canBeFullyExpressedInPhp() : bool { return $this->params === null && $this->return_type === null; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version > 7 || $php_major_version === 7 && $php_minor_version >= 1 ? $this->getKey() : null; } public function canBeFullyExpressedInPhp() : bool { return \true; } } |null */ public $extra_types; /** @var string */ public $declaring_fq_classlike_name; /** @var string */ public $alias_name; public function __construct(string $declaring_fq_classlike_name, string $alias_name) { $this->declaring_fq_classlike_name = $declaring_fq_classlike_name; $this->alias_name = $alias_name; } public function getKey(bool $include_extra = \true) : string { return 'type-alias(' . $this->declaring_fq_classlike_name . '::' . $this->alias_name . ')'; } public function __toString() : string { if ($this->extra_types) { return $this->getKey() . '&' . \implode('&', \array_map('strval', $this->extra_types)); } return $this->getKey(); } public function getId(bool $nested = \false) : string { if ($this->extra_types) { return $this->getKey() . '&' . \implode('&', \array_map(function ($type) { return $type->getId(\true); }, $this->extra_types)); } return $this->getKey(); } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return $this->getKey(); } public function getAssertionString() : string { return 'mixed'; } } value = $value; } public function __toString() : string { return 'class-string'; } public function getKey(bool $include_extra = \true) : string { return 'class-string(' . $this->value . ')'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : string { return 'string'; } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getId(bool $nested = \false) : string { return $this->value . '::class'; } public function getAssertionString() : string { return $this->getKey(); } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($this->value === 'static') { return 'static::class'; } if ($this->value === $this_class) { return 'self::class'; } if ($namespace && \stripos($this->value, $namespace . '\\') === 0) { return \preg_replace('/^' . \preg_quote($namespace . '\\') . '/i', '', $this->value) . '::class'; } if (!$namespace && \strpos($this->value, '\\') === \false) { return $this->value . '::class'; } if (isset($aliased_classes[\strtolower($this->value)])) { return $aliased_classes[\strtolower($this->value)] . '::class'; } return '\\' . $this->value . '::class'; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } } from_loop_isset = $from_loop_isset; } public function __toString() : string { return 'mixed'; } public function getKey(bool $include_extra = \true) : string { return 'mixed'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getAssertionString() : string { return 'mixed'; } } $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return $use_phpdoc_format ? 'int' : 'positive-int'; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version > 7 || $php_major_version === 7 && $php_minor_version >= 2 ? 'object' : null; } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getAssertionString() : string { return 'object'; } } param_name = $param_name; $this->as = $as; $this->as_type = $as_type; $this->defining_class = $defining_class; } public function getKey(bool $include_extra = \true) : string { return 'class-string<' . $this->param_name . '>'; } public function __toString() : string { return 'class-string<' . $this->param_name . '>'; } public function getId(bool $nested = \false) : string { return 'class-string<' . $this->param_name . ':' . $this->defining_class . ' as ' . $this->as . '>'; } public function getAssertionString() : string { return 'class-string<' . $this->param_name . '>'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return 'string'; } public function canBeFullyExpressedInPhp() : bool { return \false; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return $this->param_name . '::class'; } public function getChildNodes() : array { return $this->as_type ? [$this->as_type] : []; } } */ public $type_params; public function __toString() : string { $s = ''; foreach ($this->type_params as $type_param) { $s .= $type_param . ', '; } $extra_types = ''; if ($this instanceof \Psalm\Type\Atomic\TNamedObject && $this->extra_types) { $extra_types = '&' . \implode('&', $this->extra_types); } return $this->value . '<' . \substr($s, 0, -2) . '>' . $extra_types; } public function getId(bool $nested = \false) : string { $s = ''; foreach ($this->type_params as $type_param) { $s .= $type_param->getId() . ', '; } $extra_types = ''; if ($this instanceof \Psalm\Type\Atomic\TNamedObject && $this->extra_types) { $extra_types = '&' . \implode('&', \array_map(function ($type) { return $type->getId(\true); }, $this->extra_types)); } return $this->value . '<' . \substr($s, 0, -2) . '>' . $extra_types; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { $base_value = $this instanceof \Psalm\Type\Atomic\TNamedObject ? parent::toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format) : $this->value; if ($base_value === 'non-empty-array') { $base_value = 'array'; } if ($use_phpdoc_format) { if ($this instanceof \Psalm\Type\Atomic\TNamedObject || $this instanceof \Psalm\Type\Atomic\TIterable) { return $base_value; } $value_type = $this->type_params[1]; if ($value_type->isMixed() || $value_type->isEmpty()) { return $base_value; } $value_type_string = $value_type->toNamespacedString($namespace, $aliased_classes, $this_class, \true); if (!$value_type->isSingle()) { return '(' . $value_type_string . ')[]'; } return $value_type_string . '[]'; } $extra_types = ''; if ($this instanceof \Psalm\Type\Atomic\TNamedObject && $this->extra_types) { $extra_types = '&' . \implode('&', \array_map( /** * @return string */ function (\Psalm\Type\Atomic $extra_type) use($namespace, $aliased_classes, $this_class) : string { return $extra_type->toNamespacedString($namespace, $aliased_classes, $this_class, \false); }, $this->extra_types )); } return $base_value . '<' . \implode(', ', \array_map( /** * @return string */ function (\Psalm\Type\Union $type_param) use($namespace, $aliased_classes, $this_class) : string { return $type_param->toNamespacedString($namespace, $aliased_classes, $this_class, \false); }, $this->type_params )) . '>' . $extra_types; } public function __clone() { foreach ($this->type_params as &$type_param) { $type_param = clone $type_param; } } /** * @return array<\Psalm\Type\TypeNode> */ public function getChildNodes() : array { return $this->type_params; } public function replaceTemplateTypesWithStandins(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null, ?\Psalm\Type\Atomic $input_type = null, ?int $input_arg_offset = null, ?string $calling_class = null, ?string $calling_function = null, bool $replace = \true, bool $add_upper_bound = \false, int $depth = 0) : \Psalm\Type\Atomic { if ($input_type instanceof \Psalm\Type\Atomic\TList) { $input_type = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $input_type->type_param]); } $input_object_type_params = []; if ($input_type instanceof \Psalm\Type\Atomic\TGenericObject && ($this instanceof \Psalm\Type\Atomic\TGenericObject || $this instanceof \Psalm\Type\Atomic\TIterable) && $codebase) { $input_object_type_params = \Psalm\Internal\Type\UnionTemplateHandler::getMappedGenericTypeParams($codebase, $input_type, $this); } $atomic = clone $this; foreach ($atomic->type_params as $offset => $type_param) { $input_type_param = null; if (($input_type instanceof \Psalm\Type\Atomic\TIterable || $input_type instanceof \Psalm\Type\Atomic\TArray) && isset($input_type->type_params[$offset])) { $input_type_param = $input_type->type_params[$offset]; } elseif ($input_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($offset === 0) { $input_type_param = $input_type->getGenericKeyType(); } elseif ($offset === 1) { $input_type_param = $input_type->getGenericValueType(); } else { throw new \UnexpectedValueException('Not expecting offset of ' . $offset); } } elseif ($input_type instanceof \Psalm\Type\Atomic\TNamedObject && isset($input_object_type_params[$offset])) { $input_type_param = $input_object_type_params[$offset]; } /** @psalm-suppress PropertyTypeCoercion */ $atomic->type_params[$offset] = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($type_param, $template_result, $codebase, $statements_analyzer, $input_type_param, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth + 1); } return $atomic; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { foreach ($this->type_params as $offset => $type_param) { $type_param->replaceTemplateTypesWithArgTypes($template_result, $codebase); if ($this instanceof \Psalm\Type\Atomic\TArray && $offset === 0 && $type_param->isMixed()) { $this->type_params[0] = \Psalm\Type::getArrayKey(); } } if ($this instanceof \Psalm\Type\Atomic\TGenericObject) { $this->remapped_params = \true; } if ($this instanceof \Psalm\Type\Atomic\TGenericObject || $this instanceof \Psalm\Type\Atomic\TIterable) { $this->replaceIntersectionTemplateTypesWithArgTypes($template_result, $codebase); } } } getKey(); } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getAssertionString() : string { return 'string'; } } */ public $properties; /** * @var array|null */ public $class_strings = null; /** * @var bool - whether or not the objectlike has been created from an explicit array */ public $sealed = \false; /** * Whether or not the previous array had an unknown key type * * @var ?Union */ public $previous_key_type = null; /** * Whether or not to allow new properties to be asserted on the given array * * @var ?Union */ public $previous_value_type = null; /** * @var bool - if this is a list of sequential elements */ public $is_list = \false; public const KEY = 'array'; /** * Constructs a new instance of a generic type * * @param non-empty-array $properties * @param array $class_strings */ public function __construct(array $properties, ?array $class_strings = null) { $this->properties = $properties; $this->class_strings = $class_strings; } public function __toString() : string { $property_strings = \array_map(function ($name, \Psalm\Type\Union $type) : string { if ($this->is_list && $this->sealed) { return (string) $type; } if (\is_string($name) && \preg_match('/[ "\'\\\\.\\n:]/', $name)) { $name = '\'' . \str_replace("\n", '\\n', \addslashes($name)) . '\''; } return $name . ($type->possibly_undefined ? '?' : '') . ': ' . $type; }, \array_keys($this->properties), $this->properties); if (!$this->is_list) { \sort($property_strings); } /** @psalm-suppress MixedOperand */ return static::KEY . '{' . \implode(', ', $property_strings) . '}'; } public function getId(bool $nested = \false) : string { $property_strings = \array_map(function ($name, \Psalm\Type\Union $type) : string { if ($this->is_list && $this->sealed) { return $type->getId(); } if (\is_string($name) && \preg_match('/[ "\'\\\\.\\n:]/', $name)) { $name = '\'' . \str_replace("\n", '\\n', \addslashes($name)) . '\''; } return $name . ($type->possibly_undefined ? '?' : '') . ': ' . $type->getId(); }, \array_keys($this->properties), $this->properties); if (!$this->is_list) { \sort($property_strings); } /** @psalm-suppress MixedOperand */ return static::KEY . '{' . \implode(', ', $property_strings) . '}' . ($this->previous_value_type && (!$this->previous_value_type->isMixed() || $this->previous_key_type && !$this->previous_key_type->isArrayKey()) ? '<' . ($this->previous_key_type ? $this->previous_key_type->getId() . ', ' : '') . $this->previous_value_type->getId() . '>' : ''); } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($use_phpdoc_format) { return $this->getGenericArrayType()->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format); } /** @psalm-suppress MixedOperand */ return static::KEY . '{' . \implode(', ', \array_map(function ($name, \Psalm\Type\Union $type) use($namespace, $aliased_classes, $this_class, $use_phpdoc_format) : string { if (\is_string($name) && \preg_match('/[ "\'\\\\.\\n:]/', $name)) { $name = '\'' . \str_replace("\n", '\\n', \addslashes($name)) . '\''; } return $name . ($type->possibly_undefined ? '?' : '') . ': ' . $type->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format); }, \array_keys($this->properties), $this->properties)) . '}'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : string { return $this->getKey(); } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getGenericKeyType() : \Psalm\Type\Union { $key_types = []; foreach ($this->properties as $key => $_) { if (\is_int($key)) { $key_types[] = new \Psalm\Type\Atomic\TLiteralInt($key); } elseif (isset($this->class_strings[$key])) { $key_types[] = new \Psalm\Type\Atomic\TLiteralClassString($key); } else { $key_types[] = new \Psalm\Type\Atomic\TLiteralString($key); } } $key_type = \Psalm\Internal\Type\TypeCombination::combineTypes($key_types); $key_type->possibly_undefined = \false; if ($this->previous_key_type) { $key_type = \Psalm\Type::combineUnionTypes($this->previous_key_type, $key_type); } return $key_type; } public function getGenericValueType() : \Psalm\Type\Union { $value_type = null; foreach ($this->properties as $property) { if ($value_type === null) { $value_type = clone $property; } else { $value_type = \Psalm\Type::combineUnionTypes($property, $value_type); } } if ($this->previous_value_type) { $value_type = \Psalm\Type::combineUnionTypes($this->previous_value_type, $value_type); } $value_type->possibly_undefined = \false; return $value_type; } public function getGenericArrayType() : \Psalm\Type\Atomic\TArray { $key_types = []; $value_type = null; $has_defined_keys = \false; foreach ($this->properties as $key => $property) { if (\is_int($key)) { $key_types[] = new \Psalm\Type\Atomic\TLiteralInt($key); } elseif (isset($this->class_strings[$key])) { $key_types[] = new \Psalm\Type\Atomic\TLiteralClassString($key); } else { $key_types[] = new \Psalm\Type\Atomic\TLiteralString($key); } if ($value_type === null) { $value_type = clone $property; } else { $value_type = \Psalm\Type::combineUnionTypes($property, $value_type); } if (!$value_type->possibly_undefined) { $has_defined_keys = \true; } } $key_type = \Psalm\Internal\Type\TypeCombination::combineTypes($key_types); if ($this->previous_value_type) { $value_type = \Psalm\Type::combineUnionTypes($this->previous_value_type, $value_type); } if ($this->previous_key_type) { $key_type = \Psalm\Type::combineUnionTypes($this->previous_key_type, $key_type); } $value_type->possibly_undefined = \false; if ($this->previous_value_type || $has_defined_keys) { $array_type = new \Psalm\Type\Atomic\TNonEmptyArray([$key_type, $value_type]); } else { $array_type = new \Psalm\Type\Atomic\TArray([$key_type, $value_type]); } return $array_type; } public function __clone() { foreach ($this->properties as &$property) { $property = clone $property; } } public function getKey(bool $include_extra = \true) : string { /** @var string */ return static::KEY; } public function replaceTemplateTypesWithStandins(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null, ?\Psalm\Type\Atomic $input_type = null, ?int $input_arg_offset = null, ?string $calling_class = null, ?string $calling_function = null, bool $replace = \true, bool $add_upper_bound = \false, int $depth = 0) : \Psalm\Type\Atomic { $object_like = clone $this; foreach ($this->properties as $offset => $property) { $input_type_param = null; if ($input_type instanceof \Psalm\Type\Atomic\TKeyedArray && isset($input_type->properties[$offset])) { $input_type_param = $input_type->properties[$offset]; } $object_like->properties[$offset] = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($property, $template_result, $codebase, $statements_analyzer, $input_type_param, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth); } return $object_like; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { foreach ($this->properties as $property) { $property->replaceTemplateTypesWithArgTypes($template_result, $codebase); } } public function getChildNodes() : array { return $this->properties; } public function equals(\Psalm\Type\Atomic $other_type) : bool { if (\get_class($other_type) !== static::class) { return \false; } if (\count($this->properties) !== \count($other_type->properties)) { return \false; } if ($this->sealed !== $other_type->sealed) { return \false; } foreach ($this->properties as $property_name => $property_type) { if (!isset($other_type->properties[$property_name])) { return \false; } if (!$property_type->equals($other_type->properties[$property_name])) { return \false; } } return \true; } public function getAssertionString() : string { return $this->getKey(); } public function getList() : \Psalm\Type\Atomic\TNonEmptyList { if (!$this->is_list) { throw new \UnexpectedValueException('Object-like array must be a list for conversion'); } return new \Psalm\Type\Atomic\TNonEmptyList($this->getGenericValueType()); } } fq_classlike_name = $fq_classlike_name; $this->const_name = $const_name; } public function getKey(bool $include_extra = \true) : string { return 'value-of<' . $this->fq_classlike_name . '::' . $this->const_name . '>'; } public function __toString() : string { return 'value-of<' . $this->fq_classlike_name . '::' . $this->const_name . '>'; } public function getId(bool $nested = \false) : string { return $this->getKey(); } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($this->fq_classlike_name === 'static') { return 'value-ofconst_name . '>'; } return 'value-of<' . \Psalm\Type::getStringFromFQCLN($this->fq_classlike_name, $namespace, $aliased_classes, $this_class) . '>::' . $this->const_name . '>'; } public function getAssertionString() : string { return 'mixed'; } } param_name = $param_name; $this->defining_class = $defining_class; $this->as_type = $as_type; $this->conditional_type = $conditional_type; $this->if_type = $if_type; $this->else_type = $else_type; } public function __toString() : string { return '(' . $this->param_name . ' is ' . $this->conditional_type . ' ? ' . $this->if_type . ' : ' . $this->else_type . ')'; } public function __clone() { $this->conditional_type = clone $this->conditional_type; $this->if_type = clone $this->if_type; $this->else_type = clone $this->else_type; $this->as_type = clone $this->as_type; } public function getKey(bool $include_extra = \true) : string { return $this->__toString(); } public function getAssertionString() : string { return ''; } public function getId(bool $nested = \false) : string { return '(' . $this->param_name . ':' . $this->defining_class . ' is ' . $this->conditional_type->getId() . ' ? ' . $this->if_type->getId() . ' : ' . $this->else_type->getId() . ')'; } /** * @param array $aliased_classes * * @return null */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return ''; } public function getChildNodes() : array { return [$this->conditional_type, $this->if_type, $this->else_type]; } public function canBeFullyExpressedInPhp() : bool { return \false; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { $this->conditional_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); } } param_name = $param_name; $this->as = $extends; $this->defining_class = $defining_class; } public function __toString() : string { return $this->param_name; } public function getKey(bool $include_extra = \true) : string { if ($include_extra && $this->extra_types) { return $this->param_name . ':' . $this->defining_class . '&' . \implode('&', $this->extra_types); } return $this->param_name . ':' . $this->defining_class; } public function getAssertionString() : string { return $this->as->getId(); } public function getId(bool $nested = \false) : string { if ($this->extra_types) { return '(' . $this->param_name . ':' . $this->defining_class . ' as ' . $this->as->getId() . ')&' . \implode('&', \array_map(function ($type) { return $type->getId(\true); }, $this->extra_types)); } return ($nested ? '(' : '') . $this->param_name . ':' . $this->defining_class . ' as ' . $this->as->getId() . ($nested ? ')' : ''); } /** * @param array $aliased_classes * * @return null */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($use_phpdoc_format) { return $this->as->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format); } $intersection_types = $this->getNamespacedIntersectionTypes($namespace, $aliased_classes, $this_class, $use_phpdoc_format); return $this->param_name . $intersection_types; } public function getChildNodes() : array { return [$this->as]; } public function canBeFullyExpressedInPhp() : bool { return \false; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { $this->replaceIntersectionTemplateTypesWithArgTypes($template_result, $codebase); } } as = $as; $this->as_type = $as_type; } public function getKey(bool $include_extra = \true) : string { return 'class-string' . ($this->as === 'object' ? '' : '<' . $this->as_type . '>'); } public function __toString() : string { return $this->getKey(); } public function getId(bool $nested = \false) : string { return $this->getKey(); } public function getAssertionString() : string { return 'class-string'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return 'string'; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($this->as === 'object') { return 'class-string'; } if ($namespace && \stripos($this->as, $namespace . '\\') === 0) { return 'class-string<' . \preg_replace('/^' . \preg_quote($namespace . '\\') . '/i', '', $this->as) . '>'; } if (!$namespace && \strpos($this->as, '\\') === \false) { return 'class-string<' . $this->as . '>'; } if (isset($aliased_classes[\strtolower($this->as)])) { return 'class-string<' . $aliased_classes[\strtolower($this->as)] . '>'; } return 'class-string<\\' . $this->as . '>'; } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getChildNodes() : array { return $this->as_type ? [$this->as_type] : []; } public function replaceTemplateTypesWithStandins(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null, ?\Psalm\Type\Atomic $input_type = null, ?int $input_arg_offset = null, ?string $calling_class = null, ?string $calling_function = null, bool $replace = \true, bool $add_upper_bound = \false, int $depth = 0) : \Psalm\Type\Atomic { $class_string = clone $this; if (!$class_string->as_type) { return $class_string; } if ($input_type instanceof \Psalm\Type\Atomic\TLiteralClassString) { $input_object_type = new \Psalm\Type\Atomic\TNamedObject($input_type->value); } elseif ($input_type instanceof \Psalm\Type\Atomic\TClassString && $input_type->as_type) { $input_object_type = $input_type->as_type; } else { $input_object_type = new \Psalm\Type\Atomic\TObject(); } $as_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins(new \Psalm\Type\Union([$class_string->as_type]), $template_result, $codebase, $statements_analyzer, new \Psalm\Type\Union([$input_object_type]), $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth); $as_type_types = \array_values($as_type->getAtomicTypes()); $class_string->as_type = \count($as_type_types) === 1 && $as_type_types[0] instanceof \Psalm\Type\Atomic\TNamedObject ? $as_type_types[0] : null; if (!$class_string->as_type) { $class_string->as = 'object'; } return $class_string; } } getKey(); } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getAssertionString() : string { return 'string'; } } value_param = $value_param; $this->param_name = $param_name; $this->as_type = $as_type; } public function __toString() : string { /** @psalm-suppress MixedOperand */ return static::KEY . '<' . $this->param_name . ' as ' . ($this->as_type ? (string) $this->as_type : 'object') . ', ' . (string) $this->value_param . '>'; } public function getId(bool $nested = \false) : string { /** @psalm-suppress MixedOperand */ return static::KEY . '<' . $this->param_name . ' as ' . ($this->as_type ? (string) $this->as_type : 'object') . ', ' . $this->value_param->getId() . '>'; } public function __clone() { $this->value_param = clone $this->value_param; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($use_phpdoc_format) { return (new \Psalm\Type\Atomic\TArray([\Psalm\Type::getString(), $this->value_param]))->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format); } /** @psalm-suppress MixedOperand */ return static::KEY . '<' . $this->param_name . ($this->as_type ? ' as ' . $this->as_type : '') . ', ' . $this->value_param->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format) . '>'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : string { return 'array'; } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getKey(bool $include_extra = \true) : string { return 'array'; } public function replaceTemplateTypesWithStandins(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null, ?\Psalm\Type\Atomic $input_type = null, ?int $input_arg_offset = null, ?string $calling_class = null, ?string $calling_function = null, bool $replace = \true, bool $add_upper_bound = \false, int $depth = 0) : \Psalm\Type\Atomic { $map = clone $this; foreach ([\Psalm\Type::getString(), $map->value_param] as $offset => $type_param) { $input_type_param = null; if (($input_type instanceof \Psalm\Type\Atomic\TGenericObject || $input_type instanceof \Psalm\Type\Atomic\TIterable || $input_type instanceof \Psalm\Type\Atomic\TArray) && isset($input_type->type_params[$offset])) { $input_type_param = clone $input_type->type_params[$offset]; } elseif ($input_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($offset === 0) { $input_type_param = $input_type->getGenericKeyType(); } else { $input_type_param = $input_type->getGenericValueType(); } } elseif ($input_type instanceof \Psalm\Type\Atomic\TList) { if ($offset === 0) { continue; } $input_type_param = clone $input_type->type_param; } $value_param = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($type_param, $template_result, $codebase, $statements_analyzer, $input_type_param, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth + 1); if ($offset === 1) { $map->value_param = $value_param; } } return $map; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { $this->value_param->replaceTemplateTypesWithArgTypes($template_result, $codebase); } public function getChildNodes() : array { return [$this->value_param]; } public function equals(\Psalm\Type\Atomic $other_type) : bool { if (\get_class($other_type) !== static::class) { return \false; } if (!$this->value_param->equals($other_type->value_param)) { return \false; } return \true; } public function getAssertionString() : string { return $this->getKey(); } public function getStandinKeyParam() : \Psalm\Type\Union { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParamClass($this->param_name, $this->as_type ? $this->as_type->value : 'object', $this->as_type, 'class-string-map')]); } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } } typeof = $typeof; $this->as_type = $as_type; } public function getId(bool $nested = \false) : string { return $this->as_type->isMixed() || $this->as_type->hasObject() ? 'class-string' : 'class-string<' . $this->as_type->getId() . '>'; } public function canBeFullyExpressedInPhp() : bool { return \false; } } fq_classlike_name = $fq_classlike_name; $this->const_name = $const_name; } public function getKey(bool $include_extra = \true) : string { return 'scalar-class-constant(' . $this->fq_classlike_name . '::' . $this->const_name . ')'; } public function __toString() : string { return $this->fq_classlike_name . '::' . $this->const_name; } public function getId(bool $nested = \false) : string { return $this->getKey(); } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($this->fq_classlike_name === 'static') { return 'static::' . $this->const_name; } return \Psalm\Type::getStringFromFQCLN($this->fq_classlike_name, $namespace, $aliased_classes, $this_class) . '::' . $this->const_name; } public function getAssertionString() : string { return 'mixed'; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } } typeof = $typeof; } public function canBeFullyExpressedInPhp() : bool { return \false; } } */ public $properties; /** * @var array */ public $methods; /** * Constructs a new instance of a generic type * * @param array $properties * @param array $methods */ public function __construct(array $properties, array $methods = []) { $this->properties = $properties; $this->methods = $methods; } public function __toString() : string { $extra_types = ''; if ($this->extra_types) { $extra_types = '&' . \implode('&', $this->extra_types); } $properties_string = \implode(', ', \array_map( /** * @param string|int $name */ function ($name, \Psalm\Type\Union $type) : string { return $name . ($type->possibly_undefined ? '?' : '') . ':' . $type; }, \array_keys($this->properties), $this->properties )); $methods_string = \implode(', ', \array_map(function (string $name) : string { return $name . '()'; }, \array_keys($this->methods))); return 'object{' . $properties_string . ($methods_string && $properties_string ? ', ' : '') . $methods_string . '}' . $extra_types; } public function getId(bool $nested = \false) : string { $extra_types = ''; if ($this->extra_types) { $extra_types = '&' . \implode('&', $this->extra_types); } $properties_string = \implode(', ', \array_map( /** * @param string|int $name */ function ($name, \Psalm\Type\Union $type) : string { return $name . ($type->possibly_undefined ? '?' : '') . ':' . $type->getId(); }, \array_keys($this->properties), $this->properties )); $methods_string = \implode(', ', \array_map(function (string $name) : string { return $name . '()'; }, \array_keys($this->methods))); return 'object{' . $properties_string . ($methods_string && $properties_string ? ', ' : '') . $methods_string . '}' . $extra_types; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($use_phpdoc_format) { return 'object'; } return 'object{' . \implode(', ', \array_map( /** * @param string|int $name */ function ($name, \Psalm\Type\Union $type) use($namespace, $aliased_classes, $this_class, $use_phpdoc_format) : string { return $name . ($type->possibly_undefined ? '?' : '') . ':' . $type->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format); }, \array_keys($this->properties), $this->properties )) . '}'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : string { return $this->getKey(); } public function canBeFullyExpressedInPhp() : bool { return \false; } public function __clone() { foreach ($this->properties as &$property) { $property = clone $property; } } public function equals(\Psalm\Type\Atomic $other_type) : bool { if (!$other_type instanceof self) { return \false; } if (\count($this->properties) !== \count($other_type->properties)) { return \false; } if ($this->methods !== $other_type->methods) { return \false; } foreach ($this->properties as $property_name => $property_type) { if (!isset($other_type->properties[$property_name])) { return \false; } if (!$property_type->equals($other_type->properties[$property_name])) { return \false; } } return \true; } public function replaceTemplateTypesWithStandins(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null, ?\Psalm\Type\Atomic $input_type = null, ?int $input_arg_offset = null, ?string $calling_class = null, ?string $calling_function = null, bool $replace = \true, bool $add_upper_bound = \false, int $depth = 0) : \Psalm\Type\Atomic { $object_like = clone $this; foreach ($this->properties as $offset => $property) { $input_type_param = null; if ($input_type instanceof \Psalm\Type\Atomic\TKeyedArray && isset($input_type->properties[$offset])) { $input_type_param = $input_type->properties[$offset]; } $object_like->properties[$offset] = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($property, $template_result, $codebase, $statements_analyzer, $input_type_param, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth); } return $object_like; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { foreach ($this->properties as $property) { $property->replaceTemplateTypesWithArgTypes($template_result, $codebase); } } public function getChildNodes() : array { return \array_merge($this->properties, $this->extra_types !== null ? \array_values($this->extra_types) : []); } public function getAssertionString() : string { return $this->getKey(); } } getKey(); } public function getId(bool $nested = \false) : string { return $this->getKey(); } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return 'string'; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return 'trait-string'; } public function canBeFullyExpressedInPhp() : bool { return \false; } } value = $value; $this->was_static = $was_static; } public function __toString() : string { return $this->getKey(); } public function getKey(bool $include_extra = \true) : string { if ($include_extra && $this->extra_types) { return $this->value . '&' . \implode('&', $this->extra_types); } return $this->value; } public function getId(bool $nested = \false) : string { if ($this->extra_types) { return $this->value . '&' . \implode('&', \array_map(function ($type) { return $type->getId(\true); }, $this->extra_types)); } return $this->was_static ? $this->value . '&static' : $this->value; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($this->value === 'static') { return 'static'; } $intersection_types = $this->getNamespacedIntersectionTypes($namespace, $aliased_classes, $this_class, $use_phpdoc_format); return \Psalm\Type::getStringFromFQCLN($this->value, $namespace, $aliased_classes, $this_class, \true) . $intersection_types; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { if ($this->value === 'static') { return null; } return $this->toNamespacedString($namespace, $aliased_classes, $this_class, \false); } public function canBeFullyExpressedInPhp() : bool { return $this->value !== 'static'; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { $this->replaceIntersectionTemplateTypesWithArgTypes($template_result, $codebase); } public function getChildNodes() : array { return $this->extra_types !== null ? $this->extra_types : []; } } value = $value; } public function getKey(bool $include_extra = \true) : string { return 'int(' . $this->value . ')'; } public function getId(bool $nested = \false) : string { return 'int(' . $this->value . ')'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version >= 7 ? 'int' : null; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return $use_phpdoc_format ? 'int' : (string) $this->value; } } 7 || $php_major_version === 7 && $php_minor_version >= 2 ? 'object' : null; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return 'object'; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version >= 7 ? 'string' : null; } public function __toString() : string { return 'string'; } public function getKey(bool $include_extra = \true) : string { return 'string'; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version >= 7 ? 'bool' : null; } } $type_params */ public function __construct(string $value, array $type_params) { if ($value[0] === '\\') { $value = \substr($value, 1); } $this->value = $value; $this->type_params = $type_params; } public function getKey(bool $include_extra = \true) : string { $s = ''; foreach ($this->type_params as $type_param) { $s .= $type_param->getKey() . ', '; } $extra_types = ''; if ($include_extra && $this->extra_types) { $extra_types = '&' . \implode('&', $this->extra_types); } return $this->value . '<' . \substr($s, 0, -2) . '>' . $extra_types; } public function canBeFullyExpressedInPhp() : bool { return \false; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return parent::toNamespacedString($namespace, $aliased_classes, $this_class, \false); } public function equals(\Psalm\Type\Atomic $other_type) : bool { if (!$other_type instanceof self) { return \false; } if (\count($this->type_params) !== \count($other_type->type_params)) { return \false; } foreach ($this->type_params as $i => $type_param) { if (!$type_param->equals($other_type->type_params[$i])) { return \false; } } return \true; } public function getAssertionString() : string { return $this->value; } public function getChildNodes() : array { return \array_merge($this->type_params, $this->extra_types !== null ? $this->extra_types : []); } } param_name = $param_name; $this->defining_class = $defining_class; $this->as = $as; } public function getKey(bool $include_extra = \true) : string { return 'key-of<' . $this->param_name . '>'; } public function __toString() : string { return 'key-of<' . $this->param_name . '>'; } public function getId(bool $nested = \false) : string { return 'key-of<' . $this->param_name . ':' . $this->defining_class . ' as ' . $this->as->getId() . '>'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } /** * @return false */ public function canBeFullyExpressedInPhp() : bool { return \false; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return 'key-of<' . $this->param_name . '>'; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version > 7 || $php_major_version === 7 && $php_minor_version >= 2 ? $this->getKey() : null; } public function canBeFullyExpressedInPhp() : bool { return \true; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version >= 7 ? 'float' : null; } } value = $value; } public function getKey(bool $include_extra = \true) : string { return $this->getId(); } public function __toString() : string { return 'string'; } public function getId(bool $nested = \false) : string { $no_newline_value = \preg_replace("/\n/m", '\\n', $this->value); if (\strlen($this->value) > 80) { return 'string(' . \substr($no_newline_value, 0, 80) . '...' . ')'; } return 'string(' . $no_newline_value . ')'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version >= 7 ? 'string' : null; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return 'string'; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } public function getAssertionString() : string { return 'scalar'; } } $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } } |null */ public $params = []; /** * @var Union|null */ public $return_type; /** * @var ?bool */ public $is_pure; /** * Constructs a new instance of a generic type * * @param array $params */ public function __construct(string $value = 'callable', ?array $params = null, ?\Psalm\Type\Union $return_type = null, ?bool $is_pure = null) { $this->value = $value; $this->params = $params; $this->return_type = $return_type; $this->is_pure = $is_pure; } public function __clone() { if ($this->params) { foreach ($this->params as &$param) { $param = clone $param; } } $this->return_type = $this->return_type ? clone $this->return_type : null; } public function getKey(bool $include_extra = \true) : string { return $this->__toString(); } /** * @param array $aliased_classes */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if ($use_phpdoc_format) { if ($this instanceof \Psalm\Type\Atomic\TNamedObject) { return parent::toNamespacedString($namespace, $aliased_classes, $this_class, \true); } return $this->value; } $param_string = ''; $return_type_string = ''; if ($this->params !== null) { $param_string = '(' . \implode(', ', \array_map( /** * @return string */ function (\Psalm\Storage\FunctionLikeParameter $param) use($namespace, $aliased_classes, $this_class) : string { if (!$param->type) { $type_string = 'mixed'; } else { $type_string = $param->type->toNamespacedString($namespace, $aliased_classes, $this_class, \false); } return ($param->is_variadic ? '...' : '') . $type_string . ($param->is_optional ? '=' : ''); }, $this->params )) . ')'; } if ($this->return_type !== null) { $return_type_multiple = \count($this->return_type->getAtomicTypes()) > 1; $return_type_string = ':' . ($return_type_multiple ? '(' : '') . $this->return_type->toNamespacedString($namespace, $aliased_classes, $this_class, \false) . ($return_type_multiple ? ')' : ''); } if ($this instanceof \Psalm\Type\Atomic\TNamedObject) { return parent::toNamespacedString($namespace, $aliased_classes, $this_class, \true) . $param_string . $return_type_string; } return ($this->is_pure ? 'pure-' : '') . 'callable' . $param_string . $return_type_string; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : string { if ($this instanceof \Psalm\Type\Atomic\TNamedObject) { return parent::toNamespacedString($namespace, $aliased_classes, $this_class, \true); } return $this->value; } public function getId(bool $nested = \false) : string { $param_string = ''; $return_type_string = ''; if ($this->params !== null) { $param_string .= '('; foreach ($this->params as $i => $param) { if ($i) { $param_string .= ', '; } $param_string .= $param->getId(); } $param_string .= ')'; } if ($this->return_type !== null) { $return_type_multiple = \count($this->return_type->getAtomicTypes()) > 1; $return_type_string = ':' . ($return_type_multiple ? '(' : '') . $this->return_type->getId() . ($return_type_multiple ? ')' : ''); } return ($this->is_pure ? 'pure-' : ($this->is_pure === null ? '' : 'impure-')) . $this->value . $param_string . $return_type_string; } public function __toString() : string { return $this->getId(); } public function replaceTemplateTypesWithStandins(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null, ?\Psalm\Type\Atomic $input_type = null, ?int $input_arg_offset = null, ?string $calling_class = null, ?string $calling_function = null, bool $replace = \true, bool $add_upper_bound = \false, int $depth = 0) : \Psalm\Type\Atomic { $callable = clone $this; if ($callable->params) { foreach ($callable->params as $offset => $param) { $input_param_type = null; if (($input_type instanceof \Psalm\Type\Atomic\TClosure || $input_type instanceof \Psalm\Type\Atomic\TCallable) && isset($input_type->params[$offset])) { $input_param_type = $input_type->params[$offset]->type; } if (!$param->type) { continue; } $param->type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($param->type, $template_result, $codebase, $statements_analyzer, $input_param_type, $input_arg_offset, $calling_class, $calling_function, $replace, !$add_upper_bound, $depth); } } if (($input_type instanceof \Psalm\Type\Atomic\TCallable || $input_type instanceof \Psalm\Type\Atomic\TClosure) && $callable->return_type && $input_type->return_type) { $callable->return_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($callable->return_type, $template_result, $codebase, $statements_analyzer, $input_type->return_type, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound); } return $callable; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { if ($this->params) { foreach ($this->params as $param) { if (!$param->type) { continue; } $param->type->replaceTemplateTypesWithArgTypes($template_result, $codebase); } } if ($this->return_type) { $this->return_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); } } /** * @return list<\Psalm\Type\TypeNode> */ public function getChildNodes() : array { $child_nodes = []; if ($this->params) { foreach ($this->params as $param) { if ($param->type) { $child_nodes[] = $param->type; } } } if ($this->return_type) { $child_nodes[] = $this->return_type; } return $child_nodes; } } $type_params */ public function __construct(array $type_params = []) { if ($type_params) { $this->has_docblock_params = \true; $this->type_params = $type_params; } else { $this->type_params = [\Psalm\Type::getMixed(), \Psalm\Type::getMixed()]; } } public function getKey(bool $include_extra = \true) : string { if ($include_extra && $this->extra_types) { // do nothing } return 'iterable'; } public function getAssertionString() : string { return 'iterable'; } public function getId(bool $nested = \false) : string { $s = ''; foreach ($this->type_params as $type_param) { $s .= $type_param->getId() . ', '; } $extra_types = ''; if ($this->extra_types) { $extra_types = '&' . \implode('&', $this->extra_types); } return $this->value . '<' . \substr($s, 0, -2) . '>' . $extra_types; } public function __toString() : string { return $this->getId(); } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version > 7 || $php_major_version === 7 && $php_minor_version >= 1 ? 'iterable' : null; } public function canBeFullyExpressedInPhp() : bool { return $this->type_params[0]->isMixed() && $this->type_params[1]->isMixed(); } public function equals(\Psalm\Type\Atomic $other_type) : bool { if (!$other_type instanceof self) { return \false; } if (\count($this->type_params) !== \count($other_type->type_params)) { return \false; } foreach ($this->type_params as $i => $type_param) { if (!$type_param->equals($other_type->type_params[$i])) { return \false; } } return \true; } public function getChildNodes() : array { return \array_merge($this->type_params, $this->extra_types !== null ? $this->extra_types : []); } } value = $value; } public function getKey(bool $include_extra = \true) : string { return 'float(' . $this->value . ')'; } public function getId(bool $nested = \false) : string { return 'float(' . $this->value . ')'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return $php_major_version >= 7 ? 'float' : null; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return 'float'; } } $type_params */ public function __construct(array $type_params) { $this->type_params = $type_params; } public function getKey(bool $include_extra = \true) : string { return 'array'; } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : string { return $this->getKey(); } public function canBeFullyExpressedInPhp() : bool { return $this->type_params[0]->isArrayKey() && $this->type_params[1]->isMixed(); } public function equals(\Psalm\Type\Atomic $other_type) : bool { if (\get_class($other_type) !== static::class) { return \false; } if ($this instanceof \Psalm\Type\Atomic\TNonEmptyArray && $other_type instanceof \Psalm\Type\Atomic\TNonEmptyArray && $this->count !== $other_type->count) { return \false; } if (\count($this->type_params) !== \count($other_type->type_params)) { return \false; } foreach ($this->type_params as $i => $type_param) { if (!$type_param->equals($other_type->type_params[$i])) { return \false; } } return \true; } public function getAssertionString() : string { return $this->getKey(); } } getKey(); } public function canBeFullyExpressedInPhp() : bool { return \false; } } typeof = $typeof; } public function canBeFullyExpressedInPhp() : bool { return \false; } } |null */ public $extra_types; /** * @param array $aliased_classes */ private function getNamespacedIntersectionTypes(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { if (!$this->extra_types) { return ''; } return '&' . \implode('&', \array_map( /** * @param TNamedObject|TTemplateParam|TIterable|TObjectWithProperties $extra_type * * @return string */ function (\Psalm\Type\Atomic $extra_type) use($namespace, $aliased_classes, $this_class, $use_phpdoc_format) : string { return $extra_type->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format); }, $this->extra_types )); } /** * @param TNamedObject|TTemplateParam|TIterable|TObjectWithProperties $type */ public function addIntersectionType(\Psalm\Type\Atomic $type) : void { $this->extra_types[$type->getKey()] = $type; } /** * @return array|null */ public function getIntersectionTypes() : ?array { return $this->extra_types; } public function replaceIntersectionTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { if (!$this->extra_types) { return; } $new_types = []; foreach ($this->extra_types as $extra_type) { if ($extra_type instanceof \Psalm\Type\Atomic\TTemplateParam && isset($template_result->upper_bounds[$extra_type->param_name][$extra_type->defining_class])) { $template_type = clone $template_result->upper_bounds[$extra_type->param_name][$extra_type->defining_class][0]; foreach ($template_type->getAtomicTypes() as $template_type_part) { if ($template_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $new_types[$template_type_part->getKey()] = $template_type_part; } elseif ($template_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $new_types[$template_type_part->getKey()] = $template_type_part; } } } else { $extra_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); $new_types[$extra_type->getKey()] = $extra_type; } } $this->extra_types = $new_types; } } array_param_name = $array_param_name; $this->offset_param_name = $offset_param_name; $this->defining_class = $defining_class; } public function getKey(bool $include_extra = \true) : string { return $this->array_param_name . '[' . $this->offset_param_name . ']'; } public function __toString() : string { return $this->getKey(); } public function getId(bool $nested = \false) : string { return $this->getKey(); } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { return null; } public function canBeFullyExpressedInPhp() : bool { return \false; } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { return $this->getKey(); } } */ public $byref_uses = []; public function canBeFullyExpressedInPhp() : bool { return \false; } } >> $all_types * * @return array>> * * @psalm-pure */ public static function negateTypes(array $all_types) : array { return \array_filter(\array_map( /** * @param non-empty-list> $anded_types * * @return list> */ function (array $anded_types) : array { if (\count($anded_types) > 1) { $new_anded_types = []; foreach ($anded_types as $orred_types) { if (\count($orred_types) > 1) { return []; } $new_anded_types[] = self::negateType($orred_types[0]); } return [$new_anded_types]; } $new_orred_types = []; foreach ($anded_types[0] as $orred_type) { $new_orred_types[] = [self::negateType($orred_type)]; } return $new_orred_types; }, $all_types )); } /** * @psalm-pure */ public static function negateType(string $type) : string { if ($type === 'mixed') { return $type; } return $type[0] === '!' ? \substr($type, 1) : '!' . $type; } /** * @return list */ public static function getFormula(int $conditional_object_id, int $creating_object_id, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $conditional, ?string $this_class_name, \Psalm\FileSource $source, ?\Psalm\Codebase $codebase = null, bool $inside_negation = \false, bool $cache = \true) : array { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd) { $left_assertions = self::getFormula($conditional_object_id, \spl_object_id($conditional->left), $conditional->left, $this_class_name, $source, $codebase, $inside_negation, $cache); $right_assertions = self::getFormula($conditional_object_id, \spl_object_id($conditional->right), $conditional->right, $this_class_name, $source, $codebase, $inside_negation, $cache); return \array_merge($left_assertions, $right_assertions); } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr) { $left_clauses = self::getFormula($conditional_object_id, \spl_object_id($conditional->left), $conditional->left, $this_class_name, $source, $codebase, $inside_negation, $cache); $right_clauses = self::getFormula($conditional_object_id, \spl_object_id($conditional->right), $conditional->right, $this_class_name, $source, $codebase, $inside_negation, $cache); return self::combineOredClauses($left_clauses, $right_clauses, $conditional_object_id); } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot) { if ($conditional->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr) { $and_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($conditional->expr->left, $conditional->getAttributes()), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($conditional->expr->right, $conditional->getAttributes()), $conditional->expr->getAttributes()); return self::getFormula($conditional_object_id, $conditional_object_id, $and_expr, $this_class_name, $source, $codebase, $inside_negation, \false); } if ($conditional->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Isset_ && \count($conditional->expr->vars) > 1) { $assertions = null; if ($cache && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $assertions = $source->node_data->getAssertions($conditional->expr); } if ($assertions === null) { $assertions = \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::scrapeAssertions($conditional->expr, $this_class_name, $source, $codebase, $inside_negation, $cache); if ($cache && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $source->node_data->setAssertions($conditional->expr, $assertions); } } $clauses = []; foreach ($assertions as $var => $anded_types) { $redefined = \false; if ($var[0] === '=') { /** @var string */ $var = \substr($var, 1); $redefined = \true; } foreach ($anded_types as $orred_types) { $clauses[] = new \Psalm\Internal\Clause([$var => $orred_types], $conditional_object_id, \spl_object_id($conditional->expr), \false, \true, $orred_types[0][0] === '=' || $orred_types[0][0] === '~' || \strlen($orred_types[0]) > 1 && ($orred_types[0][1] === '=' || $orred_types[0][1] === '~'), $redefined ? [$var => \true] : []); } } return self::negateFormula($clauses); } if ($conditional->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd) { $and_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($conditional->expr->left, $conditional->getAttributes()), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($conditional->expr->right, $conditional->getAttributes()), $conditional->expr->getAttributes()); return self::getFormula($conditional_object_id, \spl_object_id($conditional->expr), $and_expr, $this_class_name, $source, $codebase, $inside_negation, \false); } return self::negateFormula(self::getFormula($conditional_object_id, \spl_object_id($conditional->expr), $conditional->expr, $this_class_name, $source, $codebase, !$inside_negation)); } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal) { $false_pos = \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::hasFalseVariable($conditional); $true_pos = \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::hasTrueVariable($conditional); if ($false_pos === \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::ASSIGNMENT_TO_RIGHT && ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd || $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr)) { $inside_negation = !$inside_negation; return self::getFormula($conditional_object_id, \spl_object_id($conditional->left), $conditional->left, $this_class_name, $source, $codebase, $inside_negation, $cache); } if ($false_pos === \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::ASSIGNMENT_TO_LEFT && ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd || $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr)) { $inside_negation = !$inside_negation; return self::getFormula($conditional_object_id, \spl_object_id($conditional->right), $conditional->right, $this_class_name, $source, $codebase, $inside_negation, $cache); } if ($true_pos === \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::ASSIGNMENT_TO_RIGHT && ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd || $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr)) { return self::getFormula($conditional_object_id, \spl_object_id($conditional->left), $conditional->left, $this_class_name, $source, $codebase, $inside_negation, $cache); } if ($true_pos === \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::ASSIGNMENT_TO_LEFT && ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd || $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr)) { return self::getFormula($conditional_object_id, \spl_object_id($conditional->right), $conditional->right, $this_class_name, $source, $codebase, $inside_negation, $cache); } } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Bool_) { return self::getFormula($conditional_object_id, \spl_object_id($conditional->expr), $conditional->expr, $this_class_name, $source, $codebase, $inside_negation, $cache); } $assertions = null; if ($cache && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $assertions = $source->node_data->getAssertions($conditional); } if ($assertions === null) { $assertions = \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::scrapeAssertions($conditional, $this_class_name, $source, $codebase, $inside_negation, $cache); if ($cache && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $source->node_data->setAssertions($conditional, $assertions); } } if ($assertions) { $clauses = []; foreach ($assertions as $var => $anded_types) { $redefined = \false; if ($var[0] === '=') { /** @var string */ $var = \substr($var, 1); $redefined = \true; } foreach ($anded_types as $orred_types) { $clauses[] = new \Psalm\Internal\Clause([$var => $orred_types], $conditional_object_id, $creating_object_id, \false, \true, $orred_types[0][0] === '=' || $orred_types[0][0] === '~' || \strlen($orred_types[0]) > 1 && ($orred_types[0][1] === '=' || $orred_types[0][1] === '~'), $redefined ? [$var => \true] : []); } } return $clauses; } return [new \Psalm\Internal\Clause([], $conditional_object_id, $creating_object_id, \true)]; } /** * This is a very simple simplification heuristic * for CNF formulae. * * It simplifies formulae: * ($a) && ($a || $b) => $a * (!$a) && (!$b) && ($a || $b || $c) => $c * * @param list $clauses * * @return list * * @psalm-pure */ public static function simplifyCNF(array $clauses) : array { $cloned_clauses = []; // avoid strict duplicates foreach ($clauses as $clause) { $unique_clause = $clause->makeUnique(); $cloned_clauses[$unique_clause->hash] = $unique_clause; } // remove impossible types foreach ($cloned_clauses as $clause_a) { if (\count($clause_a->possibilities) !== 1 || \count(\array_values($clause_a->possibilities)[0]) !== 1) { continue; } if (!$clause_a->reconcilable || $clause_a->wedge) { continue; } $clause_var = \array_keys($clause_a->possibilities)[0]; $only_type = \array_pop(\array_values($clause_a->possibilities)[0]); $negated_clause_type = self::negateType($only_type); foreach ($cloned_clauses as $clause_hash => $clause_b) { if ($clause_a === $clause_b || !$clause_b->reconcilable || $clause_b->wedge) { continue; } if (isset($clause_b->possibilities[$clause_var]) && \in_array($negated_clause_type, $clause_b->possibilities[$clause_var], \true)) { $clause_var_possibilities = \array_values(\array_filter($clause_b->possibilities[$clause_var], function (string $possible_type) use($negated_clause_type) : bool { return $possible_type !== $negated_clause_type; })); unset($cloned_clauses[$clause_hash]); if (!$clause_var_possibilities) { $updated_clause = $clause_b->removePossibilities($clause_var); if ($updated_clause) { $cloned_clauses[$updated_clause->hash] = $updated_clause; } } else { $updated_clause = $clause_b->addPossibilities($clause_var, $clause_var_possibilities); $cloned_clauses[$updated_clause->hash] = $updated_clause; } } } } $simplified_clauses = []; foreach ($cloned_clauses as $clause_a) { $is_redundant = \false; foreach ($cloned_clauses as $clause_b) { if ($clause_a === $clause_b || !$clause_b->reconcilable || $clause_b->wedge || $clause_a->wedge) { continue; } if ($clause_a->contains($clause_b)) { $is_redundant = \true; break; } } if (!$is_redundant) { $simplified_clauses[] = $clause_a; } } return $simplified_clauses; } /** * Look for clauses with only one possible value * * @param list $clauses * @param array $cond_referenced_var_ids * @param array>> $active_truths * * @return array>> */ public static function getTruthsFromFormula(array $clauses, ?int $creating_conditional_id = null, array &$cond_referenced_var_ids = [], array &$active_truths = []) : array { $truths = []; $active_truths = []; if ($clauses === []) { return []; } foreach ($clauses as $clause) { if (!$clause->reconcilable) { continue; } foreach ($clause->possibilities as $var => $possible_types) { // if there's only one possible type, return it if (\count($clause->possibilities) === 1 && \count($possible_types) === 1) { $possible_type = \array_pop($possible_types); if (isset($truths[$var]) && !isset($clause->redefined_vars[$var])) { $truths[$var][] = [$possible_type]; } else { $truths[$var] = [[$possible_type]]; } if ($creating_conditional_id && $creating_conditional_id === $clause->creating_conditional_id) { if (!isset($active_truths[$var])) { $active_truths[$var] = []; } $active_truths[$var][\count($truths[$var]) - 1] = [$possible_type]; } } elseif (\count($clause->possibilities) === 1) { // if there's only one active clause, return all the non-negation clause members ORed together $things_that_can_be_said = \array_filter($possible_types, function (string $possible_type) : bool { return $possible_type[0] !== '!'; }); if ($things_that_can_be_said && \count($things_that_can_be_said) === \count($possible_types)) { $things_that_can_be_said = \array_unique($things_that_can_be_said); if ($clause->generated && \count($possible_types) > 1) { unset($cond_referenced_var_ids[$var]); } /** @var array $things_that_can_be_said */ $truths[$var] = [$things_that_can_be_said]; if ($creating_conditional_id && $creating_conditional_id === $clause->creating_conditional_id) { $active_truths[$var] = [$things_that_can_be_said]; } } } } } return $truths; } /** * @param non-empty-list $clauses * * @return list * * @psalm-pure */ public static function groupImpossibilities(array $clauses) : array { $complexity = 1; $seed_clauses = []; $clause = \array_pop($clauses); if (!$clause->wedge) { if ($clause->impossibilities === null) { throw new \UnexpectedValueException('$clause->impossibilities should not be null'); } foreach ($clause->impossibilities as $var => $impossible_types) { foreach ($impossible_types as $impossible_type) { $seed_clause = new \Psalm\Internal\Clause([$var => [$impossible_type]], $clause->creating_conditional_id, $clause->creating_object_id); $seed_clauses[] = $seed_clause; ++$complexity; } } } if (!$clauses || !$seed_clauses) { return $seed_clauses; } while ($clauses) { $clause = \array_pop($clauses); $new_clauses = []; foreach ($seed_clauses as $grouped_clause) { if ($clause->impossibilities === null) { throw new \UnexpectedValueException('$clause->impossibilities should not be null'); } foreach ($clause->impossibilities as $var => $impossible_types) { foreach ($impossible_types as $impossible_type) { $new_clause_possibilities = $grouped_clause->possibilities; if (isset($grouped_clause->possibilities[$var])) { $new_clause_possibilities[$var][] = $impossible_type; } else { $new_clause_possibilities[$var] = [$impossible_type]; } $new_clause = new \Psalm\Internal\Clause($new_clause_possibilities, $grouped_clause->creating_conditional_id, $clause->creating_object_id, \false, \true, \true, []); $new_clauses[] = $new_clause; ++$complexity; if ($complexity > 20000) { throw new \Psalm\Exception\ComplicatedExpressionException(); } } } } $seed_clauses = $new_clauses; } return $seed_clauses; } /** * @param list $left_clauses * @param list $right_clauses * * @return list * * @psalm-pure */ public static function combineOredClauses(array $left_clauses, array $right_clauses, int $conditional_object_id) : array { $clauses = []; $all_wedges = \true; $has_wedge = \false; foreach ($left_clauses as $left_clause) { foreach ($right_clauses as $right_clause) { $all_wedges = $all_wedges && ($left_clause->wedge && $right_clause->wedge); $has_wedge = $has_wedge || $left_clause->wedge && $right_clause->wedge; } } if ($all_wedges) { return [new \Psalm\Internal\Clause([], $conditional_object_id, $conditional_object_id, \true)]; } foreach ($left_clauses as $left_clause) { foreach ($right_clauses as $right_clause) { if ($left_clause->wedge && $right_clause->wedge) { // handled below continue; } /** @var array> */ $possibilities = []; $can_reconcile = \true; if ($left_clause->wedge || $right_clause->wedge || !$left_clause->reconcilable || !$right_clause->reconcilable) { $can_reconcile = \false; } foreach ($left_clause->possibilities as $var => $possible_types) { if (isset($right_clause->redefined_vars[$var])) { continue; } if (isset($possibilities[$var])) { $possibilities[$var] = \array_merge($possibilities[$var], $possible_types); } else { $possibilities[$var] = $possible_types; } } foreach ($right_clause->possibilities as $var => $possible_types) { if (isset($possibilities[$var])) { $possibilities[$var] = \array_merge($possibilities[$var], $possible_types); } else { $possibilities[$var] = $possible_types; } } if (\count($left_clauses) > 1 || \count($right_clauses) > 1) { foreach ($possibilities as $var => $p) { $possibilities[$var] = \array_values(\array_unique($p)); } } foreach ($possibilities as $var_possibilities) { if (\count($var_possibilities) === 2) { if ($var_possibilities[0] === '!' . $var_possibilities[1] || $var_possibilities[1] === '!' . $var_possibilities[0]) { continue 2; } } } $creating_conditional_id = $right_clause->creating_conditional_id === $left_clause->creating_conditional_id ? $right_clause->creating_conditional_id : $conditional_object_id; $clauses[] = new \Psalm\Internal\Clause($possibilities, $creating_conditional_id, $creating_conditional_id, \false, $can_reconcile, $right_clause->generated || $left_clause->generated || \count($left_clauses) > 1 || \count($right_clauses) > 1, []); } } if ($has_wedge) { $clauses[] = new \Psalm\Internal\Clause([], $conditional_object_id, $conditional_object_id, \true); } return $clauses; } /** * Negates a set of clauses * negateClauses([$a || $b]) => !$a && !$b * negateClauses([$a, $b]) => !$a || !$b * negateClauses([$a, $b || $c]) => * (!$a || !$b) && * (!$a || !$c) * negateClauses([$a, $b || $c, $d || $e || $f]) => * (!$a || !$b || !$d) && * (!$a || !$b || !$e) && * (!$a || !$b || !$f) && * (!$a || !$c || !$d) && * (!$a || !$c || !$e) && * (!$a || !$c || !$f) * * @param list $clauses * * @return non-empty-list */ public static function negateFormula(array $clauses) : array { if (!$clauses) { $cond_id = \mt_rand(0, 100000000); return [new \Psalm\Internal\Clause([], $cond_id, $cond_id, \true)]; } $clauses_with_impossibilities = []; foreach ($clauses as $clause) { $clauses_with_impossibilities[] = $clause->calculateNegation(); } unset($clauses); $impossible_clauses = self::groupImpossibilities($clauses_with_impossibilities); if (!$impossible_clauses) { $cond_id = \mt_rand(0, 100000000); return [new \Psalm\Internal\Clause([], $cond_id, $cond_id, \true)]; } $negated = self::simplifyCNF($impossible_clauses); if (!$negated) { $cond_id = \mt_rand(0, 100000000); return [new \Psalm\Internal\Clause([], $cond_id, $cond_id, \true)]; } return $negated; } } */ private $types; /** * Whether the type originated in a docblock * * @var bool */ public $from_docblock = \false; /** * Whether the type originated from integer calculation * * @var bool */ public $from_calculation = \false; /** * Whether the property that this type has been derived from has been initialized in a constructor * * @var bool */ public $initialized = \true; /** * Which class the type was initialised in * * @var ?string */ public $initialized_class = null; /** * Whether or not the type has been checked yet * * @var bool */ public $checked = \false; /** * @var bool */ public $failed_reconciliation = \false; /** * Whether or not to ignore issues with possibly-null values * * @var bool */ public $ignore_nullable_issues = \false; /** * Whether or not to ignore issues with possibly-false values * * @var bool */ public $ignore_falsable_issues = \false; /** * Whether or not this variable is possibly undefined * * @var bool */ public $possibly_undefined = \false; /** * Whether or not this variable is possibly undefined * * @var bool */ public $possibly_undefined_from_try = \false; /** * Whether or not this union had a template, since replaced * * @var bool */ public $had_template = \false; /** * Whether or not this union comes from a template "as" default * * @var bool */ public $from_template_default = \false; /** * @var array */ private $literal_string_types = []; /** * @var array */ private $typed_class_strings = []; /** * @var array */ private $literal_int_types = []; /** * @var array */ private $literal_float_types = []; /** * Whether or not the type was passed by reference * * @var bool */ public $by_ref = \false; /** * @var bool */ public $reference_free = \false; /** * @var bool */ public $allow_mutations = \true; /** @var null|string */ private $id; /** * @var array */ public $parent_nodes = []; /** * @var bool */ public $different = \false; /** * Constructs an Union instance * * @param non-empty-array $types */ public function __construct(array $types) { $from_docblock = \false; $keyed_types = []; foreach ($types as $type) { $key = $type->getKey(); $keyed_types[$key] = $type; if ($type instanceof \Psalm\Type\Atomic\TLiteralInt) { $this->literal_int_types[$key] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralString) { $this->literal_string_types[$key] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralFloat) { $this->literal_float_types[$key] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TClassString && ($type->as_type || $type instanceof \Psalm\Type\Atomic\TTemplateParamClass)) { $this->typed_class_strings[$key] = $type; } $from_docblock = $from_docblock || $type->from_docblock; } $this->types = $keyed_types; $this->from_docblock = $from_docblock; } /** * @return array * @deprecated in favour of getAtomicTypes() * @psalm-suppress PossiblyUnusedMethod */ public function getTypes() : array { return $this->types; } /** * @return non-empty-array */ public function getAtomicTypes() : array { return $this->types; } public function addType(\Psalm\Type\Atomic $type) : void { $this->types[$type->getKey()] = $type; if ($type instanceof \Psalm\Type\Atomic\TLiteralString) { $this->literal_string_types[$type->getKey()] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralInt) { $this->literal_int_types[$type->getKey()] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralFloat) { $this->literal_float_types[$type->getKey()] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TString && $this->literal_string_types) { foreach ($this->literal_string_types as $key => $_) { unset($this->literal_string_types[$key], $this->types[$key]); } if (!$type instanceof \Psalm\Type\Atomic\TClassString || !$type->as_type && !$type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { foreach ($this->typed_class_strings as $key => $_) { unset($this->typed_class_strings[$key], $this->types[$key]); } } } elseif ($type instanceof \Psalm\Type\Atomic\TInt && $this->literal_int_types) { foreach ($this->literal_int_types as $key => $_) { unset($this->literal_int_types[$key], $this->types[$key]); } } elseif ($type instanceof \Psalm\Type\Atomic\TFloat && $this->literal_float_types) { foreach ($this->literal_float_types as $key => $_) { unset($this->literal_float_types[$key], $this->types[$key]); } } $this->id = null; } public function __clone() { $this->literal_string_types = []; $this->literal_int_types = []; $this->literal_float_types = []; $this->typed_class_strings = []; foreach ($this->types as $key => &$type) { $type = clone $type; if ($type instanceof \Psalm\Type\Atomic\TLiteralInt) { $this->literal_int_types[$key] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralString) { $this->literal_string_types[$key] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralFloat) { $this->literal_float_types[$key] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TClassString && ($type->as_type || $type instanceof \Psalm\Type\Atomic\TTemplateParamClass)) { $this->typed_class_strings[$key] = $type; } } } public function __toString() : string { $types = []; $printed_int = \false; $printed_float = \false; $printed_string = \false; foreach ($this->types as $type) { if ($type instanceof \Psalm\Type\Atomic\TLiteralFloat) { if ($printed_float) { continue; } $printed_float = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralString) { if ($printed_string) { continue; } $printed_string = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralInt) { if ($printed_int) { continue; } $printed_int = \true; } $types[] = \strval($type); } \sort($types); return \implode('|', $types); } public function getKey() : string { $types = []; $printed_int = \false; $printed_float = \false; $printed_string = \false; foreach ($this->types as $type) { if ($type instanceof \Psalm\Type\Atomic\TLiteralFloat) { if ($printed_float) { continue; } $types[] = 'float'; $printed_float = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralString) { if ($printed_string) { continue; } $types[] = 'string'; $printed_string = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralInt) { if ($printed_int) { continue; } $types[] = 'int'; $printed_int = \true; } else { $types[] = \strval($type->getKey()); } } \sort($types); return \implode('|', $types); } public function getId() : string { if ($this->id) { return $this->id; } $types = []; foreach ($this->types as $type) { $types[] = \strval($type->getId()); } \sort($types); if (\count($types) > 1) { foreach ($types as $i => $type) { if (\strpos($type, ' as ') && \strpos($type, '(') === \false) { $types[$i] = '(' . $type . ')'; } } } $id = \implode('|', $types); $this->id = $id; return $id; } public function getAssertionString() : string { foreach ($this->types as $type) { return $type->getAssertionString(); } throw new \UnexpectedValueException('Should only be one type per assertion'); } /** * @param array $aliased_classes * */ public function toNamespacedString(?string $namespace, array $aliased_classes, ?string $this_class, bool $use_phpdoc_format) : string { $types = []; $multi_ints = \count($this->literal_int_types) > 1 || $this->hasPositiveInt(); $multi_strings = \count($this->literal_string_types) > 1; $multi_floats = \count($this->literal_float_types) > 1; foreach ($this->types as $type) { $type_string = $type->toNamespacedString($namespace, $aliased_classes, $this_class, $use_phpdoc_format); if ($type instanceof \Psalm\Type\Atomic\TLiteralInt && !$multi_ints) { $type_string = 'int'; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralFloat && !$multi_floats) { $type_string = 'float'; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralString && !$multi_strings) { $type_string = 'string'; } $types[] = $type_string; } \sort($types); return \implode('|', \array_unique($types)); } /** * @param array $aliased_classes */ public function toPhpString(?string $namespace, array $aliased_classes, ?string $this_class, int $php_major_version, int $php_minor_version) : ?string { $nullable = \false; if (!$this->isSingleAndMaybeNullable() || $php_major_version < 7 || isset($this->types['null']) && $php_major_version === 7 && $php_minor_version < 1) { return null; } $types = $this->types; if (isset($types['null'])) { if (\count($types) === 1) { return null; } unset($types['null']); $nullable = \true; } $atomic_type = \array_values($types)[0]; $atomic_type_string = $atomic_type->toPhpString($namespace, $aliased_classes, $this_class, $php_major_version, $php_minor_version); if ($atomic_type_string) { return ($nullable ? '?' : '') . $atomic_type_string; } return null; } public function canBeFullyExpressedInPhp() : bool { if (!$this->isSingleAndMaybeNullable()) { return \false; } $types = $this->types; if (isset($types['null'])) { if (\count($types) > 1) { unset($types['null']); } else { return \false; } } $atomic_type = \array_values($types)[0]; return $atomic_type->canBeFullyExpressedInPhp(); } public function removeType(string $type_string) : bool { if (isset($this->types[$type_string])) { unset($this->types[$type_string]); if (\strpos($type_string, '(')) { unset($this->literal_string_types[$type_string], $this->literal_int_types[$type_string], $this->literal_float_types[$type_string]); } $this->id = null; return \true; } if ($type_string === 'string') { if ($this->literal_string_types) { foreach ($this->literal_string_types as $literal_key => $_) { unset($this->types[$literal_key]); } $this->literal_string_types = []; } if ($this->typed_class_strings) { foreach ($this->typed_class_strings as $typed_class_key => $_) { unset($this->types[$typed_class_key]); } $this->typed_class_strings = []; } unset($this->types['class-string'], $this->types['trait-string']); } elseif ($type_string === 'int' && $this->literal_int_types) { foreach ($this->literal_int_types as $literal_key => $_) { unset($this->types[$literal_key]); } $this->literal_int_types = []; } elseif ($type_string === 'float' && $this->literal_float_types) { foreach ($this->literal_float_types as $literal_key => $_) { unset($this->types[$literal_key]); } $this->literal_float_types = []; } return \false; } public function bustCache() : void { $this->id = null; } public function hasType(string $type_string) : bool { return isset($this->types[$type_string]); } public function hasArray() : bool { return isset($this->types['array']); } public function hasList() : bool { return isset($this->types['array']) && $this->types['array'] instanceof \Psalm\Type\Atomic\TList; } public function hasClassStringMap() : bool { return isset($this->types['array']) && $this->types['array'] instanceof \Psalm\Type\Atomic\TClassStringMap; } public function isTemplatedClassString() : bool { return $this->isSingle() && \count(\array_filter($this->types, function ($type) : bool { return $type instanceof \Psalm\Type\Atomic\TTemplateParamClass; })) === 1; } public function hasEmptyArray() : bool { return isset($this->types['array']) && $this->types['array'] instanceof \Psalm\Type\Atomic\TArray && $this->types['array']->type_params[1]->isEmpty(); } public function hasArrayAccessInterface(\Psalm\Codebase $codebase) : bool { return !!\array_filter($this->types, function ($type) use($codebase) { return $type->hasArrayAccessInterface($codebase); }); } public function hasCallableType() : bool { return $this->getCallableTypes() || $this->getClosureTypes(); } /** * @return array */ private function getCallableTypes() : array { return \array_filter($this->types, function ($type) : bool { return $type instanceof \Psalm\Type\Atomic\TCallable; }); } /** * @return array */ public function getClosureTypes() : array { return \array_filter($this->types, function ($type) : bool { return $type instanceof \Psalm\Type\Atomic\TClosure; }); } public function hasObject() : bool { return isset($this->types['object']); } public function hasObjectType() : bool { foreach ($this->types as $type) { if ($type->isObjectType()) { return \true; } } return \false; } public function isObjectType() : bool { foreach ($this->types as $type) { if (!$type->isObjectType()) { return \false; } } return \true; } public function hasNamedObjectType() : bool { foreach ($this->types as $type) { if ($type->isNamedObjectType()) { return \true; } } return \false; } public function isFormerStaticObject() : bool { foreach ($this->types as $type) { if (!$type instanceof \Psalm\Type\Atomic\TNamedObject || !$type->was_static) { return \false; } } return \true; } public function hasFormerStaticObject() : bool { foreach ($this->types as $type) { if ($type instanceof \Psalm\Type\Atomic\TNamedObject && $type->was_static) { return \true; } } return \false; } public function isNullable() : bool { if (isset($this->types['null'])) { return \true; } foreach ($this->types as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam && $type->as->isNullable()) { return \true; } } return \false; } public function isFalsable() : bool { if (isset($this->types['false'])) { return \true; } foreach ($this->types as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam && $type->as->isFalsable()) { return \true; } } return \false; } public function hasBool() : bool { return isset($this->types['bool']) || isset($this->types['false']) || isset($this->types['true']); } public function hasString() : bool { return isset($this->types['string']) || isset($this->types['class-string']) || isset($this->types['trait-string']) || isset($this->types['numeric-string']) || $this->literal_string_types || $this->typed_class_strings; } public function hasLowercaseString() : bool { return isset($this->types['string']) && ($this->types['string'] instanceof \Psalm\Type\Atomic\TLowercaseString || $this->types['string'] instanceof \Psalm\Type\Atomic\TNonEmptyLowercaseString); } public function hasLiteralClassString() : bool { return \count($this->typed_class_strings) > 0; } public function hasInt() : bool { return isset($this->types['int']) || isset($this->types['array-key']) || $this->literal_int_types; } public function hasPositiveInt() : bool { return isset($this->types['int']) && $this->types['int'] instanceof \Psalm\Type\Atomic\TPositiveInt; } public function hasArrayKey() : bool { return isset($this->types['array-key']); } public function hasFloat() : bool { return isset($this->types['float']) || $this->literal_float_types; } public function hasDefinitelyNumericType(bool $include_literal_int = \true) : bool { return isset($this->types['int']) || isset($this->types['float']) || isset($this->types['numeric-string']) || $include_literal_int && $this->literal_int_types || $this->literal_float_types; } public function hasPossiblyNumericType() : bool { return isset($this->types['int']) || isset($this->types['float']) || isset($this->types['string']) || isset($this->types['numeric-string']) || $this->literal_int_types || $this->literal_float_types || $this->literal_string_types; } public function hasScalar() : bool { return isset($this->types['scalar']); } public function hasNumeric() : bool { return isset($this->types['numeric']); } public function hasScalarType() : bool { return isset($this->types['int']) || isset($this->types['float']) || isset($this->types['string']) || isset($this->types['class-string']) || isset($this->types['trait-string']) || isset($this->types['bool']) || isset($this->types['false']) || isset($this->types['true']) || isset($this->types['numeric']) || isset($this->types['numeric-string']) || $this->literal_int_types || $this->literal_float_types || $this->literal_string_types || $this->typed_class_strings; } public function hasTemplate() : bool { return (bool) \array_filter($this->types, function (\Psalm\Type\Atomic $type) : bool { return $type instanceof \Psalm\Type\Atomic\TTemplateParam || $type instanceof \Psalm\Type\Atomic\TNamedObject && $type->extra_types && \array_filter($type->extra_types, function ($t) : bool { return $t instanceof \Psalm\Type\Atomic\TTemplateParam; }); }); } public function hasConditional() : bool { return (bool) \array_filter($this->types, function (\Psalm\Type\Atomic $type) : bool { return $type instanceof \Psalm\Type\Atomic\TConditional; }); } public function hasTemplateOrStatic() : bool { return (bool) \array_filter($this->types, function (\Psalm\Type\Atomic $type) : bool { return $type instanceof \Psalm\Type\Atomic\TTemplateParam || $type instanceof \Psalm\Type\Atomic\TNamedObject && ($type->was_static || $type->extra_types && \array_filter($type->extra_types, function ($t) : bool { return $t instanceof \Psalm\Type\Atomic\TTemplateParam; })); }); } public function hasMixed() : bool { return isset($this->types['mixed']); } public function isMixed() : bool { return isset($this->types['mixed']) && \count($this->types) === 1; } public function isEmptyMixed() : bool { return isset($this->types['mixed']) && $this->types['mixed'] instanceof \Psalm\Type\Atomic\TEmptyMixed; } public function isVanillaMixed() : bool { /** * @psalm-suppress UndefinedPropertyFetch */ return isset($this->types['mixed']) && !$this->types['mixed']->from_loop_isset && \get_class($this->types['mixed']) === \Psalm\Type\Atomic\TMixed::class && !$this->types['mixed']->from_loop_isset && \count($this->types) === 1; } public function isArrayKey() : bool { return isset($this->types['array-key']) && \count($this->types) === 1; } public function isNull() : bool { return \count($this->types) === 1 && isset($this->types['null']); } public function isFalse() : bool { return \count($this->types) === 1 && isset($this->types['false']); } public function isTrue() : bool { return \count($this->types) === 1 && isset($this->types['true']); } public function isVoid() : bool { return isset($this->types['void']); } public function isNever() : bool { return isset($this->types['never-return']); } public function isGenerator() : bool { return \count($this->types) === 1 && ($single_type = \reset($this->types)) instanceof \Psalm\Type\Atomic\TNamedObject && $single_type->value === 'Generator'; } public function isEmpty() : bool { return isset($this->types['empty']); } public function substitute(\Psalm\Type\Union $old_type, ?\Psalm\Type\Union $new_type = null) : void { if ($this->hasMixed() && !$this->isEmptyMixed()) { return; } if ($new_type && $new_type->ignore_nullable_issues) { $this->ignore_nullable_issues = \true; } if ($new_type && $new_type->ignore_falsable_issues) { $this->ignore_falsable_issues = \true; } foreach ($old_type->types as $old_type_part) { if (!$this->removeType($old_type_part->getKey())) { if ($old_type_part instanceof \Psalm\Type\Atomic\TFalse && isset($this->types['bool']) && !isset($this->types['true'])) { $this->removeType('bool'); $this->types['true'] = new \Psalm\Type\Atomic\TTrue(); } elseif ($old_type_part instanceof \Psalm\Type\Atomic\TTrue && isset($this->types['bool']) && !isset($this->types['false'])) { $this->removeType('bool'); $this->types['false'] = new \Psalm\Type\Atomic\TFalse(); } elseif (isset($this->types['iterable'])) { if ($old_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $old_type_part->value === 'Traversable' && !isset($this->types['array'])) { $this->removeType('iterable'); $this->types['array'] = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getMixed()]); } if ($old_type_part instanceof \Psalm\Type\Atomic\TArray && !isset($this->types['traversable'])) { $this->removeType('iterable'); $this->types['traversable'] = new \Psalm\Type\Atomic\TNamedObject('Traversable'); } } elseif (isset($this->types['array-key'])) { if ($old_type_part instanceof \Psalm\Type\Atomic\TString && !isset($this->types['int'])) { $this->removeType('array-key'); $this->types['int'] = new \Psalm\Type\Atomic\TInt(); } if ($old_type_part instanceof \Psalm\Type\Atomic\TInt && !isset($this->types['string'])) { $this->removeType('array-key'); $this->types['string'] = new \Psalm\Type\Atomic\TString(); } } } } if ($new_type) { foreach ($new_type->types as $key => $new_type_part) { if (!isset($this->types[$key]) || $new_type_part instanceof \Psalm\Type\Atomic\Scalar && \get_class($new_type_part) === \get_class($this->types[$key])) { $this->types[$key] = $new_type_part; } else { $combined = \Psalm\Internal\Type\TypeCombination::combineTypes([$new_type_part, $this->types[$key]]); $this->types[$key] = \array_values($combined->types)[0]; } } } elseif (\count($this->types) === 0) { $this->types['mixed'] = new \Psalm\Type\Atomic\TMixed(); } $this->id = null; } public function replaceTemplateTypesWithArgTypes(\Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase) : void { $keys_to_unset = []; $new_types = []; $is_mixed = \false; $found_generic_params = $template_result->upper_bounds ?: []; foreach ($this->types as $key => $atomic_type) { $atomic_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $template_type = null; $traversed_type = \Psalm\Internal\Type\UnionTemplateHandler::getRootTemplateType($found_generic_params, $atomic_type->param_name, $atomic_type->defining_class); if ($traversed_type) { $template_type = $traversed_type[0]; if (!$atomic_type->as->isMixed() && $template_type->isMixed()) { $template_type = clone $atomic_type->as; } else { $template_type = clone $template_type; } if ($atomic_type->extra_types) { foreach ($template_type->getAtomicTypes() as $template_type_key => $atomic_template_type) { if ($atomic_template_type instanceof \Psalm\Type\Atomic\TNamedObject || $atomic_template_type instanceof \Psalm\Type\Atomic\TTemplateParam || $atomic_template_type instanceof \Psalm\Type\Atomic\TIterable || $atomic_template_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { $atomic_template_type->extra_types = \array_merge($atomic_type->extra_types, $atomic_template_type->extra_types ?: []); } elseif ($atomic_template_type instanceof \Psalm\Type\Atomic\TObject) { $first_atomic_type = \array_shift($atomic_type->extra_types); if ($atomic_type->extra_types) { $first_atomic_type->extra_types = $atomic_type->extra_types; } $template_type->removeType($template_type_key); $template_type->addType($first_atomic_type); } } } } elseif ($codebase) { foreach ($found_generic_params as $template_type_map) { foreach ($template_type_map as $template_class => $_) { if (\substr($template_class, 0, 3) === 'fn-') { continue; } try { $classlike_storage = $codebase->classlike_storage_provider->get($template_class); if ($classlike_storage->template_type_extends) { $defining_class = $atomic_type->defining_class; if (isset($classlike_storage->template_type_extends[$defining_class])) { $param_map = $classlike_storage->template_type_extends[$defining_class]; if (isset($param_map[$key]) && isset($found_generic_params[(string) $param_map[$key]][$template_class])) { $template_type = clone $found_generic_params[(string) $param_map[$key]][$template_class][0]; } } } } catch (\InvalidArgumentException $e) { } } } } if ($template_type) { $keys_to_unset[] = $key; foreach ($template_type->types as $template_type_part) { if ($template_type_part instanceof \Psalm\Type\Atomic\TMixed) { $is_mixed = \true; } $new_types[$template_type_part->getKey()] = $template_type_part; } } } elseif ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $template_type = isset($found_generic_params[$atomic_type->param_name][$atomic_type->defining_class]) ? clone $found_generic_params[$atomic_type->param_name][$atomic_type->defining_class][0] : null; $class_template_type = null; if ($template_type) { foreach ($template_type->types as $template_type_part) { if ($template_type_part instanceof \Psalm\Type\Atomic\TMixed || $template_type_part instanceof \Psalm\Type\Atomic\TObject) { $class_template_type = new \Psalm\Type\Atomic\TClassString(); } elseif ($template_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $class_template_type = new \Psalm\Type\Atomic\TClassString($template_type_part->value, $template_type_part); } elseif ($template_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $first_atomic_type = \array_values($template_type_part->as->types)[0]; $class_template_type = new \Psalm\Type\Atomic\TTemplateParamClass($template_type_part->param_name, $template_type_part->as->getId(), $first_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject ? $first_atomic_type : null, $template_type_part->defining_class); } } } if ($class_template_type) { $keys_to_unset[] = $key; $new_types[$class_template_type->getKey()] = $class_template_type; } } elseif ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateIndexedAccess) { $keys_to_unset[] = $key; $template_type = null; if (isset($found_generic_params[$atomic_type->array_param_name][$atomic_type->defining_class]) && !empty($found_generic_params[$atomic_type->offset_param_name])) { $array_template_type = $found_generic_params[$atomic_type->array_param_name][$atomic_type->defining_class][0]; $offset_template_type = \array_values($found_generic_params[$atomic_type->offset_param_name])[0][0]; if ($array_template_type->isSingle() && $offset_template_type->isSingle() && !$array_template_type->isMixed() && !$offset_template_type->isMixed()) { $array_template_type = \array_values($array_template_type->types)[0]; $offset_template_type = \array_values($offset_template_type->types)[0]; if ($array_template_type instanceof \Psalm\Type\Atomic\TKeyedArray && ($offset_template_type instanceof \Psalm\Type\Atomic\TLiteralString || $offset_template_type instanceof \Psalm\Type\Atomic\TLiteralInt) && isset($array_template_type->properties[$offset_template_type->value])) { $template_type = clone $array_template_type->properties[$offset_template_type->value]; } } } if ($template_type) { foreach ($template_type->types as $template_type_part) { if ($template_type_part instanceof \Psalm\Type\Atomic\TMixed) { $is_mixed = \true; } $new_types[$template_type_part->getKey()] = $template_type_part; } } else { $new_types[$key] = new \Psalm\Type\Atomic\TMixed(); } } elseif ($atomic_type instanceof \Psalm\Type\Atomic\TConditional && $codebase) { $template_type = isset($found_generic_params[$atomic_type->param_name][$atomic_type->defining_class]) ? clone $found_generic_params[$atomic_type->param_name][$atomic_type->defining_class][0] : null; $class_template_type = null; $atomic_type = clone $atomic_type; if ($template_type) { $atomic_type->as_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); if ($atomic_type->as_type->isNullable() && $template_type->isVoid()) { $template_type = \Psalm\Type::getNull(); } if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $template_type, $atomic_type->conditional_type)) { $class_template_type = clone $atomic_type->if_type; $class_template_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); } elseif (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $template_type, $atomic_type->as_type) && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $atomic_type->as_type, $template_type)) { $class_template_type = clone $atomic_type->else_type; $class_template_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); } } if (!$class_template_type) { $atomic_type->if_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); $atomic_type->else_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); $class_template_type = \Psalm\Type::combineUnionTypes($atomic_type->if_type, $atomic_type->else_type, $codebase); } $keys_to_unset[] = $key; foreach ($class_template_type->getAtomicTypes() as $class_template_atomic_type) { $new_types[$class_template_atomic_type->getKey()] = $class_template_atomic_type; } } } $this->id = null; if ($is_mixed) { if (!$new_types) { throw new \UnexpectedValueException('This array should be full'); } $this->types = $new_types; return; } foreach ($keys_to_unset as $key) { unset($this->types[$key]); } foreach ($new_types as $type) { if ($type instanceof \Psalm\Type\Atomic\TLiteralString) { $this->literal_string_types[$type->getKey()] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralInt) { $this->literal_int_types[$type->getKey()] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralFloat) { $this->literal_float_types[$type->getKey()] = $type; } } $atomic_types = \array_values(\array_merge($this->types, $new_types)); if ($atomic_types) { $this->types = \Psalm\Internal\Type\TypeCombination::combineTypes($atomic_types, $codebase)->getAtomicTypes(); $this->id = null; } } public function isSingle() : bool { $type_count = \count($this->types); $int_literal_count = \count($this->literal_int_types); $string_literal_count = \count($this->literal_string_types); $float_literal_count = \count($this->literal_float_types); if ($int_literal_count && $string_literal_count || $int_literal_count && $float_literal_count || $string_literal_count && $float_literal_count) { return \false; } if ($int_literal_count || $string_literal_count || $float_literal_count) { $type_count -= $int_literal_count + $string_literal_count + $float_literal_count - 1; } return $type_count === 1; } public function isSingleAndMaybeNullable() : bool { $is_nullable = isset($this->types['null']); $type_count = \count($this->types); if ($type_count === 1 && $is_nullable) { return \false; } $int_literal_count = \count($this->literal_int_types); $string_literal_count = \count($this->literal_string_types); $float_literal_count = \count($this->literal_float_types); if ($int_literal_count && $string_literal_count || $int_literal_count && $float_literal_count || $string_literal_count && $float_literal_count) { return \false; } if ($int_literal_count || $string_literal_count || $float_literal_count) { $type_count -= $int_literal_count + $string_literal_count + $float_literal_count - 1; } return $type_count - (int) $is_nullable === 1; } /** * @return bool true if this is an int */ public function isInt(bool $check_templates = \false) : bool { return \count(\array_filter($this->types, function ($type) use($check_templates) : bool { return $type instanceof \Psalm\Type\Atomic\TInt || $check_templates && $type instanceof \Psalm\Type\Atomic\TTemplateParam && $type->as->isInt(); })) === \count($this->types); } /** * @return bool true if this is a float */ public function isFloat() : bool { if (!$this->isSingle()) { return \false; } return isset($this->types['float']) || $this->literal_float_types; } /** * @return bool true if this is a string */ public function isString(bool $check_templates = \false) : bool { return \count(\array_filter($this->types, function ($type) use($check_templates) : bool { return $type instanceof \Psalm\Type\Atomic\TString || $check_templates && $type instanceof \Psalm\Type\Atomic\TTemplateParam && $type->as->isString(); })) === \count($this->types); } /** * @return bool true if this is a string literal with only one possible value */ public function isSingleStringLiteral() : bool { return \count($this->types) === 1 && \count($this->literal_string_types) === 1; } /** * @throws \InvalidArgumentException if isSingleStringLiteral is false * * @return TLiteralString the only string literal represented by this union type */ public function getSingleStringLiteral() : \Psalm\Type\Atomic\TLiteralString { if (\count($this->types) !== 1 || \count($this->literal_string_types) !== 1) { throw new \InvalidArgumentException('Not a string literal'); } return \reset($this->literal_string_types); } public function allStringLiterals() : bool { foreach ($this->types as $atomic_key_type) { if (!$atomic_key_type instanceof \Psalm\Type\Atomic\TLiteralString) { return \false; } } return \true; } public function hasLiteralValue() : bool { return $this->literal_int_types || $this->literal_string_types || $this->literal_float_types || isset($this->types['false']) || isset($this->types['true']); } public function hasLiteralString() : bool { return \count($this->literal_string_types) > 0; } public function hasLiteralInt() : bool { return \count($this->literal_int_types) > 0; } /** * @return bool true if this is a int literal with only one possible value */ public function isSingleIntLiteral() : bool { return \count($this->types) === 1 && \count($this->literal_int_types) === 1; } /** * @throws \InvalidArgumentException if isSingleIntLiteral is false * * @return TLiteralInt the only int literal represented by this union type */ public function getSingleIntLiteral() : \Psalm\Type\Atomic\TLiteralInt { if (\count($this->types) !== 1 || \count($this->literal_int_types) !== 1) { throw new \InvalidArgumentException('Not an int literal'); } return \reset($this->literal_int_types); } /** * @param array $suppressed_issues * @param array $phantom_classes * */ public function check(\Psalm\StatementsSource $source, \Psalm\CodeLocation $code_location, array $suppressed_issues, array $phantom_classes = [], bool $inferred = \true, bool $inherited = \false, bool $prevent_template_covariance = \false, ?string $calling_method_id = null) : bool { if ($this->checked) { return \true; } $checker = new \Psalm\Internal\TypeVisitor\TypeChecker($source, $code_location, $suppressed_issues, $phantom_classes, $inferred, $inherited, $prevent_template_covariance, $calling_method_id); $checker->traverseArray($this->types); $this->checked = \true; return !$checker->hasErrors(); } /** * @param array $phantom_classes * */ public function queueClassLikesForScanning(\Psalm\Codebase $codebase, ?\Psalm\Storage\FileStorage $file_storage = null, array $phantom_classes = []) : void { $scanner_visitor = new \Psalm\Internal\TypeVisitor\TypeScanner($codebase->scanner, $file_storage, $phantom_classes); $scanner_visitor->traverseArray($this->types); } /** * @param lowercase-string $fq_class_like_name */ public function containsClassLike(string $fq_class_like_name) : bool { $classlike_visitor = new \Psalm\Internal\TypeVisitor\ContainsClassLikeVisitor($fq_class_like_name); $classlike_visitor->traverseArray($this->types); return $classlike_visitor->matches(); } /** * @return list */ public function getTemplateTypes() : array { $template_type_collector = new \Psalm\Internal\TypeVisitor\TemplateTypeCollector(); $template_type_collector->traverseArray($this->types); return $template_type_collector->getTemplateTypes(); } public function setFromDocblock() : void { $this->from_docblock = \true; (new \Psalm\Internal\TypeVisitor\FromDocblockSetter())->traverseArray($this->types); } public function replaceClassLike(string $old, string $new) : void { foreach ($this->types as $key => $atomic_type) { $atomic_type->replaceClassLike($old, $new); $this->removeType($key); $this->addType($atomic_type); } } public function equals(\Psalm\Type\Union $other_type) : bool { if ($other_type === $this) { return \true; } if ($other_type->id && $this->id && $other_type->id !== $this->id) { return \false; } if ($this->possibly_undefined !== $other_type->possibly_undefined) { return \false; } if ($this->had_template !== $other_type->had_template) { return \false; } if ($this->possibly_undefined_from_try !== $other_type->possibly_undefined_from_try) { return \false; } if ($this->from_calculation !== $other_type->from_calculation) { return \false; } if ($this->initialized !== $other_type->initialized) { return \false; } if ($this->from_docblock !== $other_type->from_docblock) { return \false; } if (\count($this->types) !== \count($other_type->types)) { return \false; } if ($this->parent_nodes !== $other_type->parent_nodes) { return \false; } if ($this->different || $other_type->different) { return \false; } $other_atomic_types = $other_type->types; foreach ($this->types as $key => $atomic_type) { if (!isset($other_atomic_types[$key])) { return \false; } if (!$atomic_type->equals($other_atomic_types[$key])) { return \false; } } return \true; } /** * @return array */ public function getLiteralStrings() : array { return $this->literal_string_types; } /** * @return array */ public function getLiteralInts() : array { return $this->literal_int_types; } /** * @return array */ public function getLiteralFloats() : array { return $this->literal_float_types; } /** * @return array */ public function getChildNodes() : array { return $this->types; } } */ public function getChildNodes() : array; } enterNode($node); if ($visitor_result === self::DONT_TRAVERSE_CHILDREN) { return \true; } if ($visitor_result === self::STOP_TRAVERSAL) { return \false; } foreach ($node->getChildNodes() as $child_node) { if ($this->traverse($child_node) === \false) { return \false; } } return \true; } /** * @param array $nodes */ public function traverseArray(array $nodes) : void { foreach ($nodes as $node) { if ($this->traverse($node) === \false) { return; } } } } > */ private static $broken_paths = []; /** * Takes two arrays and consolidates them, removing null values from existing types where applicable * * @param array $new_types * @param array $active_new_types - types we can complain about * @param array $existing_types * @param array $changed_var_ids * @param array $referenced_var_ids * @param array> $template_type_map * * @return array */ public static function reconcileKeyedTypes(array $new_types, array $active_new_types, array $existing_types, array &$changed_var_ids, array $referenced_var_ids, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, array $template_type_map = [], bool $inside_loop = \false, ?\Psalm\CodeLocation $code_location = null, bool $negated = \false) : array { if (!$new_types) { return $existing_types; } $suppressed_issues = $statements_analyzer->getSuppressedIssues(); $old_new_types = $new_types; foreach ($new_types as $nk => $type) { if (\strpos($nk, '[') || \strpos($nk, '->')) { if ($type[0][0] === '=isset' || $type[0][0] === '!=empty' || $type[0][0] === 'isset' || $type[0][0] === '!empty') { $isset_or_empty = $type[0][0] === 'isset' || $type[0][0] === '=isset' ? '=isset' : '!=empty'; $key_parts = \Psalm\Type\Reconciler::breakUpPathIntoParts($nk); if (!$key_parts) { throw new \UnexpectedValueException('There should be some key parts'); } $base_key = \array_shift($key_parts); if ($base_key[0] !== '$' && \count($key_parts) > 2 && $key_parts[0] === '::$') { $base_key .= \array_shift($key_parts); $base_key .= \array_shift($key_parts); } if (!isset($existing_types[$base_key]) || $existing_types[$base_key]->isNullable()) { if (!isset($new_types[$base_key])) { $new_types[$base_key] = [['=isset']]; } else { $new_types[$base_key][] = ['=isset']; } } while ($key_parts) { $divider = \array_shift($key_parts); if ($divider === '[') { $array_key = \array_shift($key_parts); \array_shift($key_parts); $new_base_key = $base_key . '[' . $array_key . ']'; if (\strpos($array_key, '\'') !== \false) { $new_types[$base_key][] = ['=string-array-access']; } else { $new_types[$base_key][] = ['=int-or-string-array-access']; } $base_key = $new_base_key; continue; } if ($divider === '->') { $property_name = \array_shift($key_parts); $new_base_key = $base_key . '->' . $property_name; $base_key = $new_base_key; } else { break; } if (!$key_parts) { break; } if (!isset($new_types[$base_key])) { $new_types[$base_key] = [['!~bool'], ['!~int'], ['=isset']]; } else { $new_types[$base_key][] = ['!~bool']; $new_types[$base_key][] = ['!~int']; $new_types[$base_key][] = ['=isset']; } } // replace with a less specific check $new_types[$nk][0][0] = $isset_or_empty; } if ($type[0][0] === 'array-key-exists') { $key_parts = \Psalm\Type\Reconciler::breakUpPathIntoParts($nk); if (\count($key_parts) === 4 && $key_parts[1] === '[') { if (isset($new_types[$key_parts[2]])) { $new_types[$key_parts[2]][] = ['=in-array-' . $key_parts[0]]; } else { $new_types[$key_parts[2]] = [['=in-array-' . $key_parts[0]]]; } if ($key_parts[0][0] === '$') { if (isset($new_types[$key_parts[0]])) { $new_types[$key_parts[0]][] = ['=has-array-key-' . $key_parts[2]]; } else { $new_types[$key_parts[0]] = [['=has-array-key-' . $key_parts[2]]]; } } } } } } // make sure array keys come after base keys \ksort($new_types); $codebase = $statements_analyzer->getCodebase(); foreach ($new_types as $key => $new_type_parts) { $has_negation = \false; $has_isset = \false; $has_inverted_isset = \false; $has_falsyish = \false; $has_empty = \false; $has_count_check = \false; $is_equality = ($old_new_types[$key] ?? null) === $new_type_parts; foreach ($new_type_parts as $new_type_part_parts) { foreach ($new_type_part_parts as $new_type_part_part) { switch ($new_type_part_part[0]) { case '!': $has_negation = \true; break; } $has_isset = $has_isset || $new_type_part_part === 'isset' || $new_type_part_part === '=isset' || $new_type_part_part === 'array-key-exists' || $new_type_part_part === '=string-array-access'; $has_empty = $has_empty || $new_type_part_part === 'empty'; $has_falsyish = $has_falsyish || $new_type_part_part === 'empty' || $new_type_part_part === 'falsy'; $is_equality = $is_equality && $new_type_part_part[0] === '=' && $new_type_part_part !== '=isset'; $has_inverted_isset = $has_inverted_isset || $new_type_part_part === '!isset'; $has_count_check = $has_count_check || $new_type_part_part === 'non-empty-countable'; } } $did_type_exist = isset($existing_types[$key]); $has_object_array_access = \false; $result_type = isset($existing_types[$key]) ? clone $existing_types[$key] : self::getValueForKey($codebase, $key, $existing_types, $new_types, $code_location, $has_isset, $has_inverted_isset, $has_empty, $inside_loop, $has_object_array_access); if ($result_type && empty($result_type->getAtomicTypes())) { throw new \InvalidArgumentException('Union::$types cannot be empty after get value for ' . $key); } $before_adjustment = $result_type ? clone $result_type : null; $failed_reconciliation = 0; foreach ($new_type_parts as $offset => $new_type_part_parts) { $orred_type = null; foreach ($new_type_part_parts as $new_type_part_part) { if ($new_type_part_part[0] === '>') { /** @var array>> */ $data = \json_decode(\substr($new_type_part_part, 1), \true); $existing_types = self::reconcileKeyedTypes($data, $data, $existing_types, $changed_var_ids, $referenced_var_ids, $statements_analyzer, $template_type_map, $inside_loop, $code_location, $negated); $new_type_part_part = '!falsy'; } $result_type_candidate = \Psalm\Internal\Type\AssertionReconciler::reconcile($new_type_part_part, $result_type ? clone $result_type : null, $key, $statements_analyzer, $inside_loop, $template_type_map, $code_location && isset($referenced_var_ids[$key]) && isset($active_new_types[$key][$offset]) ? $code_location : null, $suppressed_issues, $failed_reconciliation, $negated); if (!$result_type_candidate->getAtomicTypes()) { $result_type_candidate->addType(new \Psalm\Type\Atomic\TEmpty()); } $orred_type = $orred_type ? \Psalm\Type::combineUnionTypes($result_type_candidate, $orred_type, $codebase) : $result_type_candidate; } $result_type = $orred_type; } if (!$result_type) { throw new \UnexpectedValueException('$result_type should not be null'); } if (!$did_type_exist && $result_type->isEmpty()) { continue; } if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && $result_type->hasString() || $statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph) { if ($before_adjustment && $before_adjustment->parent_nodes) { $result_type->parent_nodes = $before_adjustment->parent_nodes; } elseif (!$did_type_exist && $code_location) { $result_type->parent_nodes = $statements_analyzer->getParentNodesForPossiblyUndefinedVariable($key); } } if ($before_adjustment && $before_adjustment->by_ref) { $result_type->by_ref = \true; } $type_changed = !$before_adjustment || !$result_type->equals($before_adjustment); if ($type_changed || $failed_reconciliation) { $changed_var_ids[$key] = \true; if (\substr($key, -1) === ']' && !$has_inverted_isset && !$has_empty && !$is_equality) { $key_parts = self::breakUpPathIntoParts($key); self::adjustTKeyedArrayType($key_parts, $existing_types, $changed_var_ids, $result_type); } elseif ($key !== '$this') { foreach ($existing_types as $new_key => $_) { if ($new_key === $key) { continue; } if (!isset($new_types[$new_key]) && \preg_match('/' . \preg_quote($key, '/') . '[\\]\\[\\-]/', $new_key)) { unset($existing_types[$new_key]); } } } } elseif (!$has_negation && !$has_falsyish && !$has_isset) { $changed_var_ids[$key] = \true; } if ($failed_reconciliation === 2) { $result_type->failed_reconciliation = \true; } if (!$has_object_array_access) { $existing_types[$key] = $result_type; } } return $existing_types; } /** * @return array */ public static function breakUpPathIntoParts(string $path) : array { if (isset(self::$broken_paths[$path])) { return self::$broken_paths[$path]; } $chars = \str_split($path); $string_char = null; $escape_char = \false; $brackets = 0; $parts = ['']; $parts_offset = 0; for ($i = 0, $char_count = \count($chars); $i < $char_count; ++$i) { $char = $chars[$i]; if ($string_char) { if ($char === $string_char && !$escape_char) { $string_char = null; } if ($char === '\\') { $escape_char = !$escape_char; } $parts[$parts_offset] .= $char; continue; } switch ($char) { case '[': case ']': $parts_offset++; $parts[$parts_offset] = $char; ++$parts_offset; if ($char === '[') { $brackets++; } else { $brackets--; } continue 2; case '\'': case '"': if (!isset($parts[$parts_offset])) { $parts[$parts_offset] = ''; } $parts[$parts_offset] .= $char; $string_char = $char; continue 2; case ':': if (!$brackets && $i < $char_count - 2 && $chars[$i + 1] === ':' && $chars[$i + 2] === '$') { ++$i; ++$i; ++$parts_offset; $parts[$parts_offset] = '::$'; ++$parts_offset; continue 2; } // fall through case '-': if (!$brackets && $i < $char_count - 1 && $chars[$i + 1] === '>') { ++$i; ++$parts_offset; $parts[$parts_offset] = '->'; ++$parts_offset; continue 2; } // fall through // no break default: if (!isset($parts[$parts_offset])) { $parts[$parts_offset] = ''; } $parts[$parts_offset] .= $char; } } $parts = \array_values($parts); self::$broken_paths[$path] = $parts; return $parts; } /** * Gets the type for a given (non-existent key) based on the passed keys * * @param array $existing_keys * @param array $new_assertions * @param string[][] $new_type_parts * */ private static function getValueForKey(\Psalm\Codebase $codebase, string $key, array &$existing_keys, array $new_assertions, ?\Psalm\CodeLocation $code_location, bool $has_isset, bool $has_inverted_isset, bool $has_empty, bool $inside_loop, bool &$has_object_array_access) : ?\Psalm\Type\Union { $key_parts = self::breakUpPathIntoParts($key); if (\count($key_parts) === 1) { return isset($existing_keys[$key_parts[0]]) ? clone $existing_keys[$key_parts[0]] : null; } $base_key = \array_shift($key_parts); if ($base_key[0] !== '$' && \count($key_parts) > 2 && $key_parts[0] === '::$') { $base_key .= \array_shift($key_parts); $base_key .= \array_shift($key_parts); } if (!isset($existing_keys[$base_key])) { if (\strpos($base_key, '::')) { [$fq_class_name, $const_name] = \explode('::', $base_key); if (!$codebase->classlikes->classOrInterfaceExists($fq_class_name)) { return null; } $class_constant = $codebase->classlikes->getClassConstantType($fq_class_name, $const_name, \ReflectionProperty::IS_PRIVATE, null); if ($class_constant) { $existing_keys[$base_key] = clone $class_constant; } else { return null; } } else { return null; } } while ($key_parts) { $divider = \array_shift($key_parts); if ($divider === '[') { $array_key = \array_shift($key_parts); \array_shift($key_parts); $new_base_key = $base_key . '[' . $array_key . ']'; if (!isset($existing_keys[$new_base_key])) { $new_base_type = null; foreach ($existing_keys[$base_key]->getAtomicTypes() as $existing_key_type_part) { if ($existing_key_type_part instanceof \Psalm\Type\Atomic\TArray) { if ($has_empty) { return null; } $new_base_type_candidate = clone $existing_key_type_part->type_params[1]; if ($new_base_type_candidate->isMixed() && !$has_isset && !$has_inverted_isset) { return $new_base_type_candidate; } if (($has_isset || $has_inverted_isset) && isset($new_assertions[$new_base_key])) { if ($has_inverted_isset && $new_base_key === $key) { $new_base_type_candidate->addType(new \Psalm\Type\Atomic\TNull()); } $new_base_type_candidate->possibly_undefined = \true; } } elseif ($existing_key_type_part instanceof \Psalm\Type\Atomic\TList) { if ($has_empty) { return null; } $new_base_type_candidate = clone $existing_key_type_part->type_param; if (($has_isset || $has_inverted_isset) && isset($new_assertions[$new_base_key])) { if ($has_inverted_isset && $new_base_key === $key) { $new_base_type_candidate->addType(new \Psalm\Type\Atomic\TNull()); } $new_base_type_candidate->possibly_undefined = \true; } } elseif ($existing_key_type_part instanceof \Psalm\Type\Atomic\TNull || $existing_key_type_part instanceof \Psalm\Type\Atomic\TFalse) { $new_base_type_candidate = \Psalm\Type::getNull(); if ($existing_keys[$base_key]->ignore_nullable_issues) { $new_base_type_candidate->ignore_nullable_issues = \true; } } elseif ($existing_key_type_part instanceof \Psalm\Type\Atomic\TClassStringMap) { return \Psalm\Type::getMixed(); } elseif ($existing_key_type_part instanceof \Psalm\Type\Atomic\TEmpty || $existing_key_type_part instanceof \Psalm\Type\Atomic\TMixed && $existing_key_type_part->from_loop_isset) { return \Psalm\Type::getMixed($inside_loop); } elseif ($existing_key_type_part instanceof \Psalm\Type\Atomic\TString) { $new_base_type_candidate = \Psalm\Type::getString(); } elseif ($existing_key_type_part instanceof \Psalm\Type\Atomic\TNamedObject && ($has_isset || $has_inverted_isset)) { $has_object_array_access = \true; return null; } elseif (!$existing_key_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { return \Psalm\Type::getMixed(); } elseif ($array_key[0] === '$' || $array_key[0] !== '\'' && !\is_numeric($array_key[0])) { if ($has_empty) { return null; } $new_base_type_candidate = $existing_key_type_part->getGenericValueType(); } else { $array_properties = $existing_key_type_part->properties; $key_parts_key = \str_replace('\'', '', $array_key); if (!isset($array_properties[$key_parts_key])) { if ($existing_key_type_part->previous_value_type) { $new_base_type_candidate = clone $existing_key_type_part->previous_value_type; $new_base_type_candidate->different = \true; } else { return null; } } else { $new_base_type_candidate = clone $array_properties[$key_parts_key]; } } if (!$new_base_type) { $new_base_type = $new_base_type_candidate; } else { $new_base_type = \Psalm\Type::combineUnionTypes($new_base_type, $new_base_type_candidate, $codebase); } } $existing_keys[$new_base_key] = $new_base_type; } $base_key = $new_base_key; } elseif ($divider === '->' || $divider === '::$') { $property_name = \array_shift($key_parts); $new_base_key = $base_key . $divider . $property_name; if (!isset($existing_keys[$new_base_key])) { $new_base_type = null; foreach ($existing_keys[$base_key]->getAtomicTypes() as $existing_key_type_part) { if ($existing_key_type_part instanceof \Psalm\Type\Atomic\TNull) { $class_property_type = \Psalm\Type::getNull(); } elseif ($existing_key_type_part instanceof \Psalm\Type\Atomic\TMixed || $existing_key_type_part instanceof \Psalm\Type\Atomic\TTemplateParam || $existing_key_type_part instanceof \Psalm\Type\Atomic\TObject || $existing_key_type_part instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($existing_key_type_part->value) === 'stdclass') { $class_property_type = \Psalm\Type::getMixed(); } elseif ($existing_key_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { if (!$codebase->classOrInterfaceExists($existing_key_type_part->value)) { $class_property_type = \Psalm\Type::getMixed(); } else { if (\substr($property_name, -2) === '()') { $method_id = new \Psalm\Internal\MethodIdentifier($existing_key_type_part->value, \strtolower(\substr($property_name, 0, -2))); if (!$codebase->methods->methodExists($method_id)) { return null; } $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if ($declaring_method_id === null) { return null; } $declaring_class = $declaring_method_id->fq_class_name; $method_return_type = $codebase->methods->getMethodReturnType($method_id, $declaring_class, null, null); if ($method_return_type) { $class_property_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, clone $method_return_type, $declaring_class, $declaring_class, null); } else { $class_property_type = \Psalm\Type::getMixed(); } } else { $class_property_type = self::getPropertyType($codebase, $existing_key_type_part->value, $property_name); if (!$class_property_type) { return null; } } } } else { $class_property_type = \Psalm\Type::getMixed(); } if ($new_base_type instanceof \Psalm\Type\Union) { $new_base_type = \Psalm\Type::combineUnionTypes($new_base_type, $class_property_type, $codebase); } else { $new_base_type = $class_property_type; } $existing_keys[$new_base_key] = $new_base_type; } } $base_key = $new_base_key; } else { return null; } } if (!isset($existing_keys[$base_key])) { if ($code_location) { \Psalm\IssueBuffer::add(new \Psalm\Issue\PsalmInternalError('Unknown key ' . $base_key, $code_location)); } return null; } return $existing_keys[$base_key]; } private static function getPropertyType(\Psalm\Codebase $codebase, string $fq_class_name, string $property_name) : ?\Psalm\Type\Union { $property_id = $fq_class_name . '::$' . $property_name; if (!$codebase->properties->propertyExists($property_id, \true)) { $declaring_class_storage = $codebase->classlike_storage_provider->get($fq_class_name); if (isset($declaring_class_storage->pseudo_property_get_types['$' . $property_name])) { return clone $declaring_class_storage->pseudo_property_get_types['$' . $property_name]; } return null; } $declaring_property_class = $codebase->properties->getDeclaringClassForProperty($property_id, \true); if ($declaring_property_class === null) { return null; } $class_property_type = $codebase->properties->getPropertyType($property_id, \false, null, null); $declaring_class_storage = $codebase->classlike_storage_provider->get($declaring_property_class); if ($class_property_type) { return \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, clone $class_property_type, $declaring_class_storage->name, $declaring_class_storage->name, null); } return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * */ protected static function triggerIssueForImpossible(\Psalm\Type\Union $existing_var_type, string $old_var_type_string, string $key, string $assertion, bool $redundant, bool $negated, \Psalm\CodeLocation $code_location, array $suppressed_issues) : void { $not = $assertion[0] === '!'; if ($not) { $assertion = \substr($assertion, 1); } if ($negated) { $redundant = !$redundant; $not = !$not; } $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $from_docblock = $existing_var_type->from_docblock || isset($existing_var_atomic_types[$assertion]) && $existing_var_atomic_types[$assertion]->from_docblock; if ($redundant) { if ($from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType('Docblock-defined type ' . $old_var_type_string . ' for ' . $key . ' is ' . ($not ? 'never ' : 'always ') . $assertion, $code_location, $old_var_type_string . ' ' . $assertion), $suppressed_issues)) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition('Type ' . $old_var_type_string . ' for ' . $key . ' is ' . ($not ? 'never ' : 'always ') . $assertion, $code_location, $old_var_type_string . ' ' . $assertion), $suppressed_issues)) { // fall through } } } else { if ($from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction('Docblock-defined type ' . $old_var_type_string . ' for ' . $key . ' is ' . ($not ? 'always ' : 'never ') . $assertion, $code_location, $old_var_type_string . ' ' . $assertion), $suppressed_issues)) { // fall through } } else { if ($assertion === 'null' && !$not) { $issue = new \Psalm\Issue\TypeDoesNotContainNull('Type ' . $old_var_type_string . ' for ' . $key . ' is never ' . $assertion, $code_location, $old_var_type_string . ' ' . $assertion); } else { $issue = new \Psalm\Issue\TypeDoesNotContainType('Type ' . $old_var_type_string . ' for ' . $key . ' is ' . ($not ? 'always ' : 'never ') . $assertion, $code_location, $old_var_type_string . ' ' . $assertion); } if (\Psalm\IssueBuffer::accepts($issue, $suppressed_issues)) { // fall through } } } } /** * @param string[] $key_parts * @param array $existing_types * @param array $changed_var_ids */ private static function adjustTKeyedArrayType(array $key_parts, array &$existing_types, array &$changed_var_ids, \Psalm\Type\Union $result_type) : void { \array_pop($key_parts); $array_key = \array_pop($key_parts); \array_pop($key_parts); if ($array_key === null) { throw new \UnexpectedValueException('Not expecting null array key'); } if ($array_key[0] === '$') { return; } $array_key_offset = $array_key[0] === '\'' || $array_key[0] === '"' ? \substr($array_key, 1, -1) : $array_key; $base_key = \implode($key_parts); if (isset($existing_types[$base_key]) && $array_key_offset !== \false) { foreach ($existing_types[$base_key]->getAtomicTypes() as $base_atomic_type) { if ($base_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $base_atomic_type instanceof \Psalm\Type\Atomic\TArray && !$base_atomic_type->type_params[1]->isEmpty() || $base_atomic_type instanceof \Psalm\Type\Atomic\TList || $base_atomic_type instanceof \Psalm\Type\Atomic\TClassStringMap) { $new_base_type = clone $existing_types[$base_key]; if ($base_atomic_type instanceof \Psalm\Type\Atomic\TArray) { $previous_key_type = clone $base_atomic_type->type_params[0]; $previous_value_type = clone $base_atomic_type->type_params[1]; $base_atomic_type = new \Psalm\Type\Atomic\TKeyedArray([$array_key_offset => clone $result_type], null); if (!$previous_key_type->isEmpty()) { $base_atomic_type->previous_key_type = $previous_key_type; } $base_atomic_type->previous_value_type = $previous_value_type; } elseif ($base_atomic_type instanceof \Psalm\Type\Atomic\TList) { $previous_key_type = \Psalm\Type::getInt(); $previous_value_type = clone $base_atomic_type->type_param; $base_atomic_type = new \Psalm\Type\Atomic\TKeyedArray([$array_key_offset => clone $result_type], null); $base_atomic_type->is_list = \true; $base_atomic_type->previous_key_type = $previous_key_type; $base_atomic_type->previous_value_type = $previous_value_type; } elseif ($base_atomic_type instanceof \Psalm\Type\Atomic\TClassStringMap) { // do nothing } else { $base_atomic_type = clone $base_atomic_type; $base_atomic_type->properties[$array_key_offset] = clone $result_type; } $new_base_type->addType($base_atomic_type); $changed_var_ids[$base_key . '[' . $array_key . ']'] = \true; if ($key_parts[\count($key_parts) - 1] === ']') { self::adjustTKeyedArrayType($key_parts, $existing_types, $changed_var_ids, $new_base_type); } $existing_types[$base_key] = $new_base_type; break; } } } } } */ public $uses; /** * @var array */ public $uses_flipped; /** * @var array */ public $functions; /** * @var array */ public $functions_flipped; /** * @var array */ public $constants; /** * @var array */ public $constants_flipped; /** @var string|null */ public $namespace; /** @var ?int */ public $namespace_first_stmt_start; /** @var ?int */ public $uses_start; /** @var ?int */ public $uses_end; /** * @param array $uses * @param array $functions * @param array $constants * @param array $uses_flipped * @param array $functions_flipped * @param array $constants_flipped */ public function __construct(?string $namespace = null, array $uses = [], array $functions = [], array $constants = [], array $uses_flipped = [], array $functions_flipped = [], array $constants_flipped = []) { $this->namespace = $namespace; $this->uses = $uses; $this->functions = $functions; $this->constants = $constants; $this->uses_flipped = $uses_flipped; $this->functions_flipped = $functions_flipped; $this->constants_flipped = $constants_flipped; } } > */ public $use_referencing_locations = []; /** * A map of file names to the classes that they contain explicit references to * used in collaboration with use_referencing_locations * * @var array> */ public $use_referencing_files = []; /** * @var FileStorageProvider */ public $file_storage_provider; /** * @var ClassLikeStorageProvider */ public $classlike_storage_provider; /** * @var bool */ public $collect_references = \false; /** * @var bool */ public $collect_locations = \false; /** * @var null|'always'|'auto' */ public $find_unused_code = null; /** * @var FileProvider */ public $file_provider; /** * @var FileReferenceProvider */ public $file_reference_provider; /** * @var StatementsProvider */ public $statements_provider; /** * @var Progress */ private $progress; /** * @var array */ private static $stubbed_constants = []; /** * Whether to register autoloaded information * * @var bool */ public $register_autoload_files = \false; /** * Whether to log functions just at the file level or globally (for stubs) * * @var bool */ public $register_stub_files = \false; /** * @var bool */ public $find_unused_variables = \false; /** * @var Internal\Codebase\Scanner */ public $scanner; /** * @var Internal\Codebase\Analyzer */ public $analyzer; /** * @var Internal\Codebase\Functions */ public $functions; /** * @var Internal\Codebase\ClassLikes */ public $classlikes; /** * @var Internal\Codebase\Methods */ public $methods; /** * @var Internal\Codebase\Properties */ public $properties; /** * @var Internal\Codebase\Populator */ public $populator; /** * @var ?Internal\Codebase\TaintFlowGraph */ public $taint_flow_graph = null; /** * @var bool */ public $server_mode = \false; /** * @var bool */ public $store_node_types = \false; /** * Whether or not to infer types from usage. Computationally expensive, so turned off by default * * @var bool */ public $infer_types_from_usage = \false; /** * @var bool */ public $alter_code = \false; /** * @var bool */ public $diff_methods = \false; /** * @var array */ public $methods_to_move = []; /** * @var array */ public $methods_to_rename = []; /** * @var array */ public $properties_to_move = []; /** * @var array */ public $properties_to_rename = []; /** * @var array */ public $class_constants_to_move = []; /** * @var array */ public $class_constants_to_rename = []; /** * @var array */ public $classes_to_move = []; /** * @var array */ public $call_transforms = []; /** * @var array */ public $property_transforms = []; /** * @var array */ public $class_constant_transforms = []; /** * @var array */ public $class_transforms = []; /** * @var bool */ public $allow_backwards_incompatible_changes = \true; /** * @var int */ public $php_major_version = \PHP_MAJOR_VERSION; /** * @var int */ public $php_minor_version = \PHP_MINOR_VERSION; /** * @var bool */ public $track_unused_suppressions = \false; public function __construct(\Psalm\Config $config, \Psalm\Internal\Provider\Providers $providers, ?\Psalm\Progress\Progress $progress = null) { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } $this->config = $config; $this->file_storage_provider = $providers->file_storage_provider; $this->classlike_storage_provider = $providers->classlike_storage_provider; $this->progress = $progress; $this->file_provider = $providers->file_provider; $this->file_reference_provider = $providers->file_reference_provider; $this->statements_provider = $providers->statements_provider; self::$stubbed_constants = []; $reflection = new \Psalm\Internal\Codebase\Reflection($providers->classlike_storage_provider, $this); $this->scanner = new \Psalm\Internal\Codebase\Scanner($this, $config, $providers->file_storage_provider, $providers->file_provider, $reflection, $providers->file_reference_provider, $progress); $this->loadAnalyzer(); $this->functions = new \Psalm\Internal\Codebase\Functions($providers->file_storage_provider, $reflection); $this->properties = new \Psalm\Internal\Codebase\Properties($providers->classlike_storage_provider, $providers->file_reference_provider); $this->classlikes = new \Psalm\Internal\Codebase\ClassLikes($this->config, $providers->classlike_storage_provider, $providers->file_reference_provider, $providers->statements_provider, $this->scanner); $this->methods = new \Psalm\Internal\Codebase\Methods($providers->classlike_storage_provider, $providers->file_reference_provider, $this->classlikes); $this->populator = new \Psalm\Internal\Codebase\Populator($config, $providers->classlike_storage_provider, $providers->file_storage_provider, $this->classlikes, $providers->file_reference_provider, $progress); $this->loadAnalyzer(); } private function loadAnalyzer() : void { $this->analyzer = new \Psalm\Internal\Codebase\Analyzer($this->config, $this->file_provider, $this->file_storage_provider, $this->progress); } /** * @param array $candidate_files * */ public function reloadFiles(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, array $candidate_files) : void { $this->loadAnalyzer(); $this->file_reference_provider->loadReferenceCache(\false); \Psalm\Internal\Analyzer\FunctionLikeAnalyzer::clearCache(); if (!$this->statements_provider->parser_cache_provider) { $diff_files = $candidate_files; } else { $diff_files = []; $parser_cache_provider = $this->statements_provider->parser_cache_provider; foreach ($candidate_files as $candidate_file_path) { if ($parser_cache_provider->loadExistingFileContentsFromCache($candidate_file_path) !== $this->file_provider->getContents($candidate_file_path)) { $diff_files[] = $candidate_file_path; } } } $referenced_files = $project_analyzer->getReferencedFilesFromDiff($diff_files, \false); foreach ($diff_files as $diff_file_path) { $this->invalidateInformationForFile($diff_file_path); } foreach ($referenced_files as $referenced_file_path) { if (\in_array($referenced_file_path, $diff_files, \true)) { continue; } $file_storage = $this->file_storage_provider->get($referenced_file_path); foreach ($file_storage->classlikes_in_file as $fq_classlike_name) { $this->classlike_storage_provider->remove($fq_classlike_name); $this->classlikes->removeClassLike($fq_classlike_name); } $this->file_storage_provider->remove($referenced_file_path); $this->scanner->removeFile($referenced_file_path); } $referenced_files = \array_combine($referenced_files, $referenced_files); $this->scanner->addFilesToDeepScan($referenced_files); $this->addFilesToAnalyze(\array_combine($candidate_files, $candidate_files)); $this->scanner->scanFiles($this->classlikes); $this->file_reference_provider->updateReferenceCache($this, $referenced_files); $this->populator->populateCodebase(); } public function enterServerMode() : void { $this->server_mode = \true; $this->store_node_types = \true; } public function collectLocations() : void { $this->collect_locations = \true; $this->classlikes->collect_locations = \true; $this->methods->collect_locations = \true; $this->properties->collect_locations = \true; } /** * @param 'always'|'auto' $find_unused_code * */ public function reportUnusedCode(string $find_unused_code = 'auto') : void { $this->collect_references = \true; $this->classlikes->collect_references = \true; $this->find_unused_code = $find_unused_code; $this->find_unused_variables = \true; } public function reportUnusedVariables() : void { $this->collect_references = \true; $this->find_unused_variables = \true; } /** * @param array $files_to_analyze * */ public function addFilesToAnalyze(array $files_to_analyze) : void { $this->scanner->addFilesToDeepScan($files_to_analyze); $this->analyzer->addFilesToAnalyze($files_to_analyze); } /** * Scans all files their related files * */ public function scanFiles(int $threads = 1) : void { $has_changes = $this->scanner->scanFiles($this->classlikes, $threads); if ($has_changes) { $this->populator->populateCodebase(); } } public function getFileContents(string $file_path) : string { return $this->file_provider->getContents($file_path); } /** * @return list */ public function getStatementsForFile(string $file_path) : array { return $this->statements_provider->getStatementsForFile($file_path, $this->php_major_version . '.' . $this->php_minor_version, $this->progress); } public function createClassLikeStorage(string $fq_classlike_name) : \Psalm\Storage\ClassLikeStorage { return $this->classlike_storage_provider->create($fq_classlike_name); } public function cacheClassLikeStorage(\Psalm\Storage\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); } } public function exhumeClassLikeStorage(string $fq_classlike_name, string $file_path) : void { $file_contents = $this->file_provider->getContents($file_path); $storage = $this->classlike_storage_provider->exhume($fq_classlike_name, $file_path, $file_contents); if ($storage->is_trait) { $this->classlikes->addFullyQualifiedTraitName($storage->name, $file_path); } elseif ($storage->is_interface) { $this->classlikes->addFullyQualifiedInterfaceName($storage->name, $file_path); } else { $this->classlikes->addFullyQualifiedClassName($storage->name, $file_path); } } public static function getPsalmTypeFromReflection(?\ReflectionType $type) : \Psalm\Type\Union { return \Psalm\Internal\Codebase\Reflection::getPsalmTypeFromReflectionType($type); } public function createFileStorageForPath(string $file_path) : \Psalm\Storage\FileStorage { return $this->file_storage_provider->create($file_path); } /** * @return array */ public function findReferencesToSymbol(string $symbol) : array { if (!$this->collect_locations) { throw new \UnexpectedValueException('Should not be checking references'); } if (\strpos($symbol, '::$') !== \false) { return $this->findReferencesToProperty($symbol); } if (\strpos($symbol, '::') !== \false) { return $this->findReferencesToMethod($symbol); } return $this->findReferencesToClassLike($symbol); } /** * @return array */ public function findReferencesToMethod(string $method_id) : array { return $this->file_reference_provider->getClassMethodLocations(\strtolower($method_id)); } /** * @return array */ public function findReferencesToProperty(string $property_id) : array { [$fq_class_name, $property_name] = \explode('::', $property_id); return $this->file_reference_provider->getClassPropertyLocations(\strtolower($fq_class_name) . '::' . $property_name); } /** * @return CodeLocation[] * * @psalm-return array */ public function findReferencesToClassLike(string $fq_class_name) : array { $fq_class_name_lc = \strtolower($fq_class_name); $locations = $this->file_reference_provider->getClassLocations($fq_class_name_lc); if (isset($this->use_referencing_locations[$fq_class_name_lc])) { $locations = \array_merge($locations, $this->use_referencing_locations[$fq_class_name_lc]); } return $locations; } public function getClosureStorage(string $file_path, string $closure_id) : \Psalm\Storage\FunctionStorage { $file_storage = $this->file_storage_provider->get($file_path); // closures can be returned here if (isset($file_storage->functions[$closure_id])) { return $file_storage->functions[$closure_id]; } throw new \UnexpectedValueException('Expecting ' . $closure_id . ' to have storage in ' . $file_path); } public function addGlobalConstantType(string $const_id, \Psalm\Type\Union $type) : void { self::$stubbed_constants[$const_id] = $type; } public function getStubbedConstantType(string $const_id) : ?\Psalm\Type\Union { return isset(self::$stubbed_constants[$const_id]) ? self::$stubbed_constants[$const_id] : null; } /** * @return array */ public function getAllStubbedConstants() : array { return self::$stubbed_constants; } public function fileExists(string $file_path) : bool { return $this->file_provider->fileExists($file_path); } /** * Check whether a class/interface exists */ public function classOrInterfaceExists(string $fq_class_name, ?\Psalm\CodeLocation $code_location = null, ?string $calling_fq_class_name = null, ?string $calling_method_id = null) : bool { return $this->classlikes->classOrInterfaceExists($fq_class_name, $code_location, $calling_fq_class_name, $calling_method_id); } public function classExtendsOrImplements(string $fq_class_name, string $possible_parent) : bool { return $this->classlikes->classExtends($fq_class_name, $possible_parent) || $this->classlikes->classImplements($fq_class_name, $possible_parent); } /** * Determine whether or not a given class exists */ public function classExists(string $fq_class_name, ?\Psalm\CodeLocation $code_location = null, ?string $calling_fq_class_name = null, ?string $calling_method_id = null) : bool { return $this->classlikes->classExists($fq_class_name, $code_location, $calling_fq_class_name, $calling_method_id); } /** * Determine whether or not a class extends a parent * * @throws \Psalm\Exception\UnpopulatedClasslikeException when called on unpopulated class * @throws \InvalidArgumentException when class does not exist */ public function classExtends(string $fq_class_name, string $possible_parent) : bool { return $this->classlikes->classExtends($fq_class_name, $possible_parent, \true); } /** * Check whether a class implements an interface */ public function classImplements(string $fq_class_name, string $interface) : bool { return $this->classlikes->classImplements($fq_class_name, $interface); } public function interfaceExists(string $fq_interface_name, ?\Psalm\CodeLocation $code_location = null, ?string $calling_fq_class_name = null, ?string $calling_method_id = null) : bool { return $this->classlikes->interfaceExists($fq_interface_name, $code_location, $calling_fq_class_name, $calling_method_id); } public function interfaceExtends(string $interface_name, string $possible_parent) : bool { return $this->classlikes->interfaceExtends($interface_name, $possible_parent); } /** * @return array all interfaces extended by $interface_name */ public function getParentInterfaces(string $fq_interface_name) : array { return $this->classlikes->getParentInterfaces($this->classlikes->getUnAliasedName($fq_interface_name)); } /** * Determine whether or not a class has the correct casing */ public function classHasCorrectCasing(string $fq_class_name) : bool { return $this->classlikes->classHasCorrectCasing($fq_class_name); } public function interfaceHasCorrectCasing(string $fq_interface_name) : bool { return $this->classlikes->interfaceHasCorrectCasing($fq_interface_name); } public function traitHasCorrectCase(string $fq_trait_name) : bool { return $this->classlikes->traitHasCorrectCase($fq_trait_name); } /** * Given a function id, return the function like storage for * a method, closure, or function. * * @param non-empty-string $function_id * * @return Storage\FunctionStorage|Storage\MethodStorage */ public function getFunctionLikeStorage(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $function_id) : \Psalm\Storage\FunctionLikeStorage { $doesMethodExist = \Psalm\Internal\MethodIdentifier::isValidMethodIdReference($function_id) && $this->methodExists($function_id); if ($doesMethodExist) { $method_id = \Psalm\Internal\MethodIdentifier::wrap($function_id); $declaring_method_id = $this->methods->getDeclaringMethodId($method_id); if (!$declaring_method_id) { throw new \UnexpectedValueException('Declaring method for ' . $method_id . ' cannot be found'); } return $this->methods->getStorage($declaring_method_id); } return $this->functions->getStorage($statements_analyzer, \strtolower($function_id)); } /** * Whether or not a given method exists * * @param string|\Psalm\Internal\MethodIdentifier $method_id * @param string|\Psalm\Internal\MethodIdentifier|null $calling_method_id * @return bool */ public function methodExists($method_id, ?\Psalm\CodeLocation $code_location = null, $calling_method_id = null, ?string $file_path = null) : bool { return $this->methods->methodExists(\Psalm\Internal\MethodIdentifier::wrap($method_id), \is_string($calling_method_id) ? \strtolower($calling_method_id) : \strtolower((string) $calling_method_id), $code_location, null, $file_path); } /** * @param string|\Psalm\Internal\MethodIdentifier $method_id * * @return array */ public function getMethodParams($method_id) : array { return $this->methods->getMethodParams(\Psalm\Internal\MethodIdentifier::wrap($method_id)); } /** * @param string|\Psalm\Internal\MethodIdentifier $method_id * */ public function isVariadic($method_id) : bool { return $this->methods->isVariadic(\Psalm\Internal\MethodIdentifier::wrap($method_id)); } /** * @param string|\Psalm\Internal\MethodIdentifier $method_id * @param array $call_args * */ public function getMethodReturnType($method_id, ?string &$self_class, array $call_args = []) : ?\Psalm\Type\Union { return $this->methods->getMethodReturnType(\Psalm\Internal\MethodIdentifier::wrap($method_id), $self_class, null, $call_args); } /** * @param string|\Psalm\Internal\MethodIdentifier $method_id * */ public function getMethodReturnsByRef($method_id) : bool { return $this->methods->getMethodReturnsByRef(\Psalm\Internal\MethodIdentifier::wrap($method_id)); } /** * @param string|\Psalm\Internal\MethodIdentifier $method_id * @param CodeLocation|null $defined_location * */ public function getMethodReturnTypeLocation($method_id, \Psalm\CodeLocation &$defined_location = null) : ?\Psalm\CodeLocation { return $this->methods->getMethodReturnTypeLocation(\Psalm\Internal\MethodIdentifier::wrap($method_id), $defined_location); } /** * @param string|\Psalm\Internal\MethodIdentifier $method_id * */ public function getDeclaringMethodId($method_id) : ?string { return $this->methods->getDeclaringMethodId(\Psalm\Internal\MethodIdentifier::wrap($method_id)); } /** * Get the class this method appears in (vs is declared in, which could give a trait) * * @param string|\Psalm\Internal\MethodIdentifier $method_id * */ public function getAppearingMethodId($method_id) : ?string { return $this->methods->getAppearingMethodId(\Psalm\Internal\MethodIdentifier::wrap($method_id)); } /** * @param string|\Psalm\Internal\MethodIdentifier $method_id * * @return array */ public function getOverriddenMethodIds($method_id) : array { return $this->methods->getOverriddenMethodIds(\Psalm\Internal\MethodIdentifier::wrap($method_id)); } /** * @param string|\Psalm\Internal\MethodIdentifier $method_id * */ public function getCasedMethodId($method_id) : string { return $this->methods->getCasedMethodId(\Psalm\Internal\MethodIdentifier::wrap($method_id)); } public function invalidateInformationForFile(string $file_path) : void { $this->scanner->removeFile($file_path); try { $file_storage = $this->file_storage_provider->get($file_path); } catch (\InvalidArgumentException $e) { return; } foreach ($file_storage->classlikes_in_file as $fq_classlike_name) { $this->classlike_storage_provider->remove($fq_classlike_name); $this->classlikes->removeClassLike($fq_classlike_name); } $this->file_storage_provider->remove($file_path); } public function getSymbolInformation(string $file_path, string $symbol) : ?string { if (\is_numeric($symbol[0])) { return \preg_replace('/^[^:]*:/', '', $symbol); } try { if (\strpos($symbol, '::')) { if (\strpos($symbol, '()')) { $symbol = \substr($symbol, 0, -2); /** @psalm-suppress ArgumentTypeCoercion */ $method_id = new \Psalm\Internal\MethodIdentifier(...\explode('::', $symbol)); $declaring_method_id = $this->methods->getDeclaringMethodId($method_id); if (!$declaring_method_id) { return null; } $storage = $this->methods->getStorage($declaring_method_id); return 'getSignature(\true); } [, $symbol_name] = \explode('::', $symbol); if (\strpos($symbol, '$') !== \false) { $storage = $this->properties->getStorage($symbol); return 'getInfo() . ' ' . $symbol_name; } [$fq_classlike_name, $const_name] = \explode('::', $symbol); $class_constants = $this->classlikes->getConstantsForClass($fq_classlike_name, \ReflectionProperty::IS_PRIVATE); if (!isset($class_constants[$const_name])) { return null; } return 'file_storage_provider->get($file_path); if (isset($file_storage->functions[$function_id])) { $function_storage = $file_storage->functions[$function_id]; return 'getSignature(\true); } if (!$function_id) { return null; } $function = $this->functions->getStorage(null, $function_id); return 'getSignature(\true); } $storage = $this->classlike_storage_provider->get($symbol); return 'abstract ? 'abstract ' : '') . 'class ' . $storage->name; } catch (\Exception $e) { \error_log($e->getMessage()); return null; } } public function getSymbolLocation(string $file_path, string $symbol) : ?\Psalm\CodeLocation { if (\is_numeric($symbol[0])) { $symbol = \preg_replace('/:.*/', '', $symbol); $symbol_parts = \explode('-', $symbol); $file_contents = $this->getFileContents($file_path); return new \Psalm\CodeLocation\Raw($file_contents, $file_path, $this->config->shortenFileName($file_path), (int) $symbol_parts[0], (int) $symbol_parts[1]); } try { if (\strpos($symbol, '::')) { if (\strpos($symbol, '()')) { $symbol = \substr($symbol, 0, -2); /** @psalm-suppress ArgumentTypeCoercion */ $method_id = new \Psalm\Internal\MethodIdentifier(...\explode('::', $symbol)); $declaring_method_id = $this->methods->getDeclaringMethodId($method_id); if (!$declaring_method_id) { return null; } $storage = $this->methods->getStorage($declaring_method_id); return $storage->location; } if (\strpos($symbol, '$') !== \false) { $storage = $this->properties->getStorage($symbol); return $storage->location; } [$fq_classlike_name, $const_name] = \explode('::', $symbol); $class_constants = $this->classlikes->getConstantsForClass($fq_classlike_name, \ReflectionProperty::IS_PRIVATE); if (!isset($class_constants[$const_name])) { return null; } return $class_constants[$const_name]->location; } if (\strpos($symbol, '()')) { $file_storage = $this->file_storage_provider->get($file_path); $function_id = \strtolower(\substr($symbol, 0, -2)); if (isset($file_storage->functions[$function_id])) { return $file_storage->functions[$function_id]->location; } if (!$function_id) { return null; } $function = $this->functions->getStorage(null, $function_id); return $function->location; } $storage = $this->classlike_storage_provider->get($symbol); return $storage->location; } catch (\UnexpectedValueException $e) { \error_log($e->getMessage()); return null; } catch (\InvalidArgumentException $e) { return null; } } /** * @return array{0: string, 1: Range}|null */ public function getReferenceAtPosition(string $file_path, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position $position) : ?array { $is_open = $this->file_provider->isOpen($file_path); if (!$is_open) { throw new \Psalm\Exception\UnanalyzedFileException($file_path . ' is not open'); } $file_contents = $this->getFileContents($file_path); $offset = $position->toOffset($file_contents); [$reference_map, $type_map] = $this->analyzer->getMapsForFile($file_path); $reference = null; if (!$reference_map && !$type_map) { return null; } $reference_start_pos = null; $reference_end_pos = null; \ksort($reference_map); foreach ($reference_map as $start_pos => [$end_pos, $possible_reference]) { if ($offset < $start_pos) { break; } if ($offset > $end_pos) { continue; } $reference_start_pos = $start_pos; $reference_end_pos = $end_pos; $reference = $possible_reference; } if ($reference === null || $reference_start_pos === null || $reference_end_pos === null) { return null; } $range = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Range(self::getPositionFromOffset($reference_start_pos, $file_contents), self::getPositionFromOffset($reference_end_pos, $file_contents)); return [$reference, $range]; } /** * @return array{0: non-empty-string, 1: int, 2: Range}|null */ public function getFunctionArgumentAtPosition(string $file_path, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position $position) : ?array { $is_open = $this->file_provider->isOpen($file_path); if (!$is_open) { throw new \Psalm\Exception\UnanalyzedFileException($file_path . ' is not open'); } $file_contents = $this->getFileContents($file_path); $offset = $position->toOffset($file_contents); [, , $argument_map] = $this->analyzer->getMapsForFile($file_path); $reference = null; $argument_number = null; if (!$argument_map) { return null; } $start_pos = null; $end_pos = null; \ksort($argument_map); foreach ($argument_map as $start_pos => [$end_pos, $possible_reference, $possible_argument_number]) { if ($offset < $start_pos) { break; } if ($offset > $end_pos) { continue; } $reference = $possible_reference; $argument_number = $possible_argument_number; } if ($reference === null || $start_pos === null || $end_pos === null || $argument_number === null) { return null; } $range = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Range(self::getPositionFromOffset($start_pos, $file_contents), self::getPositionFromOffset($end_pos, $file_contents)); return [$reference, $argument_number, $range]; } /** * @param non-empty-string $function_symbol */ public function getSignatureInformation(string $function_symbol) : ?\_HumbugBoxd02f763d3c56\LanguageServerProtocol\SignatureInformation { if (\strpos($function_symbol, '::') !== \false) { /** @psalm-suppress ArgumentTypeCoercion */ $method_id = new \Psalm\Internal\MethodIdentifier(...\explode('::', $function_symbol)); $declaring_method_id = $this->methods->getDeclaringMethodId($method_id); if ($declaring_method_id === null) { return null; } $method_storage = $this->methods->getStorage($declaring_method_id); $params = $method_storage->params; } else { try { $function_storage = $this->functions->getStorage(null, \strtolower($function_symbol)); $params = $function_storage->params; } catch (\Exception $exception) { if (\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($function_symbol)) { $callables = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallablesFromCallMap($function_symbol); if (!$callables || !$callables[0]->params) { return null; } $params = $callables[0]->params; } else { return null; } } } $signature_label = '('; $parameters = []; foreach ($params as $i => $param) { $parameter_label = ($param->type ?: 'mixed') . ' $' . $param->name; $parameters[] = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\ParameterInformation([\strlen($signature_label), \strlen($signature_label) + \strlen($parameter_label)]); $signature_label .= $parameter_label; if ($i < \count($params) - 1) { $signature_label .= ', '; } } $signature_label .= ')'; return new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\SignatureInformation($signature_label, $parameters); } /** * @return array{0: string, 1: '->'|'::'|'symbol', 2: int}|null */ public function getCompletionDataAtPosition(string $file_path, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position $position) : ?array { $is_open = $this->file_provider->isOpen($file_path); if (!$is_open) { throw new \Psalm\Exception\UnanalyzedFileException($file_path . ' is not open'); } $file_contents = $this->getFileContents($file_path); $offset = $position->toOffset($file_contents); [$reference_map, $type_map] = $this->analyzer->getMapsForFile($file_path); if (!$reference_map && !$type_map) { return null; } \krsort($type_map); foreach ($type_map as $start_pos => [$end_pos_excluding_whitespace, $possible_type]) { if ($offset < $start_pos) { continue; } $num_whitespace_bytes = \preg_match('/\\G\\s+/', $file_contents, $matches, 0, $end_pos_excluding_whitespace) ? \strlen($matches[0]) : 0; $end_pos = $end_pos_excluding_whitespace + $num_whitespace_bytes; if ($offset - $end_pos === 2 || $offset - $end_pos === 3) { $candidate_gap = \substr($file_contents, $end_pos, 2); if ($candidate_gap === '->' || $candidate_gap === '::') { $gap = $candidate_gap; $recent_type = $possible_type; if ($recent_type === 'mixed') { return null; } return [$recent_type, $gap, $offset]; } } } foreach ($reference_map as $start_pos => [$end_pos, $possible_reference]) { if ($offset < $start_pos || $possible_reference[0] !== '*') { continue; } if ($offset - $end_pos === 0) { $recent_type = $possible_reference; return [$recent_type, 'symbol', $offset]; } } return null; } /** * @return list<\LanguageServerProtocol\CompletionItem> */ public function getCompletionItemsForClassishThing(string $type_string, string $gap) : array { $instance_completion_items = []; $static_completion_items = []; $type = \Psalm\Type::parseString($type_string); foreach ($type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { try { $class_storage = $this->classlike_storage_provider->get($atomic_type->value); foreach ($class_storage->appearing_method_ids as $declaring_method_id) { $method_storage = $this->methods->getStorage($declaring_method_id); $completion_item = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionItem($method_storage->cased_name, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionItemKind::METHOD, (string) $method_storage, null, (string) $method_storage->visibility, $method_storage->cased_name, $method_storage->cased_name . (\count($method_storage->params) !== 0 ? '($0)' : '()'), null, null, new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Command('Trigger parameter hints', 'editor.action.triggerParameterHints')); $completion_item->insertTextFormat = \_HumbugBoxd02f763d3c56\LanguageServerProtocol\InsertTextFormat::SNIPPET; if ($method_storage->is_static) { $static_completion_items[] = $completion_item; } else { $instance_completion_items[] = $completion_item; } } foreach ($class_storage->declaring_property_ids as $property_name => $declaring_class) { $property_storage = $this->properties->getStorage($declaring_class . '::$' . $property_name); $completion_item = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionItem('$' . $property_name, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionItemKind::PROPERTY, $property_storage->getInfo(), null, (string) $property_storage->visibility, $property_name, ($gap === '::' ? '$' : '') . $property_name); if ($property_storage->is_static) { $static_completion_items[] = $completion_item; } else { $instance_completion_items[] = $completion_item; } } foreach ($class_storage->constants as $const_name => $_) { $static_completion_items[] = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionItem($const_name, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionItemKind::VARIABLE, 'const ' . $const_name, null, null, $const_name, $const_name); } } catch (\Exception $e) { \error_log($e->getMessage()); continue; } } } if ($gap === '->') { $completion_items = $instance_completion_items; } else { $completion_items = \array_merge($instance_completion_items, $static_completion_items); } return $completion_items; } /** * @return list<\LanguageServerProtocol\CompletionItem> */ public function getCompletionItemsForPartialSymbol(string $type_string, int $offset, string $file_path) : array { $matching_classlike_names = $this->classlikes->getMatchingClassLikeNames($type_string); $completion_items = []; $file_storage = $this->file_storage_provider->get($file_path); $aliases = null; foreach ($file_storage->classlikes_in_file as $fq_class_name => $_) { try { $class_storage = $this->classlike_storage_provider->get($fq_class_name); } catch (\Exception $e) { continue; } if (!$class_storage->stmt_location) { continue; } if ($offset > $class_storage->stmt_location->raw_file_start && $offset < $class_storage->stmt_location->raw_file_end) { $aliases = $class_storage->aliases; break; } } if (!$aliases) { foreach ($file_storage->namespace_aliases as $namespace_start => $namespace_aliases) { if ($namespace_start < $offset) { $aliases = $namespace_aliases; break; } } if (!$aliases) { $aliases = $file_storage->aliases; } } foreach ($matching_classlike_names as $fq_class_name) { $extra_edits = []; $insertion_text = \Psalm\Type::getStringFromFQCLN($fq_class_name, $aliases && $aliases->namespace ? $aliases->namespace : null, $aliases ? $aliases->uses_flipped : [], null); if ($aliases && $aliases->namespace && $insertion_text === '\\' . $fq_class_name && $aliases->namespace_first_stmt_start) { $file_contents = $this->getFileContents($file_path); $class_name = \preg_replace('/^.*\\\\/', '', $fq_class_name); if ($aliases->uses_end) { $position = self::getPositionFromOffset($aliases->uses_end, $file_contents); $extra_edits[] = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextEdit(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Range($position, $position), "\n" . 'use ' . $fq_class_name . ';'); } else { $position = self::getPositionFromOffset($aliases->namespace_first_stmt_start, $file_contents); $extra_edits[] = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextEdit(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Range($position, $position), 'use ' . $fq_class_name . ';' . "\n" . "\n"); } $insertion_text = $class_name; } $completion_items[] = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionItem($fq_class_name, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionItemKind::CLASS_, null, null, null, $fq_class_name, $insertion_text, null, $extra_edits); } return $completion_items; } private static function getPositionFromOffset(int $offset, string $file_contents) : \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position { $file_contents = \substr($file_contents, 0, $offset); $before_newline_count = \strrpos($file_contents, "\n", $offset - \strlen($file_contents)); return new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position(\substr_count($file_contents, "\n"), $offset - (int) $before_newline_count - 1); } public function addTemporaryFileChanges(string $file_path, string $new_content) : void { $this->file_provider->addTemporaryFileChanges($file_path, $new_content); } public function removeTemporaryFileChanges(string $file_path) : void { $this->file_provider->removeTemporaryFileChanges($file_path); } /** * Checks if type is a subtype of other * * Given two types, checks if `$input_type` is a subtype of `$container_type`. * If you consider `Type\Union` as a set of types, this will tell you * if `$input_type` is fully contained in `$container_type`, * * $input_type ⊆ $container_type * * Useful for emitting issues like InvalidArgument, where argument at the call site * should be a subset of the function parameter type. */ public function isTypeContainedByType(\Psalm\Type\Union $input_type, \Psalm\Type\Union $container_type) : bool { return \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($this, $input_type, $container_type); } /** * Checks if type has any part that is a subtype of other * * Given two types, checks if *any part* of `$input_type` is a subtype of `$container_type`. * If you consider `Type\Union` as a set of types, this will tell you if intersection * of `$input_type` with `$container_type` is not empty. * * $input_type ∩ $container_type ≠ ∅ , e.g. they are not disjoint. * * Useful for emitting issues like PossiblyInvalidArgument, where argument at the call * site should be a subtype of the function parameter type, but it's has some types that are * not a subtype of the required type. */ public function canTypeBeContainedByType(\Psalm\Type\Union $input_type, \Psalm\Type\Union $container_type) : bool { return \Psalm\Internal\Type\Comparator\UnionTypeComparator::canBeContainedBy($this, $input_type, $container_type); } /** * Extracts key and value types from a traversable object (or iterable) * * Given an iterable type (*but not TArray*) returns a tuple of it's key/value types. * First element of the tuple holds key type, second has the value type. * * Example: * ```php * $codebase->getKeyValueParamsForTraversableObject(Type::parseString('iterable')) * // returns [Union(TInt), Union(TString)] * ``` * * @return array{Type\Union,Type\Union} */ public function getKeyValueParamsForTraversableObject(\Psalm\Type\Atomic $type) : array { $key_type = null; $value_type = null; \Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer::getKeyValueParamsForTraversableObject($type, $this, $key_type, $value_type); return [$key_type ?? \Psalm\Type::getMixed(), $value_type ?? \Psalm\Type::getMixed()]; } /** * @param array $phantom_classes * @psalm-suppress PossiblyUnusedMethod part of the public API */ public function queueClassLikeForScanning(string $fq_classlike_name, bool $analyze_too = \false, bool $store_failure = \true, array $phantom_classes = []) : void { $this->scanner->queueClassLikeForScanning($fq_classlike_name, $analyze_too, $store_failure, $phantom_classes); } /** * @param array $taints * * @psalm-suppress PossiblyUnusedMethod */ public function addTaintSource(\Psalm\Type\Union $expr_type, string $taint_id, array $taints = \Psalm\Type\TaintKindGroup::ALL_INPUT, ?\Psalm\CodeLocation $code_location = null) : void { if (!$this->taint_flow_graph) { return; } $source = new \Psalm\Internal\DataFlow\TaintSource($taint_id, $taint_id, $code_location, null, $taints); $this->taint_flow_graph->addSource($source); $expr_type->parent_nodes = [$source->id => $source]; } /** * @param array $taints * * @psalm-suppress PossiblyUnusedMethod */ public function addTaintSink(string $taint_id, array $taints = \Psalm\Type\TaintKindGroup::ALL_INPUT, ?\Psalm\CodeLocation $code_location = null) : void { if (!$this->taint_flow_graph) { return; } $sink = new \Psalm\Internal\DataFlow\TaintSink($taint_id, $taint_id, $code_location, null, $taints); $this->taint_flow_graph->addSink($sink); } } write($message); } public function startScanningFiles() : void { $this->write('Scanning files...' . "\n"); } public function startAnalyzingFiles() : void { $this->write('Analyzing files...' . "\n"); } public function startAlteringFiles() : void { $this->write('Updating files...' . "\n"); } public function alterFileDone(string $file_name) : void { $this->write('Altered ' . $file_name . "\n"); } } print_errors = $print_errors; $this->print_infos = $print_infos; } public function startScanningFiles() : void { $this->write('Scanning files...' . "\n"); } public function startAnalyzingFiles() : void { $this->write('Analyzing files...' . "\n\n"); } public function startAlteringFiles() : void { $this->write('Altering files...' . "\n"); } public function alterFileDone(string $file_name) : void { $this->write('Altered ' . $file_name . "\n"); } public function start(int $number_of_tasks) : void { $this->number_of_tasks = $number_of_tasks; $this->progress = 0; } public function taskDone(int $level) : void { if ($level === 0 || $level === 1 && !$this->print_infos || !$this->print_errors) { $this->write(self::doesTerminalSupportUtf8() ? '░' : '_'); } elseif ($level === 1) { $this->write('I'); } else { $this->write('E'); } ++$this->progress; if ($this->progress % self::NUMBER_OF_COLUMNS !== 0) { return; } $this->printOverview(); $this->write(\PHP_EOL); } public function finish() : void { $this->write(\PHP_EOL); } protected function getOverview() : string { if ($this->number_of_tasks === null) { throw new \LogicException('Progress::start() should be called before Progress::startDone()'); } $leadingSpaces = 1 + \strlen((string) $this->number_of_tasks) - \strlen((string) $this->progress); // Don't show 100% unless this is the last line of the progress bar. $percentage = \floor($this->progress / $this->number_of_tasks * 100); return \sprintf('%s%s / %s (%s%%)', \str_repeat(' ', $leadingSpaces), $this->progress, $this->number_of_tasks, $percentage); } private function printOverview() : void { $this->write($this->getOverview()); } } number_of_tasks > self::TOO_MANY_FILES) { ++$this->progress; // Source for rate limiting: // https://github.com/phan/phan/blob/9a788581ee1a4e1c35bebf89c435fd8a238c1d17/src/Phan/CLI.php $time = \microtime(\true); // If not enough time has elapsed, then don't update the progress bar. // Making the update frequency based on time (instead of the number of files) // prevents the terminal from rapidly flickering while processing small/empty files, // and reduces the time spent writing to stderr. if ($time - $this->previous_update_time < self::PROGRESS_BAR_SAMPLE_INTERVAL) { // Make sure to output the section for 100% completion regardless of limits, to avoid confusion. if ($this->progress !== $this->number_of_tasks) { return; } } $this->previous_update_time = $time; $inner_progress = self::renderInnerProgressBar(self::NUMBER_OF_COLUMNS, $this->progress / $this->number_of_tasks); $this->write($inner_progress . ' ' . $this->getOverview() . "\r"); } else { parent::taskDone($level); } } /** * Fully stolen from * https://github.com/phan/phan/blob/d61a624b1384ea220f39927d53fd656a65a75fac/src/Phan/CLI.php * Renders a unicode progress bar that goes from light (left) to dark (right) * The length in the console is the positive integer $length * * @see https://en.wikipedia.org/wiki/Block_Elements */ private static function renderInnerProgressBar(int $length, float $p) : string { $current_float = $p * $length; $current = (int) $current_float; $rest = \max($length - $current, 0); if (!self::doesTerminalSupportUtf8()) { // Show a progress bar of "XXXX>------" in Windows when utf-8 is unsupported. $progress_bar = \str_repeat('X', $current); $delta = $current_float - $current; if ($delta > 0.5) { $progress_bar .= '>' . \str_repeat('-', $rest - 1); } else { $progress_bar .= \str_repeat('-', $rest); } return $progress_bar; } // The left-most characters are "Light shade" $progress_bar = \str_repeat("█", $current); $delta = $current_float - $current; if ($delta > 3.0 / 4) { $progress_bar .= "▊" . \str_repeat("░", $rest - 1); } elseif ($delta > 2.0 / 4) { $progress_bar .= "▌" . \str_repeat("░", $rest - 1); } elseif ($delta > 1.0 / 4) { $progress_bar .= "▎" . \str_repeat("░", $rest - 1); } else { $progress_bar .= \str_repeat("░", $rest); } return $progress_bar; } public function finish() : void { if ($this->number_of_tasks > self::TOO_MANY_FILES) { $this->write(\str_repeat(' ', self::NUMBER_OF_COLUMNS + \strlen($this->getOverview()) + 1) . "\r"); } else { parent::finish(); } } } >} * @psalm-suppress PossiblyUnusedMethod * * @deprecated use parsePreservingLength instead * * @psalm-pure */ public static function parse(string $docblock, ?int $line_number = null, bool $preserve_format = \false) : array { // Strip off comments. $docblock = \trim($docblock); $docblock = \preg_replace('@^/\\*\\*@', '', $docblock); $docblock = \preg_replace('@\\*/$@', '', $docblock); $docblock = \preg_replace('@^[ \\t]*\\*@m', '', $docblock); // Normalize multi-line @specials. $lines = \explode("\n", $docblock); $line_map = []; $last = \false; foreach ($lines as $k => $line) { if (\preg_match('/^\\s?@\\w/i', $line)) { $last = $k; } elseif (\preg_match('/^\\s*$/', $line)) { $last = \false; } elseif ($last !== \false) { $old_last_line = $lines[$last]; $lines[$last] = \rtrim($old_last_line) . ($preserve_format || \trim($old_last_line) === '@return' ? "\n" . $line : ' ' . \trim($line)); if ($line_number) { $old_line_number = $line_map[$old_last_line]; unset($line_map[$old_last_line]); $line_map[$lines[$last]] = $old_line_number; } unset($lines[$k]); } if ($line_number) { $line_map[$line] = $line_number++; } } $special = []; if ($preserve_format) { foreach ($lines as $m => $line) { if (\preg_match('/^\\s?@([\\w\\-:]+)[\\t ]*(.*)$/sm', $line, $matches)) { [$full_match, $type, $data] = $matches; $docblock = \str_replace($full_match, '', $docblock); if (empty($special[$type])) { $special[$type] = []; } $line_number = $line_map && isset($line_map[$full_match]) ? $line_map[$full_match] : (int) $m; $special[$type][$line_number] = \rtrim($data); } } } else { $docblock = \implode("\n", $lines); // Parse @specials. if (\preg_match_all('/^\\s?@([\\w\\-:]+)[\\t ]*([^\\n]*)/m', $docblock, $matches, \PREG_SET_ORDER)) { $docblock = \preg_replace('/^\\s?@([\\w\\-:]+)\\s*([^\\n]*)/m', '', $docblock); foreach ($matches as $m => $match) { [$_, $type, $data] = $match; if (empty($special[$type])) { $special[$type] = []; } $line_number = $line_map && isset($line_map[$_]) ? $line_map[$_] : (int) $m; $special[$type][$line_number] = $data; } } } $docblock = \str_replace("\t", ' ', $docblock); // Smush the whole docblock to the left edge. $min_indent = 80; $indent = 0; foreach (\array_filter(\explode("\n", $docblock)) as $line) { for ($ii = 0, $iiMax = \strlen($line); $ii < $iiMax; ++$ii) { if ($line[$ii] !== ' ') { break; } ++$indent; } $min_indent = \min($indent, $min_indent); } $docblock = \preg_replace('/^' . \str_repeat(' ', $min_indent) . '/m', '', $docblock); $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); foreach ($special as $special_key => $_) { if (\substr($special_key, 0, 6) === 'psalm-') { $special_key = \substr($special_key, 6); if (!\in_array($special_key, self::PSALM_ANNOTATIONS, \true)) { throw new \Psalm\Exception\DocblockParseException('Unrecognised annotation @psalm-' . $special_key); } } } return ['description' => $docblock, 'specials' => $special]; } /** * Parse a docblock comment into its parts. * * @param bool $preserve_format */ public static function parsePreservingLength(\_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $docblock) : \Psalm\Internal\Scanner\ParsedDocblock { $parsed_docblock = \Psalm\Internal\Scanner\DocblockParser::parse($docblock->getText()); foreach ($parsed_docblock->tags as $special_key => $_) { if (\substr($special_key, 0, 6) === 'psalm-') { $special_key = \substr($special_key, 6); if (!\in_array($special_key, self::PSALM_ANNOTATIONS, \true)) { throw new \Psalm\Exception\DocblockParseException('Unrecognised annotation @psalm-' . $special_key); } } } return $parsed_docblock; } /** * @psalm-pure * @return array */ public static function parseSuppressList(string $suppress_entry) : array { \preg_match('/ (?(DEFINE) # either a single issue or comma separated list of issues (? (?&issue) \\s* , \\s* (?&issue_list) | (?&issue) ) # definition of a single issue (? [A-Za-z0-9_-]+ ) ) ^ (?P (?&issue_list) ) (?P .* ) $ /xm', $suppress_entry, $matches); if (!isset($matches['issues'])) { return []; } $issue_offset = 0; $ret = []; foreach (\explode(',', $matches['issues']) as $suppressed_issue) { $issue_offset += \strspn($suppressed_issue, "\t\n\f\r "); $ret[$issue_offset] = \trim($suppressed_issue); $issue_offset += \strlen($suppressed_issue) + 1; } return $ret; } } pretty ? \Psalm\Internal\Json\Json::PRETTY : \Psalm\Internal\Json\Json::DEFAULT; $issues_data = \array_map(function ($issue_data) : array { $issue_data = (array) $issue_data; unset($issue_data['dupe_key']); return $issue_data; }, $this->issues_data); return \Psalm\Internal\Json\Json::encode(\array_values($issues_data), $options) . "\n"; } } issues_data as $issue_data) { $output .= $this->format($issue_data) . "\n" . "\n"; } return $output; } private function format(\Psalm\Internal\Analyzer\IssueData $issue_data) : string { $issue_string = ''; $is_error = $issue_data->severity === \Psalm\Config::REPORT_ERROR; if ($is_error) { $issue_string .= $this->use_color ? "\33[0;31mERROR\33[0m" : 'ERROR'; } else { $issue_string .= 'INFO'; } $issue_reference = ' (see ' . $issue_data->link . ')'; $issue_string .= ': ' . $issue_data->type . ' - ' . $issue_data->file_name . ':' . $issue_data->line_from . ':' . $issue_data->column_from . ' - ' . $issue_data->message . $issue_reference . "\n"; if ($issue_data->taint_trace) { $issue_string .= $this->getTaintSnippets($issue_data->taint_trace); } elseif ($this->show_snippet) { $snippet = $issue_data->snippet; if (!$this->use_color) { $issue_string .= $snippet; } else { $selection_start = $issue_data->from - $issue_data->snippet_from; $selection_length = $issue_data->to - $issue_data->from; $issue_string .= \substr($snippet, 0, $selection_start) . ($is_error ? "\33[97;41m" : "\33[30;47m") . \substr($snippet, $selection_start, $selection_length) . "\33[0m" . \substr($snippet, $selection_length + $selection_start) . "\n"; } } return $issue_string; } /** * @param non-empty-list $taint_trace */ private function getTaintSnippets(array $taint_trace) : string { $snippets = ''; foreach ($taint_trace as $node_data) { if ($node_data instanceof \Psalm\Internal\Analyzer\DataFlowNodeData) { $snippets .= ' ' . $node_data->label . ' - ' . $node_data->file_name . ':' . $node_data->line_from . ':' . $node_data->column_from . "\n"; if ($this->show_snippet) { $snippet = $node_data->snippet; if (!$this->use_color) { $snippets .= $snippet . "\n\n"; } else { $selection_start = $node_data->from - $node_data->snippet_from; $selection_length = $node_data->to - $node_data->from; $snippets .= \substr($snippet, 0, $selection_start) . "\33[30;47m" . \substr($snippet, $selection_start, $selection_length) . "\33[0m" . \substr($snippet, $selection_length + $selection_start) . "\n\n"; } } } else { $snippets .= ' ' . $node_data['label'] . "\n"; $snippets .= ' ' . "\n\n"; } } return $snippets; } } issues_data as $i => $issue_data) { if (!$this->show_info && $issue_data->severity === \Psalm\Config::REPORT_INFO) { continue; } elseif ($current_file === null || $current_file !== $issue_data->file_name) { // If we're processing a new file, then wrap up the last table and render it out. if ($buffer !== null) { $table->render(); $output[] = $buffer->fetch(); } $output[] = 'FILE: ' . $issue_data->file_name . "\n"; $buffer = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\BufferedOutput(); $table = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Helper\Table($buffer); $table->setHeaders(['SEVERITY', 'LINE', 'ISSUE', 'DESCRIPTION']); } $is_error = $issue_data->severity === \Psalm\Config::REPORT_ERROR; if ($is_error) { $severity = $this->use_color ? "\33[0;31mERROR\33[0m" : 'ERROR'; } else { $severity = \strtoupper($issue_data->severity); } // Since `Table::setColumnMaxWidth` is only available in symfony/console 4.2+ we need do something similar // so we have clean tables. $message = $issue_data->message; if (\strlen($message) > 70) { $message = \implode("\n", \str_split($message, 70)); } $table->addRow([$severity, $issue_data->line_from, $issue_data->type, $message]); $current_file = $issue_data->file_name; // If we're at the end of the issue sets, then wrap up the last table and render it out. if ($i === \count($this->issues_data) - 1) { $table->render(); $output[] = $buffer->fetch(); } } return \implode("\n", $output); } } \array_map(function (\Psalm\Internal\Analyzer\IssueData $issue_data) : array { $issue_data = (array) $issue_data; unset($issue_data['dupe_key']); return $issue_data; }, $this->issues_data)]); return $xml->saveXML(); } } issues_data as $issue_data) { $output .= \sprintf('::%s file=%s,line=%s,col=%s::%s', $issue_data->severity === \Psalm\Config::REPORT_ERROR ? 'error' : 'warning', $issue_data->file_name, $issue_data->line_from, $issue_data->column_from, $issue_data->message) . "\n"; } return $output; } } issues_data as $issue_data) { $output .= \sprintf('%s:%s:%s:%s - %s: %s', $issue_data->file_path, $issue_data->line_from, $issue_data->column_from, $issue_data->severity === \Psalm\Config::REPORT_ERROR ? 'error' : 'warning', $issue_data->type, $issue_data->message) . "\n"; } return $output; } } []]; foreach ($this->issues_data as $issue_data) { $report['issues'][] = ['engineId' => 'Psalm', 'ruleId' => $issue_data->type, 'primaryLocation' => ['message' => $issue_data->message, 'filePath' => $issue_data->file_name, 'textRange' => [ 'startLine' => $issue_data->line_from, 'endLine' => $issue_data->line_to, // Columns in external issue reports are indexed from 0 'startColumn' => \max(0, $issue_data->column_from - 1), 'endColumn' => \max(0, $issue_data->column_to - 1), ]], 'type' => 'CODE_SMELL', 'severity' => $issue_data->severity === \Psalm\Config::REPORT_ERROR ? 'CRITICAL' : 'MINOR']; } $options = $this->pretty ? \Psalm\Internal\Json\Json::PRETTY : \Psalm\Internal\Json\Json::DEFAULT; return \Psalm\Internal\Json\Json::encode($report, $options) . "\n"; } } issues_data as $issue_data) { $type = $issue_data->type; if (!isset($type_counts[$type])) { $type_counts[$type] = 0; } ++$type_counts[$type]; } $options = $this->pretty ? \Psalm\Internal\Json\Json::PRETTY : \Psalm\Internal\Json\Json::DEFAULT; return \Psalm\Internal\Json\Json::encode(['issue_counts' => $type_counts, 'mixed_expression_count' => $this->mixed_expression_count, 'total_expression_count' => $this->total_expression_count], $options) . "\n"; } } issues_data as $issue_data) { $output .= $this->format($issue_data) . "\n" . "\n"; } return $output; } private function format(\Psalm\Internal\Analyzer\IssueData $issue_data) : string { $issue_string = ''; $is_error = $issue_data->severity === \Psalm\Config::REPORT_ERROR; if ($is_error) { $issue_string .= $this->use_color ? "\33[0;31mERROR\33[0m" : 'ERROR'; } else { $issue_string .= 'INFO'; } $issue_reference = ' (see ' . $issue_data->link . ')'; $issue_string .= ': ' . $issue_data->type . "\nat " . $issue_data->file_path . ':' . $issue_data->line_from . ':' . $issue_data->column_from . "\n" . $issue_data->message . $issue_reference . "\n"; if ($issue_data->taint_trace) { $issue_string .= $this->getTaintSnippets($issue_data->taint_trace); } elseif ($this->show_snippet) { $snippet = $issue_data->snippet; if (!$this->use_color) { $issue_string .= $snippet; } else { $selection_start = $issue_data->from - $issue_data->snippet_from; $selection_length = $issue_data->to - $issue_data->from; $issue_string .= \substr($snippet, 0, $selection_start) . ($is_error ? "\33[97;41m" : "\33[30;47m") . \substr($snippet, $selection_start, $selection_length) . "\33[0m" . \substr($snippet, $selection_length + $selection_start) . "\n"; } } return $issue_string; } /** * @param non-empty-list $taint_trace */ private function getTaintSnippets(array $taint_trace) : string { $snippets = ''; foreach ($taint_trace as $node_data) { if ($node_data instanceof \Psalm\Internal\Analyzer\DataFlowNodeData) { $snippets .= ' ' . $node_data->label . ' - ' . $node_data->file_name . ':' . $node_data->line_from . ':' . $node_data->column_from . "\n"; if ($this->show_snippet) { $snippet = $node_data->snippet; if (!$this->use_color) { $snippets .= $snippet . "\n\n"; } else { $selection_start = $node_data->from - $node_data->snippet_from; $selection_length = $node_data->to - $node_data->from; $snippets .= \substr($snippet, 0, $selection_start) . "\33[30;47m" . \substr($snippet, $selection_start, $selection_length) . "\33[0m" . \substr($snippet, $selection_length + $selection_start) . "\n\n"; } } } else { $snippets .= ' ' . $node_data['label'] . "\n"; $snippets .= ' ' . "\n\n"; } } return $snippets; } } issues_data as $issue_data) { $output .= $this->format($issue_data) . "\n"; } return $output; } private function format(\Psalm\Internal\Analyzer\IssueData $issue_data) : string { $message = \sprintf('%s: %s', $issue_data->type, $issue_data->message); if ($issue_data->severity === \Psalm\Config::REPORT_ERROR) { $code = 'E0001'; } else { $code = 'W0001'; } // https://docs.pylint.org/en/1.6.0/output.html doesn't mention what to do about 'column', // but it's still useful for users. // E.g. jenkins can't parse %s:%d:%d. $message = \sprintf('%s (column %d)', $message, $issue_data->column_from); $issue_string = \sprintf('%s:%d: [%s] %s', $issue_data->file_name, $issue_data->line_from, $code, $message); return $issue_string; } } ' . "\n"; $output .= '' . "\n"; foreach ($this->issues_data as $issue_data) { $message = \sprintf('%s: %s', $issue_data->type, $issue_data->message); $output .= '' . "\n"; $output .= ' '; $output .= 'line_from . '"'; $output .= ' column="' . $issue_data->column_from . '"'; $output .= ' severity="' . $issue_data->severity . '"'; $output .= ' message="' . \htmlspecialchars($message) . '"'; $output .= '/>' . "\n"; $output .= '' . "\n"; } $output .= '' . "\n"; return $output; } } */ public $format = \Psalm\Report::TYPE_CONSOLE; /** * @var bool */ public $pretty = \false; /** * @var ?string */ public $output_path; /** * @var bool */ public $show_suggestions = \true; } issues_data as $issue_data) { $output .= \sprintf('%s:%s:%s:%s - %s', $issue_data->file_path, $issue_data->line_from, $issue_data->column_from, $issue_data->severity === \Psalm\Config::REPORT_ERROR ? 'error' : 'warning', $issue_data->message) . "\n"; } return $output; } } issues_data as $error) { $is_error = $error->severity === \Psalm\Config::REPORT_ERROR; $is_warning = $error->severity === \Psalm\Config::REPORT_INFO; if (!$is_error && !$is_warning) { continue; } if ($is_error) { $errors++; } $tests++; $fname = $error->file_name; if (!isset($ndata[$fname])) { $ndata[$fname] = ['errors' => $is_error ? 1 : 0, 'warnings' => $is_warning ? 1 : 0, 'failures' => []]; } else { if ($is_error) { $ndata[$fname]['errors']++; } else { $ndata[$fname]['warnings']++; } } $ndata[$fname]['failures'][] = $error; } $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = \true; $schema = 'https://raw.githubusercontent.com/junit-team/' . 'junit5/r5.5.1/platform-tests/src/test/resources/jenkins-junit.xsd'; $suites = $dom->createElement('testsuites'); $suites->setAttribute('failures', (string) $errors); $suites->setAttribute('errors', '0'); $suites->setAttribute('name', 'psalm'); $suites->setAttribute('tests', (string) $tests); $suites->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $suites->setAttribute('xsi:noNamespaceSchemaLocation', $schema); $dom->appendChild($suites); if (!\count($ndata)) { $suites->setAttribute('tests', '1'); $testsuite = $dom->createElement('testsuite'); $testsuite->setAttribute('name', 'psalm'); $testsuite->setAttribute('failures', '0'); $testsuite->setAttribute('errors', '0'); $testsuite->setAttribute('tests', '1'); $testcase = $dom->createElement('testcase'); $testcase->setAttribute('name', 'psalm'); $testsuite->appendChild($testcase); $suites->appendChild($testsuite); } else { foreach ($ndata as $file => $report) { $this->createTestSuite($dom, $suites, $file, $report); } } return $dom->saveXML(); } /** * @param array{ * errors: int, * warnings: int, * failures: list * } $report */ private function createTestSuite(\DOMDocument $dom, \DOMElement $parent, string $file, array $report) : void { $totalTests = $report['errors'] + $report['warnings']; if ($totalTests < 1) { $totalTests = 1; } $testsuite = $dom->createElement('testsuite'); $testsuite->setAttribute('name', $file); $testsuite->setAttribute('failures', (string) $report['errors']); $testsuite->setAttribute('errors', '0'); $testsuite->setAttribute('tests', (string) $totalTests); $failuresByType = $this->groupByType($report['failures']); foreach ($failuresByType as $type => $data) { foreach ($data as $d) { $testcase = $dom->createElement('testcase'); $testcase->setAttribute('name', "{$file}:{$d->line_from}"); $testcase->setAttribute('classname', $type); $testcase->setAttribute('assertions', (string) \count($data)); if ($d->severity === \Psalm\Config::REPORT_ERROR) { $issue = $dom->createElement('failure'); $issue->setAttribute('type', $type); } else { $issue = $dom->createElement('skipped'); } $issue->nodeValue = $this->dataToOutput($d); $testcase->appendChild($issue); $testsuite->appendChild($testcase); } } $parent->appendChild($testsuite); } /** * @param list $failures * * @return array> */ private function groupByType(array $failures) : array { $nfailures = []; foreach ($failures as $failure) { $nfailures[$failure->type][] = $failure; } return $nfailures; } private function dataToOutput(\Psalm\Internal\Analyzer\IssueData $data) : string { $ret = 'message: ' . \htmlspecialchars(\trim($data->message), \ENT_XML1 | \ENT_QUOTES) . "\n"; $ret .= 'type: ' . \trim($data->type) . "\n"; $ret .= 'snippet: ' . \htmlspecialchars(\trim($data->snippet), \ENT_XML1 | \ENT_QUOTES) . "\n"; $ret .= 'selected_text: ' . \htmlspecialchars(\trim($data->selected_text)) . "\n"; $ret .= 'line: ' . $data->line_from . "\n"; $ret .= 'column_from: ' . $data->column_from . "\n"; $ret .= 'column_to: ' . $data->column_to . "\n"; return $ret; } } type = clone $type; if ($this->type->getLiteralStrings()) { $this->type->addType(new \Psalm\Type\Atomic\TString()); } if ($this->type->getLiteralInts()) { $this->type->addType(new \Psalm\Type\Atomic\TInt()); } if ($this->type->getLiteralFloats()) { $this->type->addType(new \Psalm\Type\Atomic\TFloat()); } } } } > */ private $unchanged_members = []; /** * @var array> */ private $unchanged_signature_members = []; /** * @var array> */ private $changed_members = []; /** * @var array> */ private $diff_map = []; /** * @var PhpParser\Lexer|null */ private static $lexer; /** * @var PhpParser\Parser|null */ private static $parser; public function __construct(\Psalm\Internal\Provider\FileProvider $file_provider, ?\Psalm\Internal\Provider\ParserCacheProvider $parser_cache_provider = null, ?\Psalm\Internal\Provider\FileStorageCacheProvider $file_storage_cache_provider = null) { $this->file_provider = $file_provider; $this->parser_cache_provider = $parser_cache_provider; $this->this_modified_time = \filemtime(__FILE__); $this->file_storage_cache_provider = $file_storage_cache_provider; } /** * @return list<\PhpParser\Node\Stmt> */ public function getStatementsForFile(string $file_path, string $php_version, ?\Psalm\Progress\Progress $progress = null) : array { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } $from_cache = \false; $version = (string) PHP_PARSER_VERSION . $this->this_modified_time; $file_contents = $this->file_provider->getContents($file_path); $modified_time = $this->file_provider->getModifiedTime($file_path); $config = \Psalm\Config::getInstance(); if (!$this->parser_cache_provider || !$config->isInProjectDirs($file_path) && \strpos($file_path, 'vendor')) { $progress->debug('Parsing ' . $file_path . "\n"); $stmts = self::parseStatements($file_contents, $php_version, $file_path); return $stmts ?: []; } $file_content_hash = \md5($version . $file_contents); $stmts = $this->parser_cache_provider->loadStatementsFromCache($file_path, $modified_time, $file_content_hash); if ($stmts === null) { $progress->debug('Parsing ' . $file_path . "\n"); $existing_statements = $this->parser_cache_provider->loadExistingStatementsFromCache($file_path); /** @psalm-suppress DocblockTypeContradiction */ if ($existing_statements && !$existing_statements[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt) { $existing_statements = null; } $existing_file_contents = $this->parser_cache_provider->loadExistingFileContentsFromCache($file_path); // this happens after editing temporary file if ($existing_file_contents === $file_contents && $existing_statements) { $this->diff_map[$file_path] = []; $this->parser_cache_provider->saveStatementsToCache($file_path, $file_content_hash, $existing_statements, \true); return $existing_statements; } $file_changes = null; $existing_statements_copy = null; if ($existing_statements && $existing_file_contents && \abs(\strlen($existing_file_contents) - \strlen($file_contents)) < 5000) { $file_changes = \Psalm\Internal\Diff\FileDiffer::getDiff($existing_file_contents, $file_contents); if (\count($file_changes) < 10) { $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $traverser->addVisitor(new \Psalm\Internal\PhpVisitor\CloningVisitor()); // performs a deep clone /** @var list */ $existing_statements_copy = $traverser->traverse($existing_statements); } else { $file_changes = null; } } $stmts = self::parseStatements($file_contents, $php_version, $file_path, $existing_file_contents, $existing_statements_copy, $file_changes); if ($existing_file_contents && $existing_statements) { [$unchanged_members, $unchanged_signature_members, $changed_members, $diff_map] = \Psalm\Internal\Diff\FileStatementsDiffer::diff($existing_statements, $stmts, $existing_file_contents, $file_contents); $unchanged_members = \array_map( /** * @param int $_ * * @return bool */ function ($_) : bool { return \true; }, \array_flip($unchanged_members) ); $unchanged_signature_members = \array_map( /** * @param int $_ * * @return bool */ function ($_) : bool { return \true; }, \array_flip($unchanged_signature_members) ); $file_path_hash = \md5($file_path); $changed_members = \array_map(function (string $key) use($file_path_hash) : string { if (\substr($key, 0, 4) === 'use:') { return $key . ':' . $file_path_hash; } return $key; }, $changed_members); $changed_members = \array_map( /** * @param int $_ * * @return bool */ function ($_) : bool { return \true; }, \array_flip($changed_members) ); if (isset($this->unchanged_members[$file_path])) { $this->unchanged_members[$file_path] = \array_intersect_key($this->unchanged_members[$file_path], $unchanged_members); } else { $this->unchanged_members[$file_path] = $unchanged_members; } if (isset($this->unchanged_signature_members[$file_path])) { $this->unchanged_signature_members[$file_path] = \array_intersect_key($this->unchanged_signature_members[$file_path], $unchanged_signature_members); } else { $this->unchanged_signature_members[$file_path] = $unchanged_signature_members; } if (isset($this->changed_members[$file_path])) { $this->changed_members[$file_path] = \array_merge($this->changed_members[$file_path], $changed_members); } else { $this->changed_members[$file_path] = $changed_members; } $this->diff_map[$file_path] = $diff_map; } if ($this->file_storage_cache_provider) { $this->file_storage_cache_provider->removeCacheForFile($file_path); } $this->parser_cache_provider->cacheFileContents($file_path, $file_contents); } else { $from_cache = \true; $this->diff_map[$file_path] = []; } $this->parser_cache_provider->saveStatementsToCache($file_path, $file_content_hash, $stmts, $from_cache); if (!$stmts) { return []; } return $stmts; } /** * @return array> */ public function getChangedMembers() : array { return $this->changed_members; } /** * @param array> $more_changed_members * */ public function addChangedMembers(array $more_changed_members) : void { $this->changed_members = \array_merge($more_changed_members, $this->changed_members); } /** * @return array> */ public function getUnchangedSignatureMembers() : array { return $this->unchanged_signature_members; } /** * @param array> $more_unchanged_members * */ public function addUnchangedSignatureMembers(array $more_unchanged_members) : void { $this->unchanged_signature_members = \array_merge($more_unchanged_members, $this->unchanged_signature_members); } public function setUnchangedFile(string $file_path) : void { if (!isset($this->diff_map[$file_path])) { $this->diff_map[$file_path] = []; } } /** * @return array> */ public function getDiffMap() : array { return $this->diff_map; } /** * @param array> $diff_map * */ public function addDiffMap(array $diff_map) : void { $this->diff_map = \array_merge($diff_map, $this->diff_map); } public function resetDiffs() : void { $this->changed_members = []; $this->unchanged_members = []; $this->unchanged_signature_members = []; $this->diff_map = []; } /** * @param list<\PhpParser\Node\Stmt> $existing_statements * @param array $file_changes * * @return list<\PhpParser\Node\Stmt> */ public static function parseStatements(string $file_contents, string $php_version, ?string $file_path = null, ?string $existing_file_contents = null, ?array $existing_statements = null, ?array $file_changes = null) : array { $attributes = ['comments', 'startLine', 'startFilePos', 'endFilePos']; if (!self::$lexer) { self::$lexer = new \_HumbugBoxd02f763d3c56\PhpParser\Lexer\Emulative(['usedAttributes' => $attributes, 'phpVersion' => $php_version]); } if (!self::$parser) { self::$parser = (new \_HumbugBoxd02f763d3c56\PhpParser\ParserFactory())->create(\_HumbugBoxd02f763d3c56\PhpParser\ParserFactory::ONLY_PHP7, self::$lexer); } $used_cached_statements = \false; $error_handler = new \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler\Collecting(); if ($existing_statements && $file_changes && $existing_file_contents) { $clashing_traverser = new \Psalm\Internal\PhpTraverser\CustomTraverser(); $offset_analyzer = new \Psalm\Internal\PhpVisitor\PartialParserVisitor(self::$parser, $error_handler, $file_changes, $existing_file_contents, $file_contents); $clashing_traverser->addVisitor($offset_analyzer); $clashing_traverser->traverse($existing_statements); if (!$offset_analyzer->mustRescan()) { $used_cached_statements = \true; $stmts = $existing_statements; } else { try { /** @var list<\PhpParser\Node\Stmt> */ $stmts = self::$parser->parse($file_contents, $error_handler) ?: []; } catch (\Throwable $t) { $stmts = []; // hope this got caught below } } } else { try { /** @var list<\PhpParser\Node\Stmt> */ $stmts = self::$parser->parse($file_contents, $error_handler) ?: []; } catch (\Throwable $t) { $stmts = []; // hope this got caught below } } if ($error_handler->hasErrors() && $file_path) { $config = \Psalm\Config::getInstance(); foreach ($error_handler->getErrors() as $error) { if ($error->hasColumnInfo()) { \Psalm\IssueBuffer::add(new \Psalm\Issue\ParseError($error->getMessage(), new \Psalm\CodeLocation\ParseErrorLocation($error, $file_contents, $file_path, $config->shortenFileName($file_path)))); } } } $error_handler->clearErrors(); $resolving_traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $name_resolver = new \Psalm\Internal\PhpVisitor\SimpleNameResolver($error_handler, $used_cached_statements ? $file_changes : []); $resolving_traverser->addVisitor($name_resolver); $resolving_traverser->traverse($stmts); return $stmts; } public static function clearLexer() : void { self::$lexer = null; } public static function clearParser() : void { self::$parser = null; } } * > */ private static $handlers = []; public function __construct() { self::$handlers = []; } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'doesMethodExist']); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); } } /** * /** * @param \Closure( * string, * string, * ?StatementsSource=, * ?CodeLocation * ) : ?bool $c * */ public function registerClosure(string $fq_classlike_name, \Closure $c) : void { self::$handlers[\strtolower($fq_classlike_name)][] = $c; } public function has(string $fq_classlike_name) : bool { return isset(self::$handlers[\strtolower($fq_classlike_name)]); } /** * @param array $call_args * */ public function doesMethodExist(string $fq_classlike_name, string $method_name_lowercase, ?\Psalm\StatementsSource $source = null, ?\Psalm\CodeLocation $code_location = null) : ?bool { foreach (self::$handlers[\strtolower($fq_classlike_name)] as $method_handler) { $method_exists = $method_handler($fq_classlike_name, $method_name_lowercase, $source, $code_location); if ($method_exists !== null) { return $method_exists; } } return null; } } =, * ?StatementsSource=, * ?Context=, * ?CodeLocation= * ) : ?array> * > */ private static $handlers = []; public function __construct() { self::$handlers = []; $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\PdoStatementSetFetchMode::class); } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'getMethodParams']); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); } } /** * @param \Closure( * string, * string, * ?array=, * ?StatementsSource=, * ?Context=, * ?CodeLocation= * ) : ?array $c * */ public function registerClosure(string $fq_classlike_name, \Closure $c) : void { self::$handlers[\strtolower($fq_classlike_name)][] = $c; } public function has(string $fq_classlike_name) : bool { return isset(self::$handlers[\strtolower($fq_classlike_name)]); } /** * @param ?array $call_args * * @return ?array */ public function getMethodParams(string $fq_classlike_name, string $method_name_lowercase, ?array $call_args = null, ?\Psalm\StatementsSource $statements_source = null, ?\Psalm\Context $context = null, ?\Psalm\CodeLocation $code_location = null) : ?array { foreach (self::$handlers[\strtolower($fq_classlike_name)] as $class_handler) { $result = $class_handler($fq_classlike_name, $method_name_lowercase, $call_args, $statements_source, $context, $code_location); if ($result !== null) { return $result; } } return null; } } * > */ private static $handlers = []; public function __construct() { self::$handlers = []; } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'doesPropertyExist']); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); } } /** * @param \Closure( * string, * string, * bool, * ?StatementsSource=, * ?Context=, * ?CodeLocation= * ) : ?bool $c * */ public function registerClosure(string $fq_classlike_name, \Closure $c) : void { self::$handlers[\strtolower($fq_classlike_name)][] = $c; } public function has(string $fq_classlike_name) : bool { return isset(self::$handlers[\strtolower($fq_classlike_name)]); } /** * @param array $call_args * */ public function doesPropertyExist(string $fq_classlike_name, string $property_name, bool $read_mode, ?\Psalm\StatementsSource $source = null, ?\Psalm\Context $context = null, ?\Psalm\CodeLocation $code_location = null) : ?bool { foreach (self::$handlers[\strtolower($fq_classlike_name)] as $property_handler) { $property_exists = $property_handler($fq_classlike_name, $property_name, $read_mode, $source, $context, $code_location); if ($property_exists !== null) { return $property_exists; } } return null; } } * > */ private static $handlers = []; public function __construct() { self::$handlers = []; } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'doesFunctionExist']); foreach ($class::getFunctionIds() as $function_id) { $this->registerClosure($function_id, $callable); } } /** * /** * @param \Closure( * StatementsSource, * string * ) : ?bool $c * */ public function registerClosure(string $function_id, \Closure $c) : void { self::$handlers[$function_id][] = $c; } public function has(string $function_id) : bool { return isset(self::$handlers[\strtolower($function_id)]); } /** * @param array $call_args * */ public function doesFunctionExist(\Psalm\StatementsSource $statements_source, string $function_id) : ?bool { foreach (self::$handlers[\strtolower($function_id)] as $function_handler) { $function_exists = $function_handler($statements_source, $function_id); if ($function_exists !== null) { return $function_exists; } } return null; } } */ private $node_types; /** @var SplObjectStorage>>|null> */ private $node_assertions; /** @var SplObjectStorage> */ private $node_if_true_assertions; /** @var SplObjectStorage> */ private $node_if_false_assertions; /** @var bool */ public $cache_assertions = \true; public function __construct() { /** @psalm-suppress PropertyTypeCoercion */ $this->node_types = new \SplObjectStorage(); /** @psalm-suppress PropertyTypeCoercion */ $this->node_assertions = new \SplObjectStorage(); /** @psalm-suppress PropertyTypeCoercion */ $this->node_if_true_assertions = new \SplObjectStorage(); /** @psalm-suppress PropertyTypeCoercion */ $this->node_if_false_assertions = new \SplObjectStorage(); } /** * @param PhpParser\Node\Expr|PhpParser\Node\Name|PhpParser\Node\Stmt\Return_ $node */ public function setType(\_HumbugBoxd02f763d3c56\PhpParser\NodeAbstract $node, \Psalm\Type\Union $type) : void { $this->node_types[$node] = $type; } /** * @param PhpParser\Node\Expr|PhpParser\Node\Name|PhpParser\Node\Stmt\Return_ $node */ public function getType(\_HumbugBoxd02f763d3c56\PhpParser\NodeAbstract $node) : ?\Psalm\Type\Union { return $this->node_types[$node] ?? null; } /** * @param array>>|null $assertions */ public function setAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node, ?array $assertions) : void { if (!$this->cache_assertions) { return; } $this->node_assertions[$node] = $assertions; } /** * @return array>>|null */ public function getAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node) : ?array { if (!$this->cache_assertions) { return null; } return $this->node_assertions[$node] ?? null; } /** * @param PhpParser\Node\Expr\FuncCall|PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $node * @param array $assertions */ public function setIfTrueAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node, array $assertions) : void { $this->node_if_true_assertions[$node] = $assertions; } /** * @param PhpParser\Node\Expr\FuncCall|PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $node * @return array|null */ public function getIfTrueAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node) : ?array { return $this->node_if_true_assertions[$node] ?? null; } /** * @param PhpParser\Node\Expr\FuncCall|PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $node * @param array $assertions */ public function setIfFalseAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node, array $assertions) : void { $this->node_if_false_assertions[$node] = $assertions; } /** * @param PhpParser\Node\Expr\FuncCall|PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $node * @return array|null */ public function getIfFalseAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node) : ?array { return $this->node_if_false_assertions[$node] ?? null; } public function isPureCompatible(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node) : bool { $node_type = self::getType($node); return $node_type && $node_type->reference_free || isset($node->pure); } public function clearNodeOfTypeAndAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node) : void { unset($this->node_types[$node], $this->node_assertions[$node]); } } |null */ private $existing_file_content_hashes = null; /** * A map of recently-added filename hashes to contents hashes * * @var array */ private $new_file_content_hashes = []; /** * @var bool */ private $use_file_cache; /** @var bool */ private $use_igbinary; public function __construct(\Psalm\Config $config, bool $use_file_cache = \true) { $this->use_igbinary = $config->use_igbinary; $this->use_file_cache = $use_file_cache; } /** * @return list|null * * @psalm-suppress UndefinedFunction */ public function loadStatementsFromCache(string $file_path, int $file_modified_time, string $file_content_hash) : ?array { $root_cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$root_cache_directory) { return null; } $file_cache_key = $this->getParserCacheKey($file_path); $parser_cache_directory = $root_cache_directory . \DIRECTORY_SEPARATOR . self::PARSER_CACHE_DIRECTORY; $file_content_hashes = $this->new_file_content_hashes + $this->getExistingFileContentHashes(); $cache_location = $parser_cache_directory . \DIRECTORY_SEPARATOR . $file_cache_key; if (isset($file_content_hashes[$file_cache_key]) && $file_content_hash === $file_content_hashes[$file_cache_key] && \is_readable($cache_location) && \filemtime($cache_location) > $file_modified_time) { if ($this->use_igbinary) { /** @var list<\PhpParser\Node\Stmt> */ $stmts = \igbinary_unserialize((string) \file_get_contents($cache_location)); } else { /** @var list<\PhpParser\Node\Stmt> */ $stmts = \unserialize((string) \file_get_contents($cache_location)); } return $stmts; } return null; } /** * @return list|null * * @psalm-suppress UndefinedFunction */ public function loadExistingStatementsFromCache(string $file_path) : ?array { $root_cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$root_cache_directory) { return null; } $file_cache_key = $this->getParserCacheKey($file_path); $parser_cache_directory = $root_cache_directory . \DIRECTORY_SEPARATOR . self::PARSER_CACHE_DIRECTORY; $cache_location = $parser_cache_directory . \DIRECTORY_SEPARATOR . $file_cache_key; if (\is_readable($cache_location)) { if ($this->use_igbinary) { /** @var list<\PhpParser\Node\Stmt> */ return \igbinary_unserialize((string) \file_get_contents($cache_location)) ?: null; } /** @var list<\PhpParser\Node\Stmt> */ return \unserialize((string) \file_get_contents($cache_location)) ?: null; } return null; } public function loadExistingFileContentsFromCache(string $file_path) : ?string { if (!$this->use_file_cache) { return null; } $root_cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$root_cache_directory) { return null; } $file_cache_key = $this->getParserCacheKey($file_path); $parser_cache_directory = $root_cache_directory . \DIRECTORY_SEPARATOR . self::FILE_CONTENTS_CACHE_DIRECTORY; $cache_location = $parser_cache_directory . \DIRECTORY_SEPARATOR . $file_cache_key; if (\is_readable($cache_location)) { return \file_get_contents($cache_location); } return null; } /** * @return array */ private function getExistingFileContentHashes() : array { $config = \Psalm\Config::getInstance(); $root_cache_directory = $config->getCacheDirectory(); if ($this->existing_file_content_hashes === null) { $file_hashes_path = $root_cache_directory . \DIRECTORY_SEPARATOR . self::FILE_HASHES; if ($root_cache_directory && \is_readable($file_hashes_path)) { $hashes_encoded = (string) \file_get_contents($file_hashes_path); if (!$hashes_encoded) { \error_log('Unexpected value when loading from file content hashes'); $this->existing_file_content_hashes = []; return []; } /** @psalm-suppress MixedAssignment */ $hashes_decoded = \json_decode($hashes_encoded, \true); if (!\is_array($hashes_decoded)) { \error_log('Unexpected value ' . \gettype($hashes_decoded)); $this->existing_file_content_hashes = []; return []; } /** @var array $hashes_decoded */ $this->existing_file_content_hashes = $hashes_decoded; } else { $this->existing_file_content_hashes = []; } } return $this->existing_file_content_hashes; } /** * @param list $stmts * * * @psalm-suppress UndefinedFunction */ public function saveStatementsToCache(string $file_path, string $file_content_hash, array $stmts, bool $touch_only) : void { $root_cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$root_cache_directory) { return; } $file_cache_key = $this->getParserCacheKey($file_path); $parser_cache_directory = $root_cache_directory . \DIRECTORY_SEPARATOR . self::PARSER_CACHE_DIRECTORY; $cache_location = $parser_cache_directory . \DIRECTORY_SEPARATOR . $file_cache_key; if ($touch_only) { \touch($cache_location); } else { if (!\is_dir($parser_cache_directory)) { \mkdir($parser_cache_directory, 0777, \true); } if ($this->use_igbinary) { \file_put_contents($cache_location, \igbinary_serialize($stmts)); } else { \file_put_contents($cache_location, \serialize($stmts)); } $this->new_file_content_hashes[$file_cache_key] = $file_content_hash; } } /** * @return array */ public function getNewFileContentHashes() : array { return $this->new_file_content_hashes; } /** * @param array $file_content_hashes * */ public function addNewFileContentHashes(array $file_content_hashes) : void { $this->new_file_content_hashes = $file_content_hashes + $this->new_file_content_hashes; } public function saveFileContentHashes() : void { $root_cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$root_cache_directory) { return; } $file_content_hashes = $this->new_file_content_hashes + $this->getExistingFileContentHashes(); $file_hashes_path = $root_cache_directory . \DIRECTORY_SEPARATOR . self::FILE_HASHES; \file_put_contents($file_hashes_path, \json_encode($file_content_hashes)); } public function cacheFileContents(string $file_path, string $file_contents) : void { if (!$this->use_file_cache) { return; } $root_cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$root_cache_directory) { return; } $file_cache_key = $this->getParserCacheKey($file_path); $parser_cache_directory = $root_cache_directory . \DIRECTORY_SEPARATOR . self::FILE_CONTENTS_CACHE_DIRECTORY; $cache_location = $parser_cache_directory . \DIRECTORY_SEPARATOR . $file_cache_key; if (!\is_dir($parser_cache_directory)) { \mkdir($parser_cache_directory, 0777, \true); } \file_put_contents($cache_location, $file_contents); } public function deleteOldParserCaches(float $time_before) : int { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if ($cache_directory) { return 0; } $removed_count = 0; $cache_directory .= \DIRECTORY_SEPARATOR . self::PARSER_CACHE_DIRECTORY; if (\is_dir($cache_directory)) { $directory_files = \scandir($cache_directory, \SCANDIR_SORT_NONE); foreach ($directory_files as $directory_file) { $full_path = $cache_directory . \DIRECTORY_SEPARATOR . $directory_file; if ($directory_file[0] === '.') { continue; } if (\filemtime($full_path) < $time_before && \is_writable($full_path)) { \unlink($full_path); ++$removed_count; } } } return $removed_count; } public function processSuccessfulRun() : void { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$cache_directory) { return; } $cache_directory .= \DIRECTORY_SEPARATOR . self::PARSER_CACHE_DIRECTORY; if (\is_dir($cache_directory)) { $directory_files = \scandir($cache_directory, \SCANDIR_SORT_NONE); foreach ($directory_files as $directory_file) { $full_path = $cache_directory . \DIRECTORY_SEPARATOR . $directory_file; if ($directory_file[0] === '.') { continue; } \touch($full_path); } } } /** * @param array $file_names */ public function touchParserCaches(array $file_names, int $min_time) : void { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$cache_directory) { return; } $cache_directory .= \DIRECTORY_SEPARATOR . self::PARSER_CACHE_DIRECTORY; if (\is_dir($cache_directory)) { foreach ($file_names as $file_name) { $hash_file_name = $cache_directory . \DIRECTORY_SEPARATOR . $this->getParserCacheKey($file_name); if (\file_exists($hash_file_name)) { if (\filemtime($hash_file_name) < $min_time) { \touch($hash_file_name, $min_time); } } } } } private function getParserCacheKey(string $file_name) : string { return \md5($file_name) . ($this->use_igbinary ? '-igbinary' : '') . '-r'; } } */ private static $storage = []; /** * @var array */ private static $new_storage = []; /** * @var ?ClassLikeStorageCacheProvider */ public $cache; public function __construct(?\Psalm\Internal\Provider\ClassLikeStorageCacheProvider $cache = null) { $this->cache = $cache; } /** * @throws \InvalidArgumentException when class does not exist */ public function get(string $fq_classlike_name) : \Psalm\Storage\ClassLikeStorage { $fq_classlike_name_lc = \strtolower($fq_classlike_name); if (!isset(self::$storage[$fq_classlike_name_lc])) { throw new \InvalidArgumentException('Could not get class storage for ' . $fq_classlike_name_lc); } return self::$storage[$fq_classlike_name_lc]; } public function has(string $fq_classlike_name) : bool { $fq_classlike_name_lc = \strtolower($fq_classlike_name); return isset(self::$storage[$fq_classlike_name_lc]); } public function exhume(string $fq_classlike_name, ?string $file_path, ?string $file_contents) : \Psalm\Storage\ClassLikeStorage { $fq_classlike_name_lc = \strtolower($fq_classlike_name); if (isset(self::$storage[$fq_classlike_name_lc])) { return self::$storage[$fq_classlike_name_lc]; } if (!$this->cache) { throw new \LogicException('Cannot exhume when there’s no cache'); } $cached_value = $this->cache->getLatestFromCache($fq_classlike_name_lc, $file_path, $file_contents); self::$storage[$fq_classlike_name_lc] = $cached_value; self::$new_storage[$fq_classlike_name_lc] = $cached_value; return $cached_value; } /** * @return array */ public function getAll() : array { return self::$storage; } /** * @return array */ public function getNew() : array { return self::$new_storage; } /** * @param array $more * */ public function addMore(array $more) : void { self::$new_storage = \array_merge(self::$new_storage, $more); self::$storage = \array_merge(self::$storage, $more); } public function makeNew(string $fq_classlike_name_lc) : void { self::$new_storage[$fq_classlike_name_lc] = self::$storage[$fq_classlike_name_lc]; } public function create(string $fq_classlike_name) : \Psalm\Storage\ClassLikeStorage { $fq_classlike_name_lc = \strtolower($fq_classlike_name); $storage = new \Psalm\Storage\ClassLikeStorage($fq_classlike_name); self::$storage[$fq_classlike_name_lc] = $storage; self::$new_storage[$fq_classlike_name_lc] = $storage; return $storage; } public function remove(string $fq_classlike_name) : void { $fq_classlike_name_lc = \strtolower($fq_classlike_name); unset(self::$storage[$fq_classlike_name_lc]); } public static function deleteAll() : void { self::$storage = []; self::$new_storage = []; } public static function populated() : void { self::$new_storage = []; } } */ private static $storage = []; /** * A list of data useful to analyse new files * Storing this statically is much faster (at least in PHP 7.2.1) * * @var array */ private static $new_storage = []; /** * @var ?FileStorageCacheProvider */ public $cache; public function __construct(?\Psalm\Internal\Provider\FileStorageCacheProvider $cache = null) { $this->cache = $cache; } public function get(string $file_path) : \Psalm\Storage\FileStorage { $file_path = \strtolower($file_path); if (!isset(self::$storage[$file_path])) { throw new \InvalidArgumentException('Could not get file storage for ' . $file_path); } return self::$storage[$file_path]; } public function remove(string $file_path) : void { unset(self::$storage[\strtolower($file_path)]); } public function has(string $file_path, ?string $file_contents = null) : bool { $file_path = \strtolower($file_path); if (isset(self::$storage[$file_path])) { return \true; } if ($file_contents === null) { return \false; } if (!$this->cache) { return \false; } $cached_value = $this->cache->getLatestFromCache($file_path, $file_contents); if (!$cached_value) { return \false; } self::$storage[$file_path] = $cached_value; self::$new_storage[$file_path] = $cached_value; return \true; } /** * @return array */ public function getAll() : array { return self::$storage; } /** * @return array */ public function getNew() : array { return self::$new_storage; } /** * @param array $more * */ public function addMore(array $more) : void { self::$new_storage = \array_merge(self::$new_storage, $more); self::$storage = \array_merge(self::$storage, $more); } public function create(string $file_path) : \Psalm\Storage\FileStorage { $file_path_lc = \strtolower($file_path); $storage = new \Psalm\Storage\FileStorage($file_path); self::$storage[$file_path_lc] = $storage; self::$new_storage[$file_path_lc] = $storage; return $storage; } public static function deleteAll() : void { self::$storage = []; } public static function populated() : void { self::$new_storage = []; } } config = $config; $storage_dir = \dirname(__DIR__, 2) . \DIRECTORY_SEPARATOR . 'Storage' . \DIRECTORY_SEPARATOR; $dependent_files = [$storage_dir . 'FileStorage.php', $storage_dir . 'FunctionLikeStorage.php', $storage_dir . 'ClassLikeStorage.php', $storage_dir . 'MethodStorage.php']; if ($config->after_visit_classlikes) { $dependent_files = \array_merge($dependent_files, $config->plugin_paths); } foreach ($dependent_files as $dependent_file_path) { if (!\file_exists($dependent_file_path)) { throw new \UnexpectedValueException($dependent_file_path . ' must exist'); } $this->modified_timestamps .= ' ' . \filemtime($dependent_file_path); } $this->modified_timestamps .= $this->config->hash; } public function writeToCache(\Psalm\Storage\ClassLikeStorage $storage, ?string $file_path, ?string $file_contents) : void { $fq_classlike_name_lc = \strtolower($storage->name); $cache_location = $this->getCacheLocationForClass($fq_classlike_name_lc, $file_path, \true); $storage->hash = $this->getCacheHash($file_path, $file_contents); if ($this->config->use_igbinary) { \file_put_contents($cache_location, \igbinary_serialize($storage)); } else { \file_put_contents($cache_location, \serialize($storage)); } } public function getLatestFromCache(string $fq_classlike_name_lc, ?string $file_path, ?string $file_contents) : \Psalm\Storage\ClassLikeStorage { $cached_value = $this->loadFromCache($fq_classlike_name_lc, $file_path); if (!$cached_value) { throw new \UnexpectedValueException($fq_classlike_name_lc . ' should be in cache'); } $cache_hash = $this->getCacheHash($file_path, $file_contents); /** @psalm-suppress TypeDoesNotContainType */ if (@\get_class($cached_value) === '__PHP_Incomplete_Class' || $cache_hash !== $cached_value->hash) { \unlink($this->getCacheLocationForClass($fq_classlike_name_lc, $file_path)); throw new \UnexpectedValueException($fq_classlike_name_lc . ' should not be outdated'); } return $cached_value; } private function getCacheHash(?string $file_path, ?string $file_contents) : string { return \sha1(($file_path ? $file_contents : '') . $this->modified_timestamps); } /** * @psalm-suppress MixedAssignment */ private function loadFromCache(string $fq_classlike_name_lc, ?string $file_path) : ?\Psalm\Storage\ClassLikeStorage { $cache_location = $this->getCacheLocationForClass($fq_classlike_name_lc, $file_path); if (\file_exists($cache_location)) { if ($this->config->use_igbinary) { $storage = \igbinary_unserialize((string) \file_get_contents($cache_location)); if ($storage instanceof \Psalm\Storage\ClassLikeStorage) { return $storage; } return null; } $storage = \unserialize((string) \file_get_contents($cache_location)); if ($storage instanceof \Psalm\Storage\ClassLikeStorage) { return $storage; } return null; } return null; } private function getCacheLocationForClass(string $fq_classlike_name_lc, ?string $file_path, bool $create_directory = \false) : string { $root_cache_directory = $this->config->getCacheDirectory(); if (!$root_cache_directory) { throw new \UnexpectedValueException('No cache directory defined'); } $parser_cache_directory = $root_cache_directory . \DIRECTORY_SEPARATOR . self::CLASS_CACHE_DIRECTORY; if ($create_directory && !\is_dir($parser_cache_directory)) { \mkdir($parser_cache_directory, 0777, \true); } return $parser_cache_directory . \DIRECTORY_SEPARATOR . \sha1(($file_path ? \strtolower($file_path) . ' ' : '') . $fq_classlike_name_lc) . ($this->config->use_igbinary ? '-igbinary' : ''); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } foreach ($call_args as $call_arg) { if (!($call_arg_type = $statements_source->node_data->getType($call_arg->value)) || !$call_arg_type->isInt()) { $value_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TFalse()]); $codebase = $statements_source->getCodebase(); if ($codebase->config->ignore_internal_falsable_issues) { $value_type->ignore_falsable_issues = \true; } return $value_type; } } return \Psalm\Type::getInt(); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $first_arg_type = isset($call_args[0]) ? $statements_source->node_data->getType($call_args[0]->value) : null; $third_arg_type = isset($call_args[2]) ? $statements_source->node_data->getType($call_args[2]->value) : null; if ($third_arg_type) { if ($first_arg_type && $first_arg_type->isSingleIntLiteral() && $first_arg_type->getSingleIntLiteral()->value === 0) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyList(clone $third_arg_type)]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), clone $third_arg_type])]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), \Psalm\Type::getMixed()])]); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $first_arg = isset($call_args[0]->value) ? $call_args[0]->value : null; $second_arg = isset($call_args[1]->value) ? $call_args[1]->value : null; $first_arg_array = $first_arg && ($first_arg_type = $statements_source->node_data->getType($first_arg)) && $first_arg_type->hasType('array') && ($array_atomic_type = $first_arg_type->getAtomicTypes()['array']) && ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TList) ? $array_atomic_type : null; if (!$first_arg_array) { return \Psalm\Type::getMixed(); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TArray) { $key_type = clone $first_arg_array->type_params[0]; } elseif ($first_arg_array instanceof \Psalm\Type\Atomic\TList) { $key_type = \Psalm\Type::getInt(); } else { $key_type = $first_arg_array->getGenericKeyType(); } if (!$second_arg || $second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $second_arg->value === 1) { return $key_type; } $arr_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList($key_type)]); if ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { return $arr_type; } return \Psalm\Type::combineUnionTypes($key_type, $arr_type); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : ?\Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (($first_arg_type = $statements_source->node_data->getType($call_args[0]->value)) && $first_arg_type->isObjectType()) { return \Psalm\Type::parseString('array'); } return null; } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $first_arg = isset($call_args[0]->value) ? $call_args[0]->value : null; $first_arg_array = $first_arg && ($first_arg_type = $statements_source->node_data->getType($first_arg)) && $first_arg_type->hasType('array') && ($array_atomic_type = $first_arg_type->getAtomicTypes()['array']) && ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TList) ? $array_atomic_type : null; if (!$first_arg_array) { return \Psalm\Type::getMixed(); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TArray) { $value_type = clone $first_arg_array->type_params[1]; $definitely_has_items = $first_arg_array instanceof \Psalm\Type\Atomic\TNonEmptyArray; } elseif ($first_arg_array instanceof \Psalm\Type\Atomic\TList) { $value_type = clone $first_arg_array->type_param; $definitely_has_items = $first_arg_array instanceof \Psalm\Type\Atomic\TNonEmptyList; } else { $value_type = $first_arg_array->getGenericValueType(); $definitely_has_items = $first_arg_array->getGenericArrayType() instanceof \Psalm\Type\Atomic\TNonEmptyArray; } if ($value_type->isEmpty()) { $value_type = \Psalm\Type::getFalse(); } elseif ($function_id !== 'reset' && $function_id !== 'end' || !$definitely_has_items) { $value_type->addType(new \Psalm\Type\Atomic\TFalse()); $codebase = $statements_source->getCodebase(); if ($codebase->config->ignore_internal_falsable_issues) { $value_type->ignore_falsable_issues = \true; } } return $value_type; } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (($first_arg_type = $statements_source->node_data->getType($call_args[0]->value)) && $first_arg_type->hasObjectType()) { $key_type = null; $value_type = null; $codebase = $statements_source->getCodebase(); foreach ($first_arg_type->getAtomicTypes() as $call_arg_atomic_type) { if ($call_arg_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject && \Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $call_arg_atomic_type, new \Psalm\Type\Atomic\TIterable([\Psalm\Type::getMixed(), \Psalm\Type::getMixed()]))) { $has_valid_iterator = \true; \Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer::handleIterable($statements_source, $call_arg_atomic_type, $call_args[0]->value, $codebase, $context, $key_type, $value_type, $has_valid_iterator); } } if ($value_type) { $second_arg_type = isset($call_args[1]) ? $statements_source->node_data->getType($call_args[1]->value) : null; if ($second_arg_type && (string) $second_arg_type === 'false') { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList($value_type)]); } $key_type = $key_type && (!isset($call_args[1]) || $second_arg_type && (string) $second_arg_type === 'true') ? $key_type : \Psalm\Type::getArrayKey(); if ($key_type->hasMixed()) { $key_type = \Psalm\Type::getArrayKey(); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([$key_type, $value_type])]); } } $callmap_callables = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallablesFromCallMap($function_id); \assert($callmap_callables && $callmap_callables[0]->return_type); return $callmap_callables[0]->return_type; } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (!isset($call_args[0]) || !isset($call_args[1])) { return \Psalm\Type::getMixed(); } $codebase = $statements_source->getCodebase(); $array_arg = $call_args[0]->value; $function_call_arg = $call_args[1]->value; $array_arg_type = $statements_source->node_data->getType($array_arg); $function_call_arg_type = $statements_source->node_data->getType($function_call_arg); if (!$array_arg_type || !$function_call_arg_type) { return \Psalm\Type::getMixed(); } $array_arg_types = $array_arg_type->getAtomicTypes(); $array_arg_atomic_type = null; if (isset($array_arg_types['array']) && ($array_arg_types['array'] instanceof \Psalm\Type\Atomic\TArray || $array_arg_types['array'] instanceof \Psalm\Type\Atomic\TKeyedArray || $array_arg_types['array'] instanceof \Psalm\Type\Atomic\TList)) { $array_arg_atomic_type = $array_arg_types['array']; if ($array_arg_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $array_arg_atomic_type = $array_arg_atomic_type->getGenericArrayType(); } elseif ($array_arg_atomic_type instanceof \Psalm\Type\Atomic\TList) { $array_arg_atomic_type = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), clone $array_arg_atomic_type->type_param]); } } if (!isset($call_args[2])) { $reduce_return_type = \Psalm\Type::getNull(); $reduce_return_type->ignore_nullable_issues = \true; } else { $reduce_return_type = $statements_source->node_data->getType($call_args[2]->value); if (!$reduce_return_type) { return \Psalm\Type::getMixed(); } if ($reduce_return_type->hasMixed()) { return \Psalm\Type::getMixed(); } } $initial_type = $reduce_return_type; if ($closure_types = $function_call_arg_type->getClosureTypes()) { $closure_atomic_type = \reset($closure_types); $closure_return_type = $closure_atomic_type->return_type ?: \Psalm\Type::getMixed(); if ($closure_return_type->isVoid()) { $closure_return_type = \Psalm\Type::getNull(); } $reduce_return_type = \Psalm\Type::combineUnionTypes($closure_return_type, $reduce_return_type); if ($closure_atomic_type->params !== null) { if (\count($closure_atomic_type->params) < 2) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArgument('The closure passed to array_reduce needs two params', new \Psalm\CodeLocation($statements_source, $function_call_arg)), $statements_source->getSuppressedIssues())) { // fall through } return \Psalm\Type::getMixed(); } [$carry_param, $item_param] = $closure_atomic_type->params; if ($carry_param->type && (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $initial_type, $carry_param->type) || !$reduce_return_type->hasMixed() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $reduce_return_type, $carry_param->type))) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArgument('The first param of the closure passed to array_reduce must take ' . $reduce_return_type . ' but only accepts ' . $carry_param->type, $carry_param->type_location ?: new \Psalm\CodeLocation($statements_source, $function_call_arg)), $statements_source->getSuppressedIssues())) { // fall through } return \Psalm\Type::getMixed(); } if ($item_param->type && $array_arg_atomic_type && !$array_arg_atomic_type->type_params[1]->hasMixed() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $array_arg_atomic_type->type_params[1], $item_param->type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArgument('The second param of the closure passed to array_reduce must take ' . $array_arg_atomic_type->type_params[1] . ' but only accepts ' . $item_param->type, $item_param->type_location ?: new \Psalm\CodeLocation($statements_source, $function_call_arg)), $statements_source->getSuppressedIssues())) { // fall through } return \Psalm\Type::getMixed(); } } return $reduce_return_type; } if ($function_call_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $function_call_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ || $function_call_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { $mapping_function_ids = \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::getFunctionIdsFromCallableArg($statements_source, $function_call_arg); $call_map = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallMap(); foreach ($mapping_function_ids as $mapping_function_id) { $mapping_function_id_parts = \explode('&', $mapping_function_id); $part_match_found = \false; foreach ($mapping_function_id_parts as $mapping_function_id_part) { if (isset($call_map[$mapping_function_id_part][0])) { if ($call_map[$mapping_function_id_part][0]) { $mapped_function_return = \Psalm\Type::parseString($call_map[$mapping_function_id_part][0]); $reduce_return_type = \Psalm\Type::combineUnionTypes($reduce_return_type, $mapped_function_return); $part_match_found = \true; } } elseif ($mapping_function_id_part) { if (\strpos($mapping_function_id_part, '::') !== \false) { if ($mapping_function_id_part[0] === '$') { $mapping_function_id_part = \substr($mapping_function_id_part, 1); } [$callable_fq_class_name, $method_name] = \explode('::', $mapping_function_id_part); if (\in_array($callable_fq_class_name, ['self', 'static', 'parent'], \true)) { continue; } $method_id = new \Psalm\Internal\MethodIdentifier($callable_fq_class_name, \strtolower($method_name)); if (!$codebase->methods->methodExists($method_id, !$context->collect_initializations && !$context->collect_mutations ? $context->calling_method_id : null, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_source, $function_call_arg) : null, null, $statements_source->getFilePath())) { continue; } $part_match_found = \true; $self_class = 'self'; $return_type = $codebase->methods->getMethodReturnType($method_id, $self_class) ?: \Psalm\Type::getMixed(); $reduce_return_type = \Psalm\Type::combineUnionTypes($reduce_return_type, $return_type); } else { if (!$codebase->functions->functionExists($statements_source, \strtolower($mapping_function_id_part))) { return \Psalm\Type::getMixed(); } $part_match_found = \true; $function_storage = $codebase->functions->getStorage($statements_source, \strtolower($mapping_function_id_part)); $return_type = $function_storage->return_type ?: \Psalm\Type::getMixed(); $reduce_return_type = \Psalm\Type::combineUnionTypes($reduce_return_type, $return_type); } } } if ($part_match_found === \false) { return \Psalm\Type::getMixed(); } } return $reduce_return_type; } return \Psalm\Type::getMixed(); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : ?\Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $return_type = \Psalm\Type::getString(); if (($first_arg_type = $statements_source->node_data->getType($call_args[0]->value)) && $first_arg_type->isString()) { return $return_type; } $return_type->addType(new \Psalm\Type\Atomic\TNull()); $return_type->ignore_nullable_issues = \true; return $return_type; } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $first_arg = $call_args[0]->value ?? null; $first_arg_array = $first_arg && ($first_arg_type = $statements_source->node_data->getType($first_arg)) && $first_arg_type->hasType('array') && ($array_atomic_type = $first_arg_type->getAtomicTypes()['array']) && ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TList) ? $array_atomic_type : null; if (!$first_arg_array) { return \Psalm\Type::getArray(); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TKeyedArray) { $first_arg_array = $first_arg_array->getGenericArrayType(); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TArray) { if ($first_arg_array instanceof \Psalm\Type\Atomic\TNonEmptyArray) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyList(clone $first_arg_array->type_params[1])]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList(clone $first_arg_array->type_params[1])]); } return new \Psalm\Type\Union([clone $first_arg_array]); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $first_arg = isset($call_args[0]->value) ? $call_args[0]->value : null; $first_arg_array = $first_arg && ($first_arg_type = $statements_source->node_data->getType($first_arg)) && $first_arg_type->hasType('array') && ($array_atomic_type = $first_arg_type->getAtomicTypes()['array']) && ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TList) ? $array_atomic_type : null; if (!$first_arg_array) { return \Psalm\Type::getArray(); } $dont_preserve_int_keys = !isset($call_args[3]->value) || ($third_arg_type = $statements_source->node_data->getType($call_args[3]->value)) && (string) $third_arg_type === 'false'; $already_cloned = \false; if ($first_arg_array instanceof \Psalm\Type\Atomic\TKeyedArray) { $already_cloned = \true; $first_arg_array = $first_arg_array->getGenericArrayType(); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TArray) { if (!$already_cloned) { $first_arg_array = clone $first_arg_array; } $array_type = new \Psalm\Type\Atomic\TArray($first_arg_array->type_params); } else { $array_type = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), clone $first_arg_array->type_param]); } if ($dont_preserve_int_keys && $array_type->type_params[0]->isInt()) { $array_type = new \Psalm\Type\Atomic\TList($array_type->type_params[1]); } return new \Psalm\Type\Union([$array_type]); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $function_call_arg = $call_args[0] ?? null; $function_call_type = $function_call_arg ? $statements_source->node_data->getType($function_call_arg->value) : null; if ($function_call_type && $function_call_type->isNull()) { \array_shift($call_args); $array_arg_types = []; foreach ($call_args as $call_arg) { $call_arg_type = $statements_source->node_data->getType($call_arg->value); if ($call_arg_type) { $array_arg_types[] = clone $call_arg_type; } else { $array_arg_types[] = \Psalm\Type::getMixed(); break; } } if ($array_arg_types) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TKeyedArray($array_arg_types)]); } return \Psalm\Type::getArray(); } $array_arg = $call_args[1] ?? null; if (!$array_arg) { return \Psalm\Type::getArray(); } $array_arg_atomic_type = null; $array_arg_type = null; if ($array_arg_union_type = $statements_source->node_data->getType($array_arg->value)) { $arg_types = $array_arg_union_type->getAtomicTypes(); if (isset($arg_types['array'])) { $array_arg_atomic_type = $arg_types['array']; $array_arg_type = \Psalm\Internal\Type\ArrayType::infer($array_arg_atomic_type); } } $generic_key_type = null; $mapping_return_type = null; if ($function_call_arg && $function_call_type) { if (\count($call_args) === 2) { $generic_key_type = $array_arg_type->key ?? \Psalm\Type::getArrayKey(); } else { $generic_key_type = \Psalm\Type::getInt(); } if ($closure_types = $function_call_type->getClosureTypes()) { $closure_atomic_type = \reset($closure_types); $closure_return_type = $closure_atomic_type->return_type ?: \Psalm\Type::getMixed(); if ($closure_return_type->isVoid()) { $closure_return_type = \Psalm\Type::getNull(); } $mapping_return_type = clone $closure_return_type; } elseif ($function_call_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $function_call_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ || $function_call_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { $mapping_function_ids = \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::getFunctionIdsFromCallableArg($statements_source, $function_call_arg->value); if ($mapping_function_ids) { $mapping_return_type = self::getReturnTypeFromMappingIds($statements_source, $mapping_function_ids, $context, $function_call_arg, \array_slice($call_args, 1)); } if ($function_call_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ && isset($function_call_arg->value->items[0]) && isset($function_call_arg->value->items[1]) && $function_call_arg->value->items[1]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ && $function_call_arg->value->items[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && ($variable_type = $statements_source->node_data->getType($function_call_arg->value->items[0]->value))) { $fake_method_call = null; foreach ($variable_type->getAtomicTypes() as $variable_atomic_type) { if ($variable_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam || $variable_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall($function_call_arg->value->items[0]->value, $function_call_arg->value->items[1]->value->value, []); } elseif ($variable_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall($function_call_arg->value->items[0]->value, $function_call_arg->value->items[1]->value->value, []); } } if ($fake_method_call) { $fake_method_return_type = self::executeFakeCall($statements_source, $fake_method_call, $context); if ($fake_method_return_type) { $mapping_return_type = $fake_method_return_type; } } } } } if ($mapping_return_type && $generic_key_type) { if ($array_arg_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray && \count($call_args) === 2) { $atomic_type = new \Psalm\Type\Atomic\TKeyedArray(\array_map( /** * @return Type\Union */ function (\Psalm\Type\Union $_) use($mapping_return_type) : Type\Union { return clone $mapping_return_type; }, $array_arg_atomic_type->properties )); $atomic_type->is_list = $array_arg_atomic_type->is_list; $atomic_type->sealed = $array_arg_atomic_type->sealed; return new \Psalm\Type\Union([$atomic_type]); } if ($array_arg_atomic_type instanceof \Psalm\Type\Atomic\TList || \count($call_args) !== 2) { if ($array_arg_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyList) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyList($mapping_return_type)]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList($mapping_return_type)]); } if ($array_arg_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyArray([$generic_key_type, $mapping_return_type])]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([$generic_key_type, $mapping_return_type])]); } return \count($call_args) === 2 && !($array_arg_type->is_list ?? \false) ? new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([$array_arg_type->key ?? \Psalm\Type::getArrayKey(), \Psalm\Type::getMixed()])]) : \Psalm\Type::getList(); } /** * @param-out array>>|null $assertions */ private static function executeFakeCall(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $fake_call, \Psalm\Context $context, ?array &$assertions = null) : ?\Psalm\Type\Union { $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('MixedArrayOffset', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['MixedArrayOffset']); } $was_inside_call = $context->inside_call; $context->inside_call = \true; if ($fake_call instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall) { \Psalm\Internal\Analyzer\Statements\Expression\Call\StaticCallAnalyzer::analyze($statements_analyzer, $fake_call, $context); } elseif ($fake_call instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall) { \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_call, $context); } elseif ($fake_call instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { \Psalm\Internal\Analyzer\Statements\Expression\Call\FunctionCallAnalyzer::analyze($statements_analyzer, $fake_call, $context); } else { throw new \UnexpectedValueException('UnrecognizedCall'); } $codebase = $statements_analyzer->getCodebase(); if ($assertions !== null) { $assertions = \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::scrapeAssertions($fake_call, null, $statements_analyzer, $codebase); } $context->inside_call = $was_inside_call; if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('MixedArrayOffset', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['MixedArrayOffset']); } $return_type = $statements_analyzer->node_data->getType($fake_call) ?: null; $statements_analyzer->node_data = $old_data_provider; return $return_type; } /** * @param non-empty-array $mapping_function_ids * @param array $array_args * @param-out array>>|null $assertions */ public static function getReturnTypeFromMappingIds(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_source, array $mapping_function_ids, \Psalm\Context $context, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $function_call_arg, array $array_args, ?array &$assertions = null) : \Psalm\Type\Union { $mapping_return_type = null; $codebase = $statements_source->getCodebase(); foreach ($mapping_function_ids as $mapping_function_id) { $mapping_function_id_parts = \explode('&', $mapping_function_id); foreach ($mapping_function_id_parts as $mapping_function_id_part) { $fake_args = []; foreach ($array_args as $array_arg) { $fake_args[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($array_arg->value, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable('__fake_offset_var__', $array_arg->value->getAttributes()), $array_arg->value->getAttributes()), \false, \false, $array_arg->getAttributes()); } if (\strpos($mapping_function_id_part, '::') !== \false) { $is_instance = \false; if ($mapping_function_id_part[0] === '$') { $mapping_function_id_part = \substr($mapping_function_id_part, 1); $is_instance = \true; } $method_id_parts = \explode('::', $mapping_function_id_part); [$callable_fq_class_name, $callable_method_name] = $method_id_parts; if ($is_instance) { $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable('__fake_method_call_var__', $function_call_arg->getAttributes()), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($callable_method_name, $function_call_arg->getAttributes()), $fake_args, $function_call_arg->getAttributes()); $context->vars_in_scope['$__fake_offset_var__'] = \Psalm\Type::getMixed(); $context->vars_in_scope['$__fake_method_call_var__'] = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($callable_fq_class_name)]); $fake_method_return_type = self::executeFakeCall($statements_source, $fake_method_call, $context, $assertions); unset($context->vars_in_scope['$__fake_offset_var__']); unset($context->vars_in_scope['$__method_call_var__']); } else { $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($callable_fq_class_name, $function_call_arg->getAttributes()), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($callable_method_name, $function_call_arg->getAttributes()), $fake_args, $function_call_arg->getAttributes()); $context->vars_in_scope['$__fake_offset_var__'] = \Psalm\Type::getMixed(); $fake_method_return_type = self::executeFakeCall($statements_source, $fake_method_call, $context, $assertions); unset($context->vars_in_scope['$__fake_offset_var__']); } $function_id_return_type = $fake_method_return_type ?: \Psalm\Type::getMixed(); } else { $fake_function_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($mapping_function_id_part, $function_call_arg->getAttributes()), $fake_args, $function_call_arg->getAttributes()); $context->vars_in_scope['$__fake_offset_var__'] = \Psalm\Type::getMixed(); $fake_function_return_type = self::executeFakeCall($statements_source, $fake_function_call, $context, $assertions); unset($context->vars_in_scope['$__fake_offset_var__']); $function_id_return_type = $fake_function_return_type ?: \Psalm\Type::getMixed(); } } if (!$mapping_return_type) { $mapping_return_type = $function_id_return_type; } else { $mapping_return_type = \Psalm\Type::combineUnionTypes($function_id_return_type, $mapping_return_type, $codebase); } } return $mapping_return_type; } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $inner_value_types = []; $inner_key_types = []; $codebase = $statements_source->getCodebase(); $generic_properties = []; $all_keyed_arrays = \true; $all_int_offsets = \true; $all_nonempty_lists = \true; $any_nonempty = \false; foreach ($call_args as $call_arg) { if (!($call_arg_type = $statements_source->node_data->getType($call_arg->value))) { return \Psalm\Type::getArray(); } foreach ($call_arg_type->getAtomicTypes() as $type_part) { if ($call_arg->unpack) { if (!$type_part instanceof \Psalm\Type\Atomic\TArray) { if ($type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $type_part_value_type = $type_part->getGenericValueType(); } elseif ($type_part instanceof \Psalm\Type\Atomic\TList) { $type_part_value_type = $type_part->type_param; } else { return \Psalm\Type::getArray(); } } else { $type_part_value_type = $type_part->type_params[1]; } $unpacked_type_parts = []; foreach ($type_part_value_type->getAtomicTypes() as $value_type_part) { $unpacked_type_parts[] = $value_type_part; } } else { $unpacked_type_parts = [$type_part]; } foreach ($unpacked_type_parts as $unpacked_type_part) { if (!$unpacked_type_part instanceof \Psalm\Type\Atomic\TArray) { if ($unpacked_type_part instanceof \Psalm\Type\Atomic\TFalse && $call_arg_type->ignore_falsable_issues || $unpacked_type_part instanceof \Psalm\Type\Atomic\TNull && $call_arg_type->ignore_nullable_issues) { continue; } if ($unpacked_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { foreach ($unpacked_type_part->properties as $key => $type) { if (!\is_string($key)) { $generic_properties[] = $type; continue; } if (!isset($generic_properties[$key]) || !$type->possibly_undefined) { $generic_properties[$key] = $type; } else { $was_possibly_undefined = $generic_properties[$key]->possibly_undefined; $generic_properties[$key] = \Psalm\Type::combineUnionTypes($generic_properties[$key], $type, $codebase); $generic_properties[$key]->possibly_undefined = $was_possibly_undefined; } } if (!$unpacked_type_part->is_list) { $all_nonempty_lists = \false; } if ($unpacked_type_part->sealed) { $any_nonempty = \true; } continue; } if ($unpacked_type_part instanceof \Psalm\Type\Atomic\TList) { $all_keyed_arrays = \false; if (!$unpacked_type_part instanceof \Psalm\Type\Atomic\TNonEmptyList) { $all_nonempty_lists = \false; } else { $any_nonempty = \true; } } else { if ($unpacked_type_part instanceof \Psalm\Type\Atomic\TMixed && $unpacked_type_part->from_loop_isset) { $unpacked_type_part = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getMixed(\true)]); } else { return \Psalm\Type::getArray(); } } } else { if (!$unpacked_type_part->type_params[0]->isEmpty()) { foreach ($generic_properties as $key => $keyed_type) { $generic_properties[$key] = \Psalm\Type::combineUnionTypes($keyed_type, $unpacked_type_part->type_params[1], $codebase); } $all_keyed_arrays = \false; $all_nonempty_lists = \false; } } if ($unpacked_type_part instanceof \Psalm\Type\Atomic\TArray) { if ($unpacked_type_part->type_params[1]->isEmpty()) { continue; } if (!$unpacked_type_part->type_params[0]->isInt()) { $all_int_offsets = \false; } if ($unpacked_type_part instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $any_nonempty = \true; } } $inner_key_types = \array_merge($inner_key_types, $unpacked_type_part instanceof \Psalm\Type\Atomic\TList ? [new \Psalm\Type\Atomic\TInt()] : \array_values($unpacked_type_part->type_params[0]->getAtomicTypes())); $inner_value_types = \array_merge($inner_value_types, $unpacked_type_part instanceof \Psalm\Type\Atomic\TList ? \array_values($unpacked_type_part->type_param->getAtomicTypes()) : \array_values($unpacked_type_part->type_params[1]->getAtomicTypes())); } } } $inner_key_type = null; $inner_value_type = null; if ($inner_key_types) { $inner_key_type = \Psalm\Internal\Type\TypeCombination::combineTypes($inner_key_types, $codebase, \true); } if ($inner_value_types) { $inner_value_type = \Psalm\Internal\Type\TypeCombination::combineTypes($inner_value_types, $codebase, \true); } if ($generic_properties) { $objectlike = new \Psalm\Type\Atomic\TKeyedArray($generic_properties); if ($all_nonempty_lists || $all_int_offsets) { $objectlike->is_list = \true; } if (!$all_keyed_arrays) { $objectlike->previous_key_type = $inner_key_type; $objectlike->previous_value_type = $inner_value_type; } return new \Psalm\Type\Union([$objectlike]); } if ($inner_value_type) { if ($all_int_offsets) { if ($any_nonempty) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyList($inner_value_type)]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList($inner_value_type)]); } $inner_key_type = $inner_key_type ?: \Psalm\Type::getArrayKey(); if ($any_nonempty) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyArray([$inner_key_type, $inner_value_type])]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([$inner_key_type, $inner_value_type])]); } return \Psalm\Type::getArray(); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } return \Psalm\Type::getInt(\true); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if ($subject_type = $statements_source->node_data->getType($call_args[2]->value)) { if (!$subject_type->hasString() && $subject_type->hasArray()) { return \Psalm\Type::getArray(); } $return_type = \Psalm\Type::getString(); if (\in_array($function_id, ['preg_replace', 'preg_replace_callback'], \true)) { $return_type->addType(new \Psalm\Type\Atomic\TNull()); $codebase = $statements_source->getCodebase(); if ($codebase->config->ignore_internal_nullable_issues) { $return_type->ignore_nullable_issues = \true; } } return $return_type; } return \Psalm\Type::getMixed(); } } = 2 && ($array_arg_type = $statements_source->getNodeTypeProvider()->getType($call_args[0]->value)) && $array_arg_type->isSingle() && $array_arg_type->hasArray() && ($array_type = \Psalm\Internal\Type\ArrayType::infer($array_arg_type->getAtomicTypes()['array']))) { $preserve_keys = isset($call_args[2]) && ($preserve_keys_arg_type = $statements_source->getNodeTypeProvider()->getType($call_args[2]->value)) && (string) $preserve_keys_arg_type !== 'false'; return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList(new \Psalm\Type\Union([$preserve_keys ? new \Psalm\Type\Atomic\TNonEmptyArray([$array_type->key, $array_type->value]) : new \Psalm\Type\Atomic\TNonEmptyList($array_type->value)]))]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList(\Psalm\Type::getArray())]); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $row_shape = null; $input_array_not_empty = \false; // calculate row shape if (($first_arg_type = $statements_source->node_data->getType($call_args[0]->value)) && $first_arg_type->isSingle() && $first_arg_type->hasArray()) { $input_array = $first_arg_type->getAtomicTypes()['array']; if ($input_array instanceof \Psalm\Type\Atomic\TKeyedArray) { $row_type = $input_array->getGenericArrayType()->type_params[1]; if ($row_type->isSingle() && $row_type->hasArray()) { $row_shape = $row_type->getAtomicTypes()['array']; } } elseif ($input_array instanceof \Psalm\Type\Atomic\TArray) { $row_type = $input_array->type_params[1]; if ($row_type->isSingle() && $row_type->hasArray()) { $row_shape = $row_type->getAtomicTypes()['array']; } } elseif ($input_array instanceof \Psalm\Type\Atomic\TList) { $row_type = $input_array->type_param; if ($row_type->isSingle() && $row_type->hasArray()) { $row_shape = $row_type->getAtomicTypes()['array']; } } $input_array_not_empty = $input_array instanceof \Psalm\Type\Atomic\TNonEmptyList || $input_array instanceof \Psalm\Type\Atomic\TNonEmptyArray || $input_array instanceof \Psalm\Type\Atomic\TKeyedArray; } $value_column_name = null; // calculate value column name if ($second_arg_type = $statements_source->node_data->getType($call_args[1]->value)) { if ($second_arg_type->isSingleIntLiteral()) { $value_column_name = $second_arg_type->getSingleIntLiteral()->value; } elseif ($second_arg_type->isSingleStringLiteral()) { $value_column_name = $second_arg_type->getSingleStringLiteral()->value; } } $key_column_name = null; $third_arg_type = null; // calculate key column name if (isset($call_args[2])) { $third_arg_type = $statements_source->node_data->getType($call_args[2]->value); if ($third_arg_type) { if ($third_arg_type->isSingleIntLiteral()) { $key_column_name = $third_arg_type->getSingleIntLiteral()->value; } elseif ($third_arg_type->isSingleStringLiteral()) { $key_column_name = $third_arg_type->getSingleStringLiteral()->value; } } } $result_key_type = \Psalm\Type::getArrayKey(); $result_element_type = null; $have_at_least_one_res = \false; // calculate results if ($row_shape instanceof \Psalm\Type\Atomic\TKeyedArray) { if (null !== $value_column_name && isset($row_shape->properties[$value_column_name])) { if ($input_array_not_empty) { $have_at_least_one_res = \true; } $result_element_type = $row_shape->properties[$value_column_name]; } else { $result_element_type = \Psalm\Type::getMixed(); } if (null !== $key_column_name && isset($row_shape->properties[$key_column_name])) { $result_key_type = $row_shape->properties[$key_column_name]; } } if (isset($call_args[2]) && (string) $third_arg_type !== 'null') { $type = $have_at_least_one_res ? new \Psalm\Type\Atomic\TNonEmptyArray([$result_key_type, $result_element_type ?? \Psalm\Type::getMixed()]) : new \Psalm\Type\Atomic\TArray([$result_key_type, $result_element_type ?? \Psalm\Type::getMixed()]); } else { $type = $have_at_least_one_res ? new \Psalm\Type\Atomic\TNonEmptyList($result_element_type ?? \Psalm\Type::getMixed()) : new \Psalm\Type\Atomic\TList($result_element_type ?? \Psalm\Type::getMixed()); } return new \Psalm\Type\Union([$type]); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : ?\Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (($first_arg_type = $statements_source->node_data->getType($call_args[0]->value)) && ($first_arg_type->hasObjectType() || $first_arg_type->hasString())) { return \Psalm\Type::parseString('array'); } return null; } } $call_args */ public static function getMethodReturnType(\Psalm\StatementsSource $source, string $fq_classlike_name, string $method_name_lowercase, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location, ?array $template_type_parameters = null, ?string $called_fq_classlike_name = null, ?string $called_method_name_lowercase = null) : ?\Psalm\Type\Union { if ($method_name_lowercase === 'asxml' && !\count($call_args)) { return \Psalm\Type::parseString('string|false'); } return null; } } getNodeTypeProvider(); if (\count($call_args) >= 3 && ($array_arg_type = $type_provider->getType($call_args[0]->value)) && ($size_arg_type = $type_provider->getType($call_args[1]->value)) && ($value_arg_type = $type_provider->getType($call_args[2]->value)) && $array_arg_type->isSingle() && $array_arg_type->hasArray() && ($array_type = \Psalm\Internal\Type\ArrayType::infer($array_arg_type->getAtomicTypes()['array']))) { $codebase = $statements_source->getCodebase(); $key_type = \Psalm\Type::combineUnionTypes($array_type->key, \Psalm\Type::getInt(), $codebase); $value_type = \Psalm\Type::combineUnionTypes($array_type->value, $value_arg_type, $codebase); $can_return_empty = !$size_arg_type->isSingleIntLiteral() || $size_arg_type->getSingleIntLiteral()->value === 0; return new \Psalm\Type\Union([$array_type->is_list ? $can_return_empty ? new \Psalm\Type\Atomic\TList($value_type) : new \Psalm\Type\Atomic\TNonEmptyList($value_type) : ($can_return_empty ? new \Psalm\Type\Atomic\TArray([$key_type, $value_type]) : new \Psalm\Type\Atomic\TNonEmptyArray([$key_type, $value_type]))]); } return \Psalm\Type::getArray(); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (\count($call_args) > 1) { if ($component_type = $statements_source->node_data->getType($call_args[1]->value)) { if (!$component_type->hasMixed()) { $codebase = $statements_source->getCodebase(); $acceptable_string_component_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralInt(\PHP_URL_SCHEME), new \Psalm\Type\Atomic\TLiteralInt(\PHP_URL_USER), new \Psalm\Type\Atomic\TLiteralInt(\PHP_URL_PASS), new \Psalm\Type\Atomic\TLiteralInt(\PHP_URL_HOST), new \Psalm\Type\Atomic\TLiteralInt(\PHP_URL_PATH), new \Psalm\Type\Atomic\TLiteralInt(\PHP_URL_QUERY), new \Psalm\Type\Atomic\TLiteralInt(\PHP_URL_FRAGMENT)]); $acceptable_int_component_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralInt(\PHP_URL_PORT)]); if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $component_type, $acceptable_string_component_type)) { $nullable_falsable_string = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TString(), new \Psalm\Type\Atomic\TFalse(), new \Psalm\Type\Atomic\TNull()]); $codebase = $statements_source->getCodebase(); if ($codebase->config->ignore_internal_nullable_issues) { $nullable_falsable_string->ignore_nullable_issues = \true; } if ($codebase->config->ignore_internal_falsable_issues) { $nullable_falsable_string->ignore_falsable_issues = \true; } return $nullable_falsable_string; } if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $component_type, $acceptable_int_component_type)) { $nullable_falsable_int = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TFalse(), new \Psalm\Type\Atomic\TNull()]); $codebase = $statements_source->getCodebase(); if ($codebase->config->ignore_internal_nullable_issues) { $nullable_falsable_int->ignore_nullable_issues = \true; } if ($codebase->config->ignore_internal_falsable_issues) { $nullable_falsable_int->ignore_falsable_issues = \true; } return $nullable_falsable_int; } } } $nullable_string_or_int = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TString(), new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TNull()]); $codebase = $statements_source->getCodebase(); if ($codebase->config->ignore_internal_nullable_issues) { $nullable_string_or_int->ignore_nullable_issues = \true; } return $nullable_string_or_int; } $component_types = ['scheme' => \Psalm\Type::getString(), 'user' => \Psalm\Type::getString(), 'pass' => \Psalm\Type::getString(), 'host' => \Psalm\Type::getString(), 'port' => \Psalm\Type::getInt(), 'path' => \Psalm\Type::getString(), 'query' => \Psalm\Type::getString(), 'fragment' => \Psalm\Type::getString()]; foreach ($component_types as $component_type) { $component_type->possibly_undefined = \true; } $return_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TKeyedArray($component_types), new \Psalm\Type\Atomic\TFalse()]); if ($statements_source->getCodebase()->config->ignore_internal_falsable_issues) { $return_type->ignore_falsable_issues = \true; } return $return_type; } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $first_arg = $call_args[0]->value ?? null; $first_arg_array = $first_arg && ($first_arg_type = $statements_source->node_data->getType($first_arg)) && $first_arg_type->hasType('array') && ($array_atomic_type = $first_arg_type->getAtomicTypes()['array']) && ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TList) ? $array_atomic_type : null; if (!$first_arg_array) { return \Psalm\Type::getArray(); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TArray) { $first_arg_array = clone $first_arg_array; if ($first_arg_array instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $first_arg_array->count = null; } return new \Psalm\Type\Union([$first_arg_array]); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TList) { if ($first_arg_array instanceof \Psalm\Type\Atomic\TNonEmptyList) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyArray([\Psalm\Type::getInt(), clone $first_arg_array->type_param])]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), clone $first_arg_array->type_param])]); } return new \Psalm\Type\Union([$first_arg_array->getGenericArrayType()]); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (\count($call_args) >= 2) { $second_arg_type = $statements_source->node_data->getType($call_args[1]->value); $inner_type = new \Psalm\Type\Union([$second_arg_type && $second_arg_type->hasLowercaseString() ? new \Psalm\Type\Atomic\TLowercaseString() : new \Psalm\Type\Atomic\TString()]); $can_return_empty = isset($call_args[2]) && (!$call_args[2]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || $call_args[2]->value->value < 0); if ($call_args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if ($call_args[0]->value->value === '') { return \Psalm\Type::getFalse(); } return new \Psalm\Type\Union([$can_return_empty ? new \Psalm\Type\Atomic\TList($inner_type) : new \Psalm\Type\Atomic\TNonEmptyList($inner_type)]); } elseif (($first_arg_type = $statements_source->node_data->getType($call_args[0]->value)) && $first_arg_type->hasString()) { $falsable_array = new \Psalm\Type\Union([$can_return_empty ? new \Psalm\Type\Atomic\TList($inner_type) : new \Psalm\Type\Atomic\TNonEmptyList($inner_type), new \Psalm\Type\Atomic\TFalse()]); if ($statements_source->getCodebase()->config->ignore_internal_falsable_issues) { $falsable_array->ignore_falsable_issues = \true; } return $falsable_array; } } return \Psalm\Type::getMixed(); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (\count($call_args) > 2) { $operator_type = $statements_source->node_data->getType($call_args[2]->value); if ($operator_type) { if (!$operator_type->hasMixed()) { $acceptable_operator_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralString('<'), new \Psalm\Type\Atomic\TLiteralString('lt'), new \Psalm\Type\Atomic\TLiteralString('<='), new \Psalm\Type\Atomic\TLiteralString('le'), new \Psalm\Type\Atomic\TLiteralString('>'), new \Psalm\Type\Atomic\TLiteralString('gt'), new \Psalm\Type\Atomic\TLiteralString('>='), new \Psalm\Type\Atomic\TLiteralString('ge'), new \Psalm\Type\Atomic\TLiteralString('=='), new \Psalm\Type\Atomic\TLiteralString('='), new \Psalm\Type\Atomic\TLiteralString('eq'), new \Psalm\Type\Atomic\TLiteralString('!='), new \Psalm\Type\Atomic\TLiteralString('<>'), new \Psalm\Type\Atomic\TLiteralString('ne')]); $codebase = $statements_source->getCodebase(); if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $operator_type, $acceptable_operator_type)) { return \Psalm\Type::getBool(); } } } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TBool(), new \Psalm\Type\Atomic\TNull()]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralInt(-1), new \Psalm\Type\Atomic\TLiteralInt(0), new \Psalm\Type\Atomic\TLiteralInt(1)]); } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { throw new \UnexpectedValueException(); } $filter_type = null; if (isset($call_args[1]) && ($second_arg_type = $statements_source->node_data->getType($call_args[1]->value)) && $second_arg_type->isSingleIntLiteral()) { $filter_type_type = $second_arg_type->getSingleIntLiteral(); $filter_type = null; switch ($filter_type_type->value) { case \FILTER_VALIDATE_INT: $filter_type = \Psalm\Type::getInt(); break; case \FILTER_VALIDATE_FLOAT: $filter_type = \Psalm\Type::getFloat(); break; case \FILTER_VALIDATE_BOOLEAN: $filter_type = \Psalm\Type::getBool(); break; case \FILTER_VALIDATE_IP: case \FILTER_VALIDATE_MAC: case \FILTER_VALIDATE_REGEXP: case \FILTER_VALIDATE_URL: case \FILTER_VALIDATE_EMAIL: case \FILTER_VALIDATE_DOMAIN: $filter_type = \Psalm\Type::getString(); break; } $has_object_like = \false; $filter_null = \false; if (isset($call_args[2]) && ($third_arg_type = $statements_source->node_data->getType($call_args[2]->value)) && $filter_type) { foreach ($third_arg_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $has_object_like = \true; if (isset($atomic_type->properties['options']) && $atomic_type->properties['options']->hasArray() && ($options_array = $atomic_type->properties['options']->getAtomicTypes()['array']) && $options_array instanceof \Psalm\Type\Atomic\TKeyedArray && isset($options_array->properties['default'])) { $filter_type = \Psalm\Type::combineUnionTypes($filter_type, $options_array->properties['default']); } else { $filter_type->addType(new \Psalm\Type\Atomic\TFalse()); } if (isset($atomic_type->properties['flags']) && $atomic_type->properties['flags']->isSingleIntLiteral()) { $filter_flag_type = $atomic_type->properties['flags']->getSingleIntLiteral(); if ($filter_type->hasBool() && $filter_flag_type->value === \FILTER_NULL_ON_FAILURE) { $filter_type->addType(new \Psalm\Type\Atomic\TNull()); } } } elseif ($atomic_type instanceof \Psalm\Type\Atomic\TLiteralInt) { if ($atomic_type->value === \FILTER_NULL_ON_FAILURE) { $filter_null = \true; $filter_type->addType(new \Psalm\Type\Atomic\TNull()); } } } } if (!$has_object_like && !$filter_null && $filter_type) { $filter_type->addType(new \Psalm\Type\Atomic\TFalse()); } } if (!$filter_type) { $filter_type = \Psalm\Type::getMixed(); } if ($statements_source->data_flow_graph && !\in_array('TaintedInput', $statements_source->getSuppressedIssues())) { $function_return_sink = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodReturn($function_id, $function_id, null, $code_location); $statements_source->data_flow_graph->addNode($function_return_sink); $function_param_sink = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodArgument($function_id, $function_id, 0, null, $code_location); $statements_source->data_flow_graph->addNode($function_param_sink); $statements_source->data_flow_graph->addPath($function_param_sink, $function_return_sink, 'arg'); $filter_type->parent_nodes = [$function_return_sink->id => $function_return_sink]; } return $filter_type; } } $call_args */ public static function getMethodReturnType(\Psalm\StatementsSource $source, string $fq_classlike_name, string $method_name_lowercase, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location, ?array $template_type_parameters = null, ?string $called_fq_classlike_name = null, ?string $called_method_name_lowercase = null) : ?\Psalm\Type\Union { if (!$source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if ($method_name_lowercase === 'appendchild' && ($first_arg_type = $source->node_data->getType($call_args[0]->value)) && $first_arg_type->hasObjectType()) { return clone $first_arg_type; } return null; } } $call_args */ public static function getMethodReturnType(\Psalm\StatementsSource $source, string $fq_classlike_name, string $method_name_lowercase, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location, ?array $template_type_parameters = null, ?string $called_fq_classlike_name = null, ?string $called_method_name_lowercase = null) : ?\Psalm\Type\Union { if (!$source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return null; } $type_provider = $source->getNodeTypeProvider(); $codebase = $source->getCodebase(); if ($method_name_lowercase === 'fromcallable') { $closure_types = []; if (isset($call_args[0]) && ($input_type = $type_provider->getType($call_args[0]->value))) { foreach ($input_type->getAtomicTypes() as $atomic_type) { $candidate_callable = \Psalm\Internal\Type\Comparator\CallableTypeComparator::getCallableFromAtomic($codebase, $atomic_type, null, $source); if ($candidate_callable) { $closure_types[] = new \Psalm\Type\Atomic\TClosure('Closure', $candidate_callable->params, $candidate_callable->return_type, $candidate_callable->is_pure); } else { return \Psalm\Type::getClosure(); } } } if ($closure_types) { return \Psalm\Internal\Type\TypeCombination::combineTypes($closure_types, $codebase); } return \Psalm\Type::getClosure(); } return null; } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $array_arg = isset($call_args[0]->value) ? $call_args[0]->value : null; $first_arg_array = $array_arg && ($first_arg_type = $statements_source->node_data->getType($array_arg)) && $first_arg_type->hasType('array') && ($array_atomic_type = $first_arg_type->getAtomicTypes()['array']) && ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TList) ? $array_atomic_type : null; if (!$first_arg_array) { return \Psalm\Type::getArray(); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TArray) { $inner_type = $first_arg_array->type_params[1]; $key_type = clone $first_arg_array->type_params[0]; } elseif ($first_arg_array instanceof \Psalm\Type\Atomic\TList) { $inner_type = $first_arg_array->type_param; $key_type = \Psalm\Type::getInt(); } else { $inner_type = $first_arg_array->getGenericValueType(); $key_type = $first_arg_array->getGenericKeyType(); if (!isset($call_args[1]) && !$first_arg_array->previous_value_type) { $had_one = \count($first_arg_array->properties) === 1; $first_arg_array = clone $first_arg_array; $new_properties = \array_filter(\array_map(function ($keyed_type) use($statements_source, $context) { $prev_keyed_type = $keyed_type; $keyed_type = \Psalm\Internal\Type\AssertionReconciler::reconcile('!falsy', clone $keyed_type, '', $statements_source, $context->inside_loop, [], null, $statements_source->getSuppressedIssues()); $keyed_type->possibly_undefined = $prev_keyed_type->hasInt() && !$prev_keyed_type->hasLiteralInt() || $prev_keyed_type->hasFloat() || $prev_keyed_type->getId() !== $keyed_type->getId(); return $keyed_type; }, $first_arg_array->properties), function ($keyed_type) { return !$keyed_type->isEmpty(); }); if (!$new_properties) { return \Psalm\Type::getEmptyArray(); } $first_arg_array->properties = $new_properties; $first_arg_array->is_list = $first_arg_array->is_list && $had_one; $first_arg_array->sealed = \false; return new \Psalm\Type\Union([$first_arg_array]); } } if (!isset($call_args[1])) { $inner_type = \Psalm\Internal\Type\AssertionReconciler::reconcile('!falsy', clone $inner_type, '', $statements_source, $context->inside_loop, [], null, $statements_source->getSuppressedIssues()); if ($first_arg_array instanceof \Psalm\Type\Atomic\TKeyedArray && $first_arg_array->is_list && $key_type->isSingleIntLiteral() && $key_type->getSingleIntLiteral()->value === 0) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList($inner_type)]); } if ($key_type->getLiteralStrings()) { $key_type->addType(new \Psalm\Type\Atomic\TString()); } if ($key_type->getLiteralInts()) { $key_type->addType(new \Psalm\Type\Atomic\TInt()); } if (!$inner_type->getAtomicTypes()) { return \Psalm\Type::getEmptyArray(); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([$key_type, $inner_type])]); } if (!isset($call_args[2])) { $function_call_arg = $call_args[1]; if ($function_call_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $function_call_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ || $function_call_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { $mapping_function_ids = \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::getFunctionIdsFromCallableArg($statements_source, $function_call_arg->value); if ($array_arg && $mapping_function_ids) { $assertions = []; \Psalm\Internal\Provider\ReturnTypeProvider\ArrayMapReturnTypeProvider::getReturnTypeFromMappingIds($statements_source, $mapping_function_ids, $context, $function_call_arg, \array_slice($call_args, 0, 1), $assertions); $array_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($array_arg, null, $statements_source); if (isset($assertions[$array_var_id . '[$__fake_offset_var__]'])) { $changed_var_ids = []; $assertions = ['$inner_type' => $assertions[$array_var_id . '[$__fake_offset_var__]']]; $reconciled_types = \Psalm\Type\Reconciler::reconcileKeyedTypes($assertions, $assertions, ['$inner_type' => $inner_type], $changed_var_ids, ['$inner_type' => \true], $statements_source, $statements_source->getTemplateTypeMap() ?: [], \false, new \Psalm\CodeLocation($statements_source, $function_call_arg->value)); if (isset($reconciled_types['$inner_type'])) { $inner_type = $reconciled_types['$inner_type']; } } } } elseif (($function_call_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $function_call_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) && ($second_arg_type = $statements_source->node_data->getType($function_call_arg->value)) && ($closure_types = $second_arg_type->getClosureTypes())) { $closure_atomic_type = \reset($closure_types); $closure_return_type = $closure_atomic_type->return_type ?: \Psalm\Type::getMixed(); if ($closure_return_type->isVoid()) { \Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidReturnType('No return type could be found in the closure passed to array_filter', $code_location), $statements_source->getSuppressedIssues()); return \Psalm\Type::getArray(); } if (\count($function_call_arg->value->getStmts()) === 1 && \count($function_call_arg->value->params)) { $first_param = $function_call_arg->value->params[0]; $stmt = $function_call_arg->value->getStmts()[0]; if ($first_param->variadic === \false && $first_param->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($first_param->var->name) && $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_ && $stmt->expr) { $codebase = $statements_source->getCodebase(); $assertions = \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::scrapeAssertions($stmt->expr, null, $statements_source, $codebase); if (isset($assertions['$' . $first_param->var->name])) { $changed_var_ids = []; $assertions = ['$inner_type' => $assertions['$' . $first_param->var->name]]; $reconciled_types = \Psalm\Type\Reconciler::reconcileKeyedTypes($assertions, $assertions, ['$inner_type' => $inner_type], $changed_var_ids, ['$inner_type' => \true], $statements_source, $statements_source->getTemplateTypeMap() ?: [], \false, new \Psalm\CodeLocation($statements_source, $stmt)); if (isset($reconciled_types['$inner_type'])) { $inner_type = $reconciled_types['$inner_type']; } } } } } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([$key_type, $inner_type])]); } if (!$inner_type->getAtomicTypes()) { return \Psalm\Type::getEmptyArray(); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([$key_type, $inner_type])]); } } $call_args */ public static function getMethodReturnType(\Psalm\StatementsSource $source, string $fq_classlike_name, string $method_name_lowercase, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location, ?array $template_type_parameters = null, ?string $called_fq_classlike_name = null, ?string $called_method_name_lowercase = null) : ?\Psalm\Type\Union { if ($method_name_lowercase === 'fetch' && \class_exists('PDO') && 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 \PDO::FETCH_ASSOC: // array|false return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getString(), \Psalm\Type::getScalar()]), new \Psalm\Type\Atomic\TFalse()]); case \PDO::FETCH_BOTH: // array|false return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getScalar()]), new \Psalm\Type\Atomic\TFalse()]); case \PDO::FETCH_BOUND: // bool return \Psalm\Type::getBool(); case \PDO::FETCH_CLASS: // object|false return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TObject(), new \Psalm\Type\Atomic\TFalse()]); case \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 \Psalm\Type\Union([new \Psalm\Type\Atomic\TObject(), new \Psalm\Type\Atomic\TFalse()]); case \PDO::FETCH_NAMED: // array>|false return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getString(), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TScalar(), new \Psalm\Type\Atomic\TList(\Psalm\Type::getScalar())])]), new \Psalm\Type\Atomic\TFalse()]); case \PDO::FETCH_NUM: // list|false return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList(\Psalm\Type::getScalar()), new \Psalm\Type\Atomic\TFalse()]); case \PDO::FETCH_OBJ: // stdClass|false return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject('stdClass'), new \Psalm\Type\Atomic\TFalse()]); } } return null; } } $call_args * * @return ?array */ public static function getMethodParams(string $fq_classlike_name, string $method_name_lowercase, ?array $call_args = null, ?\Psalm\StatementsSource $statements_source = null, ?\Psalm\Context $context = null, ?\Psalm\CodeLocation $code_location = null) : ?array { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return null; } if ($method_name_lowercase === 'setfetchmode') { if (!$context || !$call_args || \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_source, $call_args[0]->value, $context) === \false) { return null; } if (($first_call_arg_type = $statements_source->node_data->getType($call_args[0]->value)) && $first_call_arg_type->isSingleIntLiteral()) { $params = [new \Psalm\Storage\FunctionLikeParameter('mode', \false, \Psalm\Type::getInt(), null, null, \false)]; $value = $first_call_arg_type->getSingleIntLiteral()->value; switch ($value) { case \PDO::FETCH_COLUMN: $params[] = new \Psalm\Storage\FunctionLikeParameter('colno', \false, \Psalm\Type::getInt(), null, null, \false); break; case \PDO::FETCH_CLASS: $params[] = new \Psalm\Storage\FunctionLikeParameter('classname', \false, \Psalm\Type::getClassString(), null, null, \false); $params[] = new \Psalm\Storage\FunctionLikeParameter('ctorargs', \false, \Psalm\Type::getArray(), null, null, \true); break; case \PDO::FETCH_INTO: $params[] = new \Psalm\Storage\FunctionLikeParameter('object', \false, \Psalm\Type::getObject(), null, null, \false); break; } return $params; } } return null; } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $first_arg = isset($call_args[0]->value) ? $call_args[0]->value : null; $first_arg_array = $first_arg && ($first_arg_type = $statements_source->node_data->getType($first_arg)) && $first_arg_type->hasType('array') && !$first_arg_type->hasMixed() && ($array_atomic_type = $first_arg_type->getAtomicTypes()['array']) && ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TList) ? $array_atomic_type : null; if (!$first_arg_array) { return \Psalm\Type::getMixed(); } $nullable = \false; if ($first_arg_array instanceof \Psalm\Type\Atomic\TArray) { $value_type = clone $first_arg_array->type_params[1]; if ($value_type->isEmpty()) { return \Psalm\Type::getNull(); } if (!$first_arg_array instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $nullable = \true; } } elseif ($first_arg_array instanceof \Psalm\Type\Atomic\TList) { $value_type = clone $first_arg_array->type_param; if (!$first_arg_array instanceof \Psalm\Type\Atomic\TNonEmptyList) { $nullable = \true; } } else { // special case where we know the type of the first element if ($function_id === 'array_shift' && $first_arg_array->is_list && isset($first_arg_array->properties[0])) { $value_type = clone $first_arg_array->properties[0]; } else { $value_type = $first_arg_array->getGenericValueType(); if (!$first_arg_array->sealed && !$first_arg_array->previous_value_type) { $nullable = \true; } } } if ($nullable) { $value_type->addType(new \Psalm\Type\Atomic\TNull()); $codebase = $statements_source->getCodebase(); if ($codebase->config->ignore_internal_nullable_issues) { $value_type->ignore_nullable_issues = \true; } } return $value_type; } } $call_args */ public static function getFunctionReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : \Psalm\Type\Union { if (!$statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } $first_arg = $call_args[0]->value ?? null; $first_arg_array = $first_arg && ($first_arg_type = $statements_source->node_data->getType($first_arg)) && $first_arg_type->hasType('array') && ($array_atomic_type = $first_arg_type->getAtomicTypes()['array']) && ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TList) ? $array_atomic_type : null; if (!$first_arg_array) { return \Psalm\Type::getArray(); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TArray) { return new \Psalm\Type\Union([clone $first_arg_array]); } if ($first_arg_array instanceof \Psalm\Type\Atomic\TList) { $second_arg = $call_args[1]->value ?? null; if (!$second_arg || ($second_arg_type = $statements_source->node_data->getType($second_arg)) && $second_arg_type->isFalse()) { return new \Psalm\Type\Union([clone $first_arg_array]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), clone $first_arg_array->type_param])]); } return new \Psalm\Type\Union([$first_arg_array->getGenericArrayType()]); } } * > */ private static $handlers = []; public function __construct() { self::$handlers = []; } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'isPropertyVisible']); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); } } /** * /** * @param \Closure( * StatementsSource, * string, * string, * bool, * Context, * CodeLocation * ) : ?bool $c * */ public function registerClosure(string $fq_classlike_name, \Closure $c) : void { self::$handlers[\strtolower($fq_classlike_name)][] = $c; } public function has(string $fq_classlike_name) : bool { return isset(self::$handlers[\strtolower($fq_classlike_name)]); } /** * @param array $call_args * */ public function isPropertyVisible(\Psalm\StatementsSource $source, string $fq_classlike_name, string $property_name, bool $read_mode, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : ?bool { foreach (self::$handlers[\strtolower($fq_classlike_name)] as $property_handler) { $property_visible = $property_handler($source, $fq_classlike_name, $property_name, $read_mode, $context, $code_location); if ($property_visible !== null) { return $property_visible; } } return null; } } file_provider = $file_provider; $this->parser_cache_provider = $parser_cache_provider; $this->project_cache_provider = $project_cache_provider; $this->file_storage_provider = new \Psalm\Internal\Provider\FileStorageProvider($file_storage_cache_provider); $this->classlike_storage_provider = new \Psalm\Internal\Provider\ClassLikeStorageProvider($classlike_storage_cache_provider); $this->statements_provider = new \Psalm\Internal\Provider\StatementsProvider($file_provider, $parser_cache_provider, $file_storage_cache_provider); $this->file_reference_provider = new \Psalm\Internal\Provider\FileReferenceProvider($file_reference_cache_provider); } } > */ private static $nonmethod_references_to_classes = []; /** * A lookup table used for getting all the methods that reference a class * * @var array> */ private static $method_references_to_classes = []; /** * A lookup table used for getting all the files that reference a class member * * @var array> */ private static $file_references_to_class_members = []; /** * A lookup table used for getting all the files that reference a missing class member * * @var array> */ private static $file_references_to_missing_class_members = []; /** * @var array> */ private static $files_inheriting_classes = []; /** * A list of all files deleted since the last successful run * * @var array|null */ private static $deleted_files = null; /** * A lookup table used for getting all the files referenced by a file * * @var array, i:array}> */ private static $file_references = []; /** * @var array> */ private static $method_references_to_class_members = []; /** * @var array> */ private static $method_references_to_missing_class_members = []; /** * @var array> */ private static $references_to_mixed_member_names = []; /** * @var array> */ private static $class_method_locations = []; /** * @var array> */ private static $class_property_locations = []; /** * @var array> */ private static $class_locations = []; /** * @var array */ private static $classlike_files = []; /** * @var array> */ private static $analyzed_methods = []; /** * @var array> */ private static $issues = []; /** * @var array */ private static $file_maps = []; /** * @var array */ private static $mixed_counts = []; /** * @var array>> */ private static $method_param_uses = []; /** * @var ?FileReferenceCacheProvider */ public $cache; public function __construct(?\Psalm\Internal\Provider\FileReferenceCacheProvider $cache = null) { $this->cache = $cache; } /** * @return array */ public function getDeletedReferencedFiles() : array { if (self::$deleted_files === null) { self::$deleted_files = \array_filter(\array_keys(self::$file_references), function (string $file_name) : bool { return !\file_exists($file_name); }); } return self::$deleted_files; } /** * @param lowercase-string $fq_class_name_lc */ public function addNonMethodReferenceToClass(string $source_file, string $fq_class_name_lc) : void { self::$nonmethod_references_to_classes[$fq_class_name_lc][$source_file] = \true; } /** * @return array> */ public function getAllNonMethodReferencesToClasses() : array { return self::$nonmethod_references_to_classes; } /** * @param array> $references * */ public function addNonMethodReferencesToClasses(array $references) : void { foreach ($references as $key => $reference) { if (isset(self::$nonmethod_references_to_classes[$key])) { self::$nonmethod_references_to_classes[$key] = \array_merge($reference, self::$nonmethod_references_to_classes[$key]); } else { self::$nonmethod_references_to_classes[$key] = $reference; } } } /** * @param array $map */ public function addClassLikeFiles(array $map) : void { self::$classlike_files += $map; } public function addFileReferenceToClassMember(string $source_file, string $referenced_member_id) : void { self::$file_references_to_class_members[$referenced_member_id][$source_file] = \true; } public function addFileReferenceToMissingClassMember(string $source_file, string $referenced_member_id) : void { self::$file_references_to_missing_class_members[$referenced_member_id][$source_file] = \true; } /** * @return array> */ public function getAllFileReferencesToClassMembers() : array { return self::$file_references_to_class_members; } /** * @return array> */ public function getAllFileReferencesToMissingClassMembers() : array { return self::$file_references_to_missing_class_members; } /** * @param array> $references * */ public function addFileReferencesToClassMembers(array $references) : void { foreach ($references as $key => $reference) { if (isset(self::$file_references_to_class_members[$key])) { self::$file_references_to_class_members[$key] = \array_merge($reference, self::$file_references_to_class_members[$key]); } else { self::$file_references_to_class_members[$key] = $reference; } } } /** * @param array> $references * */ public function addFileReferencesToMissingClassMembers(array $references) : void { foreach ($references as $key => $reference) { if (isset(self::$file_references_to_missing_class_members[$key])) { self::$file_references_to_missing_class_members[$key] = \array_merge($reference, self::$file_references_to_missing_class_members[$key]); } else { self::$file_references_to_missing_class_members[$key] = $reference; } } } public function addFileInheritanceToClass(string $source_file, string $fq_class_name_lc) : void { self::$files_inheriting_classes[$fq_class_name_lc][$source_file] = \true; } public function addMethodParamUse(string $method_id, int $offset, string $referencing_method_id) : void { self::$method_param_uses[$method_id][$offset][$referencing_method_id] = \true; } /** * @return array */ private function calculateFilesReferencingFile(\Psalm\Codebase $codebase, string $file) : array { $referenced_files = []; $file_classes = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getClassesForFile($codebase, $file); foreach ($file_classes as $file_class_lc => $_) { if (isset(self::$nonmethod_references_to_classes[$file_class_lc])) { $new_files = \array_keys(self::$nonmethod_references_to_classes[$file_class_lc]); $referenced_files = \array_merge($referenced_files, $new_files); } if (isset(self::$method_references_to_classes[$file_class_lc])) { $new_referencing_methods = \array_keys(self::$method_references_to_classes[$file_class_lc]); foreach ($new_referencing_methods as $new_referencing_method_id) { $fq_class_name_lc = \explode('::', $new_referencing_method_id)[0]; try { $referenced_files[] = $codebase->scanner->getClassLikeFilePath($fq_class_name_lc); } catch (\UnexpectedValueException $e) { if (isset(self::$classlike_files[$fq_class_name_lc])) { $referenced_files[] = self::$classlike_files[$fq_class_name_lc]; } } } } } return \array_unique($referenced_files); } /** * @return array */ private function calculateFilesInheritingFile(\Psalm\Codebase $codebase, string $file) : array { $referenced_files = []; $file_classes = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getClassesForFile($codebase, $file); foreach ($file_classes as $file_class_lc => $_) { if (isset(self::$files_inheriting_classes[$file_class_lc])) { $referenced_files = \array_merge($referenced_files, \array_keys(self::$files_inheriting_classes[$file_class_lc])); } } return \array_unique($referenced_files); } public function removeDeletedFilesFromReferences() : void { $deleted_files = self::getDeletedReferencedFiles(); if ($deleted_files) { foreach ($deleted_files as $file) { unset(self::$file_references[$file]); } if ($this->cache) { $this->cache->setCachedFileReferences(self::$file_references); } } } /** * @return array */ public function getFilesReferencingFile(string $file) : array { return isset(self::$file_references[$file]['a']) ? self::$file_references[$file]['a'] : []; } /** * @return array */ public function getFilesInheritingFromFile(string $file) : array { return isset(self::$file_references[$file]['i']) ? self::$file_references[$file]['i'] : []; } /** * @return array> */ public function getAllMethodReferencesToClassMembers() : array { return self::$method_references_to_class_members; } /** * @return array> */ public function getAllMethodReferencesToClasses() : array { return self::$method_references_to_classes; } /** * @return array> */ public function getAllMethodReferencesToMissingClassMembers() : array { return self::$method_references_to_missing_class_members; } /** * @return array> */ public function getAllReferencesToMixedMemberNames() : array { return self::$references_to_mixed_member_names; } /** * @return array>> */ public function getAllMethodParamUses() : array { return self::$method_param_uses; } /** * @psalm-suppress MixedPropertyTypeCoercion */ public function loadReferenceCache(bool $force_reload = \true) : bool { if ($this->cache && (!$this->loaded_from_cache || $force_reload)) { $this->loaded_from_cache = \true; $file_references = $this->cache->getCachedFileReferences(); if ($file_references === null) { return \false; } self::$file_references = $file_references; $nonmethod_references_to_classes = $this->cache->getCachedNonMethodClassReferences(); if ($nonmethod_references_to_classes === null) { return \false; } self::$nonmethod_references_to_classes = $nonmethod_references_to_classes; $method_references_to_classes = $this->cache->getCachedMethodClassReferences(); if ($method_references_to_classes === null) { return \false; } self::$method_references_to_classes = $method_references_to_classes; $method_references_to_class_members = $this->cache->getCachedMethodMemberReferences(); if ($method_references_to_class_members === null) { return \false; } self::$method_references_to_class_members = $method_references_to_class_members; $method_references_to_missing_class_members = $this->cache->getCachedMethodMissingMemberReferences(); if ($method_references_to_missing_class_members === null) { return \false; } self::$method_references_to_missing_class_members = $method_references_to_missing_class_members; $file_references_to_class_members = $this->cache->getCachedFileMemberReferences(); if ($file_references_to_class_members === null) { return \false; } self::$file_references_to_class_members = $file_references_to_class_members; $file_references_to_missing_class_members = $this->cache->getCachedFileMissingMemberReferences(); if ($file_references_to_missing_class_members === null) { return \false; } self::$file_references_to_missing_class_members = $file_references_to_missing_class_members; $references_to_mixed_member_names = $this->cache->getCachedMixedMemberNameReferences(); if ($references_to_mixed_member_names === null) { return \false; } self::$references_to_mixed_member_names = $references_to_mixed_member_names; $analyzed_methods = $this->cache->getAnalyzedMethodCache(); if ($analyzed_methods === \false) { return \false; } self::$analyzed_methods = $analyzed_methods; $issues = $this->cache->getCachedIssues(); if ($issues === null) { return \false; } self::$issues = $issues; $method_param_uses = $this->cache->getCachedMethodParamUses(); if ($method_param_uses === null) { return \false; } self::$method_param_uses = $method_param_uses; $mixed_counts = $this->cache->getTypeCoverage(); if ($mixed_counts === \false) { return \false; } self::$mixed_counts = $mixed_counts; $classlike_files = $this->cache->getCachedClassLikeFiles(); if ($classlike_files === null) { return \false; } self::$classlike_files = $classlike_files; self::$file_maps = $this->cache->getFileMapCache() ?: []; return \true; } return \false; } /** * @param array $visited_files * */ public function updateReferenceCache(\Psalm\Codebase $codebase, array $visited_files) : void { foreach ($visited_files as $file => $_) { $all_file_references = \array_unique(\array_merge(isset(self::$file_references[$file]['a']) ? self::$file_references[$file]['a'] : [], $this->calculateFilesReferencingFile($codebase, $file))); $inheritance_references = \array_unique(\array_merge(isset(self::$file_references[$file]['i']) ? self::$file_references[$file]['i'] : [], $this->calculateFilesInheritingFile($codebase, $file))); self::$file_references[$file] = ['a' => $all_file_references, 'i' => $inheritance_references]; } if ($this->cache) { $this->cache->setCachedFileReferences(self::$file_references); $this->cache->setCachedMethodClassReferences(self::$method_references_to_classes); $this->cache->setCachedNonMethodClassReferences(self::$nonmethod_references_to_classes); $this->cache->setCachedMethodMemberReferences(self::$method_references_to_class_members); $this->cache->setCachedFileMemberReferences(self::$file_references_to_class_members); $this->cache->setCachedMethodMissingMemberReferences(self::$method_references_to_missing_class_members); $this->cache->setCachedFileMissingMemberReferences(self::$file_references_to_missing_class_members); $this->cache->setCachedMixedMemberNameReferences(self::$references_to_mixed_member_names); $this->cache->setCachedMethodParamUses(self::$method_param_uses); $this->cache->setCachedIssues(self::$issues); $this->cache->setCachedClassLikeFiles(self::$classlike_files); $this->cache->setFileMapCache(self::$file_maps); $this->cache->setTypeCoverage(self::$mixed_counts); $this->cache->setAnalyzedMethodCache(self::$analyzed_methods); } } /** * @param lowercase-string $fq_class_name_lc */ public function addMethodReferenceToClass(string $calling_function_id, string $fq_class_name_lc) : void { if (!isset(self::$method_references_to_classes[$fq_class_name_lc])) { self::$method_references_to_classes[$fq_class_name_lc] = [$calling_function_id => \true]; } else { self::$method_references_to_classes[$fq_class_name_lc][$calling_function_id] = \true; } } public function addMethodReferenceToClassMember(string $calling_function_id, string $referenced_member_id) : void { if (!isset(self::$method_references_to_class_members[$referenced_member_id])) { self::$method_references_to_class_members[$referenced_member_id] = [$calling_function_id => \true]; } else { self::$method_references_to_class_members[$referenced_member_id][$calling_function_id] = \true; } } public function addMethodReferenceToMissingClassMember(string $calling_function_id, string $referenced_member_id) : void { if (!isset(self::$method_references_to_missing_class_members[$referenced_member_id])) { self::$method_references_to_missing_class_members[$referenced_member_id] = [$calling_function_id => \true]; } else { self::$method_references_to_missing_class_members[$referenced_member_id][$calling_function_id] = \true; } } public function addCallingLocationForClassMethod(\Psalm\CodeLocation $code_location, string $referenced_member_id) : void { if (!isset(self::$class_method_locations[$referenced_member_id])) { self::$class_method_locations[$referenced_member_id] = [$code_location]; } else { self::$class_method_locations[$referenced_member_id][] = $code_location; } } public function addCallingLocationForClassProperty(\Psalm\CodeLocation $code_location, string $referenced_property_id) : void { if (!isset(self::$class_property_locations[$referenced_property_id])) { self::$class_property_locations[$referenced_property_id] = [$code_location]; } else { self::$class_property_locations[$referenced_property_id][] = $code_location; } } public function addCallingLocationForClass(\Psalm\CodeLocation $code_location, string $referenced_class) : void { if (!isset(self::$class_locations[$referenced_class])) { self::$class_locations[$referenced_class] = [$code_location]; } else { self::$class_locations[$referenced_class][] = $code_location; } } public function isClassMethodReferenced(string $method_id) : bool { return !empty(self::$file_references_to_class_members[$method_id]) || !empty(self::$method_references_to_class_members[$method_id]); } public function isClassPropertyReferenced(string $property_id) : bool { return !empty(self::$file_references_to_class_members[$property_id]) || !empty(self::$method_references_to_class_members[$property_id]); } public function isClassReferenced(string $fq_class_name_lc) : bool { return isset(self::$method_references_to_classes[$fq_class_name_lc]) || isset(self::$nonmethod_references_to_classes[$fq_class_name_lc]); } public function isMethodParamUsed(string $method_id, int $offset) : bool { return !empty(self::$method_param_uses[$method_id][$offset]); } /** * @param array> $references * */ public function setNonMethodReferencesToClasses(array $references) : void { self::$nonmethod_references_to_classes = $references; } /** * @return array> */ public function getAllClassMethodLocations() : array { return self::$class_method_locations; } /** * @return array> */ public function getAllClassPropertyLocations() : array { return self::$class_property_locations; } /** * @return array> */ public function getAllClassLocations() : array { return self::$class_locations; } /** * @return array */ public function getClassMethodLocations(string $method_id) : array { return self::$class_method_locations[$method_id] ?? []; } /** * @return array */ public function getClassPropertyLocations(string $property_id) : array { return self::$class_property_locations[$property_id] ?? []; } /** * @return array */ public function getClassLocations(string $fq_class_name_lc) : array { return self::$class_locations[$fq_class_name_lc] ?? []; } /** * @param array> $references * */ public function addMethodReferencesToClassMembers(array $references) : void { foreach ($references as $key => $reference) { if (isset(self::$method_references_to_class_members[$key])) { self::$method_references_to_class_members[$key] = \array_merge($reference, self::$method_references_to_class_members[$key]); } else { self::$method_references_to_class_members[$key] = $reference; } } } /** * @param array> $references * */ public function addMethodReferencesToClasses(array $references) : void { foreach ($references as $key => $reference) { if (isset(self::$method_references_to_classes[$key])) { self::$method_references_to_classes[$key] = \array_merge($reference, self::$method_references_to_classes[$key]); } else { self::$method_references_to_classes[$key] = $reference; } } } /** * @param array> $references * */ public function addMethodReferencesToMissingClassMembers(array $references) : void { foreach ($references as $key => $reference) { if (isset(self::$method_references_to_missing_class_members[$key])) { self::$method_references_to_missing_class_members[$key] = \array_merge($reference, self::$method_references_to_missing_class_members[$key]); } else { self::$method_references_to_missing_class_members[$key] = $reference; } } } /** * @param array>> $references * */ public function addMethodParamUses(array $references) : void { foreach ($references as $method_id => $method_param_uses) { if (isset(self::$method_param_uses[$method_id])) { foreach ($method_param_uses as $offset => $reference_map) { if (isset(self::$method_param_uses[$method_id][$offset])) { self::$method_param_uses[$method_id][$offset] = \array_merge(self::$method_param_uses[$method_id][$offset], $reference_map); } else { self::$method_param_uses[$method_id][$offset] = $reference_map; } } } else { self::$method_param_uses[$method_id] = $method_param_uses; } } } /** * @param array> $references * */ public function setCallingMethodReferencesToClasses(array $references) : void { self::$method_references_to_classes = $references; } /** * @param array> $references * */ public function setCallingMethodReferencesToClassMembers(array $references) : void { self::$method_references_to_class_members = $references; } /** * @param array> $references * */ public function setCallingMethodReferencesToMissingClassMembers(array $references) : void { self::$method_references_to_missing_class_members = $references; } /** * @param array> $references * */ public function setFileReferencesToClassMembers(array $references) : void { self::$file_references_to_class_members = $references; } /** * @param array> $references * */ public function setFileReferencesToMissingClassMembers(array $references) : void { self::$file_references_to_missing_class_members = $references; } /** * @param array> $references * */ public function setReferencesToMixedMemberNames(array $references) : void { self::$references_to_mixed_member_names = $references; } /** * @param array>> $references * */ public function setMethodParamUses(array $references) : void { self::$method_param_uses = $references; } /** * @param array> $references * */ public function addClassMethodLocations(array $references) : void { foreach ($references as $referenced_member_id => $locations) { if (isset(self::$class_method_locations[$referenced_member_id])) { self::$class_method_locations[$referenced_member_id] = \array_merge(self::$class_method_locations[$referenced_member_id], $locations); } else { self::$class_method_locations[$referenced_member_id] = $locations; } } } /** * @param array> $references * */ public function addClassPropertyLocations(array $references) : void { foreach ($references as $referenced_member_id => $locations) { if (isset(self::$class_property_locations[$referenced_member_id])) { self::$class_property_locations[$referenced_member_id] = \array_merge(self::$class_property_locations[$referenced_member_id], $locations); } else { self::$class_property_locations[$referenced_member_id] = $locations; } } } /** * @param array> $references * */ public function addClassLocations(array $references) : void { foreach ($references as $referenced_member_id => $locations) { if (isset(self::$class_locations[$referenced_member_id])) { self::$class_locations[$referenced_member_id] = \array_merge(self::$class_locations[$referenced_member_id], $locations); } else { self::$class_locations[$referenced_member_id] = $locations; } } } /** * @return array> */ public function getExistingIssues() : array { return self::$issues; } public function clearExistingIssuesForFile(string $file_path) : void { unset(self::$issues[$file_path]); } public function clearExistingFileMapsForFile(string $file_path) : void { unset(self::$file_maps[$file_path]); } public function addIssue(string $file_path, \Psalm\Internal\Analyzer\IssueData $issue) : void { // don’t save parse errors ever, as they're not responsive to AST diffing if ($issue->type === 'ParseError') { return; } if (!isset(self::$issues[$file_path])) { self::$issues[$file_path] = [$issue]; } else { self::$issues[$file_path][] = $issue; } } /** * @param array> $analyzed_methods * */ public function setAnalyzedMethods(array $analyzed_methods) : void { self::$analyzed_methods = $analyzed_methods; } /** * @param array $file_maps */ public function setFileMaps(array $file_maps) : void { self::$file_maps = $file_maps; } /** * @return array */ public function getTypeCoverage() : array { return self::$mixed_counts; } /** * @param array $mixed_counts * */ public function setTypeCoverage(array $mixed_counts) : void { self::$mixed_counts = \array_merge(self::$mixed_counts, $mixed_counts); } /** * @return array> */ public function getAnalyzedMethods() : array { return self::$analyzed_methods; } /** * @return array */ public function getFileMaps() : array { return self::$file_maps; } public static function clearCache() : void { self::$files_inheriting_classes = []; self::$deleted_files = null; self::$file_references = []; self::$file_references_to_class_members = []; self::$method_references_to_class_members = []; self::$method_references_to_classes = []; self::$nonmethod_references_to_classes = []; self::$file_references_to_missing_class_members = []; self::$method_references_to_missing_class_members = []; self::$references_to_mixed_member_names = []; self::$class_method_locations = []; self::$class_property_locations = []; self::$class_locations = []; self::$analyzed_methods = []; self::$issues = []; self::$file_maps = []; self::$method_param_uses = []; self::$classlike_files = []; self::$mixed_counts = []; } } * > */ private static $handlers = []; public function __construct() { self::$handlers = []; } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'getPropertyType']); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); } } /** * /** * @param \Closure( * string, * string, * bool, * ?StatementsSource=, * ?Context= * ) : ?Type\Union $c * */ public function registerClosure(string $fq_classlike_name, \Closure $c) : void { self::$handlers[\strtolower($fq_classlike_name)][] = $c; } public function has(string $fq_classlike_name) : bool { return isset(self::$handlers[\strtolower($fq_classlike_name)]); } /** * @param array $call_args * */ public function getPropertyType(string $fq_classlike_name, string $property_name, bool $read_mode, ?\Psalm\StatementsSource $source = null, ?\Psalm\Context $context = null) : ?\Psalm\Type\Union { foreach (self::$handlers[\strtolower($fq_classlike_name)] as $property_handler) { $property_type = $property_handler($fq_classlike_name, $property_name, $read_mode, $source, $context); if ($property_type !== null) { return $property_type; } } return null; } } config = $config; } public function hasConfigChanged() : bool { $has_changed = $this->config->hash !== $this->getConfigHashCache(); $this->setConfigHashCache($this->config->hash); return $has_changed; } /** * @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; } $reference_cache = \unserialize((string) \file_get_contents($reference_cache_location)); if (!\is_array($reference_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $reference_cache; } /** * @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; } $reference_cache = \unserialize((string) \file_get_contents($reference_cache_location)); if (!\is_array($reference_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $reference_cache; } /** * @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; } $reference_cache = \unserialize((string) \file_get_contents($reference_cache_location)); if (!\is_array($reference_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $reference_cache; } /** * @psalm-suppress MixedAssignment */ public function getCachedMethodClassReferences() : ?array { $cache_directory = $this->config->getCacheDirectory(); if (!$cache_directory) { return null; } $cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::METHOD_CLASS_REFERENCE_CACHE_NAME; if (!\is_readable($cache_location)) { return null; } $reference_cache = \unserialize((string) \file_get_contents($cache_location)); if (!\is_array($reference_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $reference_cache; } /** * @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 = \unserialize((string) \file_get_contents($class_member_cache_location)); if (!\is_array($class_member_reference_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $class_member_reference_cache; } /** * @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 = \unserialize((string) \file_get_contents($class_member_cache_location)); if (!\is_array($class_member_reference_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $class_member_reference_cache; } /** * @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 = \unserialize((string) \file_get_contents($file_class_member_cache_location)); if (!\is_array($file_class_member_reference_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $file_class_member_reference_cache; } /** * @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 = \unserialize((string) \file_get_contents($file_class_member_cache_location)); if (!\is_array($file_class_member_reference_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $file_class_member_reference_cache; } /** * @psalm-suppress MixedAssignment */ public function getCachedMixedMemberNameReferences() : ?array { $cache_directory = $this->config->getCacheDirectory(); if (!$cache_directory) { return null; } $cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::UNKNOWN_MEMBER_CACHE_NAME; if (!\is_readable($cache_location)) { return null; } $cache = \unserialize((string) \file_get_contents($cache_location)); if (!\is_array($cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $cache; } /** * @psalm-suppress MixedAssignment */ public function getCachedMethodParamUses() : ?array { $cache_directory = $this->config->getCacheDirectory(); if (!$cache_directory) { return null; } $cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::METHOD_PARAM_USE_CACHE_NAME; if (!\is_readable($cache_location)) { return null; } $cache = \unserialize((string) \file_get_contents($cache_location)); if (!\is_array($cache)) { throw new \UnexpectedValueException('The method param use cache must be an array'); } return $cache; } /** * @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; } $issues_cache = \unserialize((string) \file_get_contents($issues_cache_location)); if (!\is_array($issues_cache)) { throw new \UnexpectedValueException('The reference cache must be an array'); } return $issues_cache; } 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; \file_put_contents($reference_cache_location, \serialize($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; \file_put_contents($reference_cache_location, \serialize($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; \file_put_contents($reference_cache_location, \serialize($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; \file_put_contents($reference_cache_location, \serialize($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; \file_put_contents($member_cache_location, \serialize($member_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; \file_put_contents($member_cache_location, \serialize($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; \file_put_contents($member_cache_location, \serialize($member_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; \file_put_contents($member_cache_location, \serialize($member_references)); } public function setCachedMixedMemberNameReferences(array $references) : void { $cache_directory = $this->config->getCacheDirectory(); if (!$cache_directory) { return; } $cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::UNKNOWN_MEMBER_CACHE_NAME; \file_put_contents($cache_location, \serialize($references)); } public function setCachedMethodParamUses(array $uses) : void { $cache_directory = $this->config->getCacheDirectory(); if (!$cache_directory) { return; } $cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::METHOD_PARAM_USE_CACHE_NAME; \file_put_contents($cache_location, \serialize($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; \file_put_contents($issues_cache_location, \serialize($issues)); } /** * @return array>|false */ public function getAnalyzedMethodCache() { $cache_directory = $this->config->getCacheDirectory(); $analyzed_methods_cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::ANALYZED_METHODS_CACHE_NAME; if ($cache_directory && \file_exists($analyzed_methods_cache_location)) { /** @var array> */ return \unserialize(\file_get_contents($analyzed_methods_cache_location)); } return \false; } /** * @param array> $analyzed_methods */ public function setAnalyzedMethodCache(array $analyzed_methods) : void { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if ($cache_directory) { $analyzed_methods_cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::ANALYZED_METHODS_CACHE_NAME; \file_put_contents($analyzed_methods_cache_location, \serialize($analyzed_methods)); } } /** * @return array|false */ public function getFileMapCache() { $cache_directory = $this->config->getCacheDirectory(); $file_maps_cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::FILE_MAPS_CACHE_NAME; if ($cache_directory && \file_exists($file_maps_cache_location)) { /** * @var array */ $file_maps_cache = \unserialize(\file_get_contents($file_maps_cache_location)); return $file_maps_cache; } return \false; } /** * @param array $file_maps */ public function setFileMapCache(array $file_maps) : void { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if ($cache_directory) { $file_maps_cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::FILE_MAPS_CACHE_NAME; \file_put_contents($file_maps_cache_location, \serialize($file_maps)); } } /** * @return array|false */ public function getTypeCoverage() { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); $type_coverage_cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::TYPE_COVERAGE_CACHE_NAME; if ($cache_directory && \file_exists($type_coverage_cache_location)) { /** @var array */ $type_coverage_cache = \unserialize(\file_get_contents($type_coverage_cache_location)); return $type_coverage_cache; } return \false; } /** * @param array $mixed_counts */ public function setTypeCoverage(array $mixed_counts) : void { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if ($cache_directory) { $type_coverage_cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::TYPE_COVERAGE_CACHE_NAME; \file_put_contents($type_coverage_cache_location, \serialize($mixed_counts)); } } /** * @return string|false */ public function getConfigHashCache() { $cache_directory = $this->config->getCacheDirectory(); $config_hash_cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::CONFIG_HASH_CACHE_NAME; if ($cache_directory && \file_exists($config_hash_cache_location)) { /** @var string */ $file_maps_cache = \file_get_contents($config_hash_cache_location); return $file_maps_cache; } return \false; } public function setConfigHashCache(string $hash) : void { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if ($cache_directory) { if (!\file_exists($cache_directory)) { \mkdir($cache_directory, 0777, \true); } $config_hash_cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::CONFIG_HASH_CACHE_NAME; \file_put_contents($config_hash_cache_location, $hash); } } } , * Context, * CodeLocation, * ?array=, * ?string=, * ?lowercase-string= * ) : ?Type\Union> * > */ private static $handlers = []; public function __construct() { self::$handlers = []; $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\DomNodeAppendChild::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\SimpleXmlElementAsXml::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\PdoStatementReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ClosureFromCallableReturnTypeProvider::class); } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'getMethodReturnType']); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); } } /** * @param \Closure( * StatementsSource, * string, * lowercase-string, * array, * Context, * CodeLocation, * ?array=, * ?string=, * ?lowercase-string= * ) : ?Type\Union $c * */ public function registerClosure(string $fq_classlike_name, \Closure $c) : void { self::$handlers[\strtolower($fq_classlike_name)][] = $c; } public function has(string $fq_classlike_name) : bool { return isset(self::$handlers[\strtolower($fq_classlike_name)]); } /** * @param array $call_args * @param ?array $template_type_parameters * */ public function getReturnType(\Psalm\StatementsSource $statements_source, string $fq_classlike_name, string $method_name, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location, ?array $template_type_parameters = null, ?string $called_fq_classlike_name = null, ?string $called_method_name = null) : ?\Psalm\Type\Union { foreach (self::$handlers[\strtolower($fq_classlike_name)] as $class_handler) { $result = $class_handler($statements_source, $fq_classlike_name, \strtolower($method_name), $call_args, $context, $code_location, $template_type_parameters, $called_fq_classlike_name, $called_method_name ? \strtolower($called_method_name) : null); if ($result) { return $result; } } return null; } } composer_lock_location = $composer_lock_location; } public function canDiffFiles() : bool { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); return $cache_directory && \file_exists($cache_directory . \DIRECTORY_SEPARATOR . self::GOOD_RUN_NAME); } public function processSuccessfulRun(float $start_time) : void { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$cache_directory) { return; } $run_cache_location = $cache_directory . \DIRECTORY_SEPARATOR . self::GOOD_RUN_NAME; \touch($run_cache_location, (int) $start_time); } public function getLastRun() : int { if ($this->last_run === null) { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (\file_exists($cache_directory . \DIRECTORY_SEPARATOR . self::GOOD_RUN_NAME)) { $this->last_run = \filemtime($cache_directory . \DIRECTORY_SEPARATOR . self::GOOD_RUN_NAME); } else { $this->last_run = 0; } } return $this->last_run; } public function hasLockfileChanged() : bool { if (!\file_exists($this->composer_lock_location)) { return \true; } $lockfile_contents = \file_get_contents($this->composer_lock_location); if (!$lockfile_contents) { return \true; } $sha1 = \sha1($lockfile_contents); $changed = $sha1 !== $this->getComposerLockHash(); $this->composer_lock_hash = $sha1; return $changed; } public function updateComposerLockHash() : void { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); if (!$cache_directory || !$this->composer_lock_hash) { return; } if (!\file_exists($cache_directory)) { \mkdir($cache_directory, 0777, \true); } $lock_hash_location = $cache_directory . \DIRECTORY_SEPARATOR . self::COMPOSER_LOCK_HASH; \file_put_contents($lock_hash_location, $this->composer_lock_hash); } protected function getComposerLockHash() : string { if ($this->composer_lock_hash === null) { $cache_directory = \Psalm\Config::getInstance()->getCacheDirectory(); $lock_hash_location = $cache_directory . \DIRECTORY_SEPARATOR . self::COMPOSER_LOCK_HASH; if (\file_exists($lock_hash_location)) { $this->composer_lock_hash = \file_get_contents($lock_hash_location) ?: ''; } else { $this->composer_lock_hash = ''; } } return $this->composer_lock_hash; } } config = $config; $storage_dir = \dirname(__DIR__, 2) . \DIRECTORY_SEPARATOR . 'Storage' . \DIRECTORY_SEPARATOR; $dependent_files = [$storage_dir . 'FileStorage.php', $storage_dir . 'FunctionLikeStorage.php', $storage_dir . 'ClassLikeStorage.php', $storage_dir . 'MethodStorage.php', $storage_dir . 'FunctionLikeParameter.php']; if ($config->after_visit_classlikes) { $dependent_files = \array_merge($dependent_files, $config->plugin_paths); } foreach ($dependent_files as $dependent_file_path) { if (!\file_exists($dependent_file_path)) { throw new \UnexpectedValueException($dependent_file_path . ' must exist'); } $this->modified_timestamps .= ' ' . \filemtime($dependent_file_path); } $this->modified_timestamps .= $this->config->hash; } public function writeToCache(\Psalm\Storage\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)); } else { \file_put_contents($cache_location, \serialize($storage)); } } public function getLatestFromCache(string $file_path, string $file_contents) : ?\Psalm\Storage\FileStorage { $file_path = \strtolower($file_path); $cached_value = $this->loadFromCache($file_path); if (!$cached_value) { return null; } $cache_hash = $this->getCacheHash($file_path, $file_contents); /** @psalm-suppress TypeDoesNotContainType */ if (@\get_class($cached_value) === '__PHP_Incomplete_Class' || $cache_hash !== $cached_value->hash) { $this->removeCacheForFile($file_path); return null; } return $cached_value; } public function removeCacheForFile(string $file_path) : void { $cache_path = $this->getCacheLocationForPath($file_path); if (\file_exists($cache_path)) { \unlink($cache_path); } } private function getCacheHash(string $file_path, string $file_contents) : string { return \sha1(\strtolower($file_path) . ' ' . $file_contents . $this->modified_timestamps); } /** * @psalm-suppress MixedAssignment */ private function loadFromCache(string $file_path) : ?\Psalm\Storage\FileStorage { $cache_location = $this->getCacheLocationForPath($file_path); if (\file_exists($cache_location)) { if ($this->config->use_igbinary) { $storage = \igbinary_unserialize((string) \file_get_contents($cache_location)); if ($storage instanceof \Psalm\Storage\FileStorage) { return $storage; } return null; } $storage = \unserialize((string) \file_get_contents($cache_location)); if ($storage instanceof \Psalm\Storage\FileStorage) { return $storage; } return null; } return null; } private function getCacheLocationForPath(string $file_path, bool $create_directory = \false) : string { $root_cache_directory = $this->config->getCacheDirectory(); if (!$root_cache_directory) { throw new \UnexpectedValueException('No cache directory defined'); } $parser_cache_directory = $root_cache_directory . \DIRECTORY_SEPARATOR . self::FILE_STORAGE_CACHE_DIRECTORY; if ($create_directory && !\is_dir($parser_cache_directory)) { \mkdir($parser_cache_directory, 0777, \true); } return $parser_cache_directory . \DIRECTORY_SEPARATOR . \sha1($file_path) . ($this->config->use_igbinary ? '-igbinary' : ''); } } , * ?Context=, * ?CodeLocation= * ) : ?array> * > */ private static $handlers = []; public function __construct() { self::$handlers = []; } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'getFunctionParams']); foreach ($class::getFunctionIds() as $function_id) { $this->registerClosure($function_id, $callable); } } /** * @param \Closure( * StatementsSource, * string, * array, * ?Context=, * ?CodeLocation= * ) : ?array $c * */ public function registerClosure(string $fq_classlike_name, \Closure $c) : void { self::$handlers[\strtolower($fq_classlike_name)][] = $c; } public function has(string $fq_classlike_name) : bool { return isset(self::$handlers[\strtolower($fq_classlike_name)]); } /** * @param array $call_args * * @return ?array */ public function getFunctionParams(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, ?\Psalm\Context $context = null, ?\Psalm\CodeLocation $code_location = null) : ?array { foreach (self::$handlers[\strtolower($function_id)] as $class_handler) { $result = $class_handler($statements_source, $function_id, $call_args, $context, $code_location); if ($result) { return $result; } } return null; } } * > */ private static $handlers = []; public function __construct() { self::$handlers = []; } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'isMethodVisible']); foreach ($class::getClassLikeNames() as $fq_classlike_name) { $this->registerClosure($fq_classlike_name, $callable); } } /** * /** * @param \Closure( * StatementsSource, * string, * string, * Context, * ?CodeLocation * ) : ?bool $c * */ public function registerClosure(string $fq_classlike_name, \Closure $c) : void { self::$handlers[\strtolower($fq_classlike_name)][] = $c; } public function has(string $fq_classlike_name) : bool { return isset(self::$handlers[\strtolower($fq_classlike_name)]); } /** * @param array $call_args * */ public function isMethodVisible(\Psalm\StatementsSource $source, string $fq_classlike_name, string $method_name, \Psalm\Context $context, ?\Psalm\CodeLocation $code_location = null) : ?bool { foreach (self::$handlers[\strtolower($fq_classlike_name)] as $method_handler) { $method_visible = $method_handler($source, $fq_classlike_name, $method_name, $context, $code_location); if ($method_visible !== null) { return $method_visible; } } return null; } } */ protected $temp_files = []; /** * @var array */ protected $open_files = []; public function getContents(string $file_path, bool $go_to_source = \false) : string { if (!$go_to_source && isset($this->temp_files[\strtolower($file_path)])) { return $this->temp_files[\strtolower($file_path)]; } if (isset($this->open_files[\strtolower($file_path)])) { return $this->open_files[\strtolower($file_path)]; } if (!\file_exists($file_path)) { throw new \UnexpectedValueException('File ' . $file_path . ' should exist to get contents'); } if (\is_dir($file_path)) { throw new \UnexpectedValueException('File ' . $file_path . ' is a directory'); } return (string) \file_get_contents($file_path); } public function setContents(string $file_path, string $file_contents) : void { if (isset($this->open_files[\strtolower($file_path)])) { $this->open_files[\strtolower($file_path)] = $file_contents; } if (isset($this->temp_files[\strtolower($file_path)])) { $this->temp_files[\strtolower($file_path)] = $file_contents; } \file_put_contents($file_path, $file_contents); } public function setOpenContents(string $file_path, string $file_contents) : void { if (isset($this->open_files[\strtolower($file_path)])) { $this->open_files[\strtolower($file_path)] = $file_contents; } } public function getModifiedTime(string $file_path) : int { if (!\file_exists($file_path)) { throw new \UnexpectedValueException('File should exist to get modified time'); } return (int) \filemtime($file_path); } public function addTemporaryFileChanges(string $file_path, string $new_content) : void { $this->temp_files[\strtolower($file_path)] = $new_content; } public function removeTemporaryFileChanges(string $file_path) : void { unset($this->temp_files[\strtolower($file_path)]); } public function openFile(string $file_path) : void { $this->open_files[\strtolower($file_path)] = $this->getContents($file_path, \true); } public function isOpen(string $file_path) : bool { return isset($this->temp_files[\strtolower($file_path)]) || isset($this->open_files[\strtolower($file_path)]); } public function closeFile(string $file_path) : void { unset($this->temp_files[\strtolower($file_path)], $this->open_files[\strtolower($file_path)]); } public function fileExists(string $file_path) : bool { return \file_exists($file_path); } /** * @param array $file_extensions * * @return list */ public function getFilesInDir(string $dir_path, array $file_extensions) : array { $file_paths = []; /** @var \RecursiveDirectoryIterator */ $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir_path)); $iterator->rewind(); while ($iterator->valid()) { if (!$iterator->isDot()) { $extension = $iterator->getExtension(); if (\in_array($extension, $file_extensions, \true)) { $file_paths[] = (string) $iterator->getRealPath(); } } $iterator->next(); } return $file_paths; } } , * Context, * CodeLocation * ) : ?Type\Union> * > */ private static $handlers = []; public function __construct() { self::$handlers = []; $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayChunkReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayColumnReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayFilterReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayMapReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayMergeReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayPadReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayPointerAdjustmentReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayPopReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayRandReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayReduceReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArraySliceReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayReverseReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayUniqueReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayValuesReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ArrayFillReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\FilterVarReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\IteratorToArrayReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ParseUrlReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\StrReplaceReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\VersionCompareReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\MktimeReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\ExplodeReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\GetObjectVarsReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\GetClassMethodsReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\FirstArgStringReturnTypeProvider::class); $this->registerClass(\Psalm\Internal\Provider\ReturnTypeProvider\HexdecReturnTypeProvider::class); } /** * @param class-string $class * */ public function registerClass(string $class) : void { $callable = \Closure::fromCallable([$class, 'getFunctionReturnType']); foreach ($class::getFunctionIds() as $function_id) { $this->registerClosure($function_id, $callable); } } /** * /** * @param \Closure( * StatementsSource, * non-empty-string, * array, * Context, * CodeLocation * ) : ?Type\Union $c * */ public function registerClosure(string $function_id, \Closure $c) : void { self::$handlers[$function_id][] = $c; } public function has(string $function_id) : bool { return isset(self::$handlers[\strtolower($function_id)]); } /** * @param non-empty-string $function_id * @param array $call_args * */ public function getReturnType(\Psalm\StatementsSource $statements_source, string $function_id, array $call_args, \Psalm\Context $context, \Psalm\CodeLocation $code_location) : ?\Psalm\Type\Union { foreach (self::$handlers[\strtolower($function_id)] as $function_handler) { $return_type = $function_handler($statements_source, $function_id, $call_args, $context, $code_location); if ($return_type) { return $return_type; } } return null; } } $a * @param array $b * * @return array{0:non-empty-list>, 1: int, 2: int, 3: array} */ protected static function calculateTrace(\Closure $is_equal, array $a, array $b, string $a_code, string $b_code) : array { $n = \count($a); $m = \count($b); $max = $n + $m; $v = [1 => 0]; $bc = []; $trace = []; for ($d = 0; $d <= $max; ++$d) { $trace[] = $v; for ($k = -$d; $k <= $d; $k += 2) { if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) { $x = $v[$k + 1]; } else { $x = $v[$k - 1] + 1; } $y = $x - $k; $body_change = \false; while ($x < $n && $y < $m && $is_equal($a[$x], $b[$y], $a_code, $b_code, $body_change)) { /** @var bool */ $bc[$x] = $body_change; ++$x; ++$y; $body_change = \false; } $v[$k] = $x; if ($x >= $n && $y >= $m) { return [$trace, $x, $y, $bc]; } } } throw new \Exception('Should not happen'); } /** * @param array> $trace * @param array $a * @param array $b * @param array $bc * * @return list * * @psalm-pure */ protected static function extractDiff(array $trace, int $x, int $y, array $a, array $b, array $bc) : array { $result = []; for ($d = \count($trace) - 1; $d >= 0; --$d) { $v = $trace[$d]; $k = $x - $y; if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) { $prevK = $k + 1; } else { $prevK = $k - 1; } $prevX = $v[$prevK]; $prevY = $prevX - $prevK; while ($x > $prevX && $y > $prevY) { $result[] = new \Psalm\Internal\Diff\DiffElem($bc[$x - 1] ? \Psalm\Internal\Diff\DiffElem::TYPE_KEEP_SIGNATURE : \Psalm\Internal\Diff\DiffElem::TYPE_KEEP, $a[$x - 1], $b[$y - 1]); --$x; --$y; } if ($d === 0) { break; } while ($x > $prevX) { $result[] = new \Psalm\Internal\Diff\DiffElem(\Psalm\Internal\Diff\DiffElem::TYPE_REMOVE, $a[$x - 1], null); --$x; } while ($y > $prevY) { $result[] = new \Psalm\Internal\Diff\DiffElem(\Psalm\Internal\Diff\DiffElem::TYPE_ADD, null, $b[$y - 1]); --$y; } } return \array_reverse($result); } } $a * @param array $b * * @return array{ * 0: list, * 1: list, * 2: list, * 3: list * } */ public static function diff(string $name, array $a, array $b, string $a_code, string $b_code) : array { [$trace, $x, $y, $bc] = self::calculateTrace( /** * @param string $a_code * @param string $b_code * * @return bool */ function (\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt $a, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt $b, $a_code, $b_code, bool &$body_change = \false) : bool { if (\get_class($a) !== \get_class($b)) { return \false; } if ($a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ || $a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ || $a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_ && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_) { // @todo add check for comments comparison return (string) $a->name === (string) $b->name; } if ($a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ || $a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { $a_start = (int) $a->getAttribute('startFilePos'); $a_end = (int) $a->getAttribute('endFilePos'); $b_start = (int) $b->getAttribute('startFilePos'); $b_end = (int) $b->getAttribute('endFilePos'); $a_size = $a_end - $a_start; $b_size = $b_end - $b_start; if (\substr($a_code, $a_start, $a_size) === \substr($b_code, $b_start, $b_size)) { return \true; } } return \false; }, $a, $b, $a_code, $b_code ); $diff = self::extractDiff($trace, $x, $y, $a, $b, $bc); $keep = []; $keep_signature = []; $add_or_delete = []; $diff_map = []; foreach ($diff as $diff_elem) { if ($diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_KEEP) { if ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ && $diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ || $diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ && $diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ || $diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_ && $diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_) { $class_keep = \Psalm\Internal\Diff\ClassStatementsDiffer::diff(($name ? $name . '\\' : '') . $diff_elem->old->name, $diff_elem->old->stmts, $diff_elem->new->stmts, $a_code, $b_code); $keep = \array_merge($keep, $class_keep[0]); $keep_signature = \array_merge($keep_signature, $class_keep[1]); $add_or_delete = \array_merge($add_or_delete, $class_keep[2]); $diff_map = \array_merge($diff_map, $class_keep[3]); } } elseif ($diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_REMOVE) { if ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ || $diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { foreach ($diff_elem->old->uses as $use) { if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { $name_parts = $use->name->parts; $add_or_delete[] = 'use:' . \end($name_parts); } } } } elseif ($diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_ADD) { if ($diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ || $diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { foreach ($diff_elem->new->uses as $use) { if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { $name_parts = $use->name->parts; $add_or_delete[] = 'use:' . \end($name_parts); } } } } } return [$keep, $keep_signature, $add_or_delete, $diff_map]; } } $a * @param array $b * * @return array{ * 0: list, * 1: list, * 2: list, * 3: array * } */ public static function diff(string $name, array $a, array $b, string $a_code, string $b_code) : array { $diff_map = []; [$trace, $x, $y, $bc] = self::calculateTrace( /** * @param string $a_code * @param string $b_code * @param bool $body_change * * @return bool */ function (\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt $a, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt $b, $a_code, $b_code, &$body_change = \false) use(&$diff_map) : bool { if (\get_class($a) !== \get_class($b)) { return \false; } $a_start = (int) $a->getAttribute('startFilePos'); $a_end = (int) $a->getAttribute('endFilePos'); $b_start = (int) $b->getAttribute('startFilePos'); $b_end = (int) $b->getAttribute('endFilePos'); $a_comments_end = $a_start; $b_comments_end = $b_start; /** @var list */ $a_comments = $a->getComments(); /** @var list */ $b_comments = $b->getComments(); $signature_change = \false; $body_change = \false; if ($a_comments) { if (!$b_comments) { $signature_change = \true; } $a_start = $a_comments[0]->getStartFilePos(); } if ($b_comments) { if (!$a_comments) { $signature_change = \true; } $b_start = $b_comments[0]->getStartFilePos(); } $a_size = $a_end - $a_start; $b_size = $b_end - $b_start; if ($a_size === $b_size && \substr($a_code, $a_start, $a_size) === \substr($b_code, $b_start, $b_size)) { $start_diff = $b_start - $a_start; $line_diff = $b->getLine() - $a->getLine(); /** @psalm-suppress MixedArrayAssignment */ $diff_map[] = [$a_start, $a_end, $start_diff, $line_diff]; return \true; } if (!$signature_change && \substr($a_code, $a_start, $a_comments_end - $a_start) !== \substr($b_code, $b_start, $b_comments_end - $b_start)) { $signature_change = \true; } if ($a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { if ((string) $a->name !== (string) $b->name) { return \false; } if ($a->stmts) { $first_stmt = $a->stmts[0]; $a_stmts_start = (int) $first_stmt->getAttribute('startFilePos'); if ($a_stmt_comments = $first_stmt->getComments()) { $a_stmts_start = $a_stmt_comments[0]->getStartFilePos(); } } else { $a_stmts_start = $a_end; } if ($b->stmts) { $first_stmt = $b->stmts[0]; $b_stmts_start = (int) $first_stmt->getAttribute('startFilePos'); if ($b_stmt_comments = $first_stmt->getComments()) { $b_stmts_start = $b_stmt_comments[0]->getStartFilePos(); } } else { $b_stmts_start = $b_end; } $a_body_size = $a_end - $a_stmts_start; $b_body_size = $b_end - $b_stmts_start; $body_change = $a_body_size !== $b_body_size || \substr($a_code, $a_stmts_start, $a_end - $a_stmts_start) !== \substr($b_code, $b_stmts_start, $b_end - $b_stmts_start); if (!$signature_change) { $a_signature = \substr($a_code, $a_start, $a_stmts_start - $a_start); $b_signature = \substr($b_code, $b_start, $b_stmts_start - $b_start); if ($a_signature !== $b_signature) { $a_signature = \trim($a_signature); $b_signature = \trim($b_signature); if (\strpos($a_signature, $b_signature) === \false && \strpos($b_signature, $a_signature) === \false) { $signature_change = \true; } } } } elseif ($a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { if (\count($a->props) !== 1 || \count($b->props) !== 1) { return \false; } if ((string) $a->props[0]->name !== (string) $b->props[0]->name || $a->flags !== $b->flags) { 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 { $signature_change = \true; } if (!$signature_change && !$body_change) { /** @psalm-suppress MixedArrayAssignment */ $diff_map[] = [$a_start, $a_end, $b_start - $a_start, $b->getLine() - $a->getLine()]; } return !$signature_change; }, $a, $b, $a_code, $b_code ); $diff = self::extractDiff($trace, $x, $y, $a, $b, $bc); $keep = []; $keep_signature = []; $add_or_delete = []; foreach ($diff as $diff_elem) { if ($diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_KEEP) { if ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $keep[] = \strtolower($name) . '::' . \strtolower((string) $diff_elem->old->name); } elseif ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { foreach ($diff_elem->old->props as $prop) { $keep[] = \strtolower($name) . '::$' . $prop->name; } } elseif ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst) { foreach ($diff_elem->old->consts as $const) { $keep[] = \strtolower($name) . '::' . $const->name; } } elseif ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { foreach ($diff_elem->old->traits as $trait) { $keep[] = \strtolower($name . '&' . (string) $trait->getAttribute('resolvedName')); } } } elseif ($diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_KEEP_SIGNATURE) { if ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $keep_signature[] = \strtolower($name) . '::' . \strtolower((string) $diff_elem->old->name); } elseif ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { foreach ($diff_elem->old->props as $prop) { $keep_signature[] = \strtolower($name) . '::$' . $prop->name; } } } elseif ($diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_REMOVE || $diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_ADD) { /** @psalm-suppress MixedAssignment */ $affected_elem = $diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_REMOVE ? $diff_elem->old : $diff_elem->new; if ($affected_elem instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $add_or_delete[] = \strtolower($name) . '::' . \strtolower((string) $affected_elem->name); } elseif ($affected_elem instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { foreach ($affected_elem->props as $prop) { $add_or_delete[] = \strtolower($name) . '::$' . $prop->name; } } elseif ($affected_elem instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst) { foreach ($affected_elem->consts as $const) { $add_or_delete[] = \strtolower($name) . '::' . $const->name; } } elseif ($affected_elem instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { foreach ($affected_elem->traits as $trait) { $add_or_delete[] = \strtolower($name . '&' . (string) $trait->getAttribute('resolvedName')); } } } } /** @var array $diff_map */ return [$keep, $keep_signature, $add_or_delete, $diff_map]; } } $a * @param list $b * * @return array{0:non-empty-list>, 1: int, 2: int} * * @psalm-pure */ private static function calculateTrace(array $a, array $b) : array { $n = \count($a); $m = \count($b); $max = $n + $m; $v = [1 => 0]; $trace = []; for ($d = 0; $d <= $max; ++$d) { $trace[] = $v; for ($k = -$d; $k <= $d; $k += 2) { if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) { $x = $v[$k + 1]; } else { $x = $v[$k - 1] + 1; } $y = $x - $k; while ($x < $n && $y < $m && $a[$x] === $b[$y]) { ++$x; ++$y; } $v[$k] = $x; if ($x >= $n && $y >= $m) { return [$trace, $x, $y]; } } } throw new \Exception('Should not happen'); } /** * @param list> $trace * @param list $a * @param list $b * * @return list * * @psalm-pure */ private static function extractDiff(array $trace, int $x, int $y, array $a, array $b) : array { $result = []; for ($d = \count($trace) - 1; $d >= 0; --$d) { $v = $trace[$d]; $k = $x - $y; if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) { $prevK = $k + 1; } else { $prevK = $k - 1; } $prevX = $v[$prevK]; $prevY = $prevX - $prevK; while ($x > $prevX && $y > $prevY) { $result[] = new \Psalm\Internal\Diff\DiffElem(\Psalm\Internal\Diff\DiffElem::TYPE_KEEP, $a[$x - 1], $b[$y - 1]); --$x; --$y; } if ($d === 0) { break; } while ($x > $prevX) { $result[] = new \Psalm\Internal\Diff\DiffElem(\Psalm\Internal\Diff\DiffElem::TYPE_REMOVE, $a[$x - 1], null); --$x; } while ($y > $prevY) { $result[] = new \Psalm\Internal\Diff\DiffElem(\Psalm\Internal\Diff\DiffElem::TYPE_ADD, null, $b[$y - 1]); --$y; } } return \array_reverse($result); } /** * @return array * * @psalm-pure */ public static function getDiff(string $a_code, string $b_code) : array { $a = \explode("\n", $a_code); $b = \explode("\n", $b_code); [$trace, $x, $y] = self::calculateTrace($a, $b); $diff = self::coalesceReplacements(self::extractDiff($trace, $x, $y, $a, $b)); $a_offset = 0; $b_offset = 0; $last_diff_type = null; /** @var array{0:int, 1:int, 2:int, 3:int, 4:int, 5:string}|null */ $last_change = null; $changes = []; $i = 0; $line_diff = 0; foreach ($diff as $diff_elem) { $diff_type = $diff_elem->type; if ($diff_type !== $last_diff_type) { $last_change = null; } if ($diff_type === \Psalm\Internal\Diff\DiffElem::TYPE_REMOVE) { /** @var string $diff_elem->old */ $diff_text = $diff_elem->old . "\n"; $text_length = \strlen($diff_text); --$line_diff; if ($last_change === null) { ++$i; $last_change = [$a_offset, $a_offset + $text_length, $b_offset, $b_offset, $line_diff, '']; $changes[$i - 1] = $last_change; } else { $last_change[1] += $text_length; $last_change[4] = $line_diff; $changes[$i - 1] = $last_change; } $a_offset += $text_length; } elseif ($diff_type === \Psalm\Internal\Diff\DiffElem::TYPE_ADD) { /** @var string $diff_elem->new */ $diff_text = $diff_elem->new . "\n"; $text_length = \strlen($diff_text); ++$line_diff; if ($last_change === null) { ++$i; $last_change = [$a_offset, $a_offset, $b_offset, $b_offset + $text_length, $line_diff, $diff_text]; $changes[$i - 1] = $last_change; } else { $last_change[3] += $text_length; $last_change[4] = $line_diff; $last_change[5] .= $diff_text; $changes[$i - 1] = $last_change; } $b_offset += $text_length; } elseif ($diff_type === \Psalm\Internal\Diff\DiffElem::TYPE_REPLACE) { /** @var string $diff_elem->old */ $old_diff_text = $diff_elem->old . "\n"; /** @var string $diff_elem->new */ $new_diff_text = $diff_elem->new . "\n"; $old_text_length = \strlen($old_diff_text); $new_text_length = \strlen($new_diff_text); $max_same_count = \min($old_text_length, $new_text_length); for ($j = 0; $j < $max_same_count; ++$j) { if ($old_diff_text[$j] !== $new_diff_text[$j]) { break; } ++$a_offset; ++$b_offset; --$old_text_length; --$new_text_length; } $new_diff_text = \substr($new_diff_text, $j); if ($last_change === null || $j) { ++$i; $last_change = [$a_offset, $a_offset + $old_text_length, $b_offset, $b_offset + $new_text_length, $line_diff, $new_diff_text]; $changes[$i - 1] = $last_change; } else { $last_change[1] += $old_text_length; $last_change[3] += $new_text_length; $last_change[5] .= $new_diff_text; $changes[$i - 1] = $last_change; } $a_offset += $old_text_length; $b_offset += $new_text_length; } else { /** @psalm-suppress MixedArgument */ $same_text_length = \strlen($diff_elem->new) + 1; $a_offset += $same_text_length; $b_offset += $same_text_length; } $last_diff_type = $diff_elem->type; } return $changes; } /** * Coalesce equal-length sequences of remove+add into a replace operation. * * @param DiffElem[] $diff * * @return list * * @psalm-pure */ private static function coalesceReplacements(array $diff) : array { $newDiff = []; $c = \count($diff); for ($i = 0; $i < $c; ++$i) { $diffType = $diff[$i]->type; if ($diffType !== \Psalm\Internal\Diff\DiffElem::TYPE_REMOVE) { $newDiff[] = $diff[$i]; continue; } $j = $i; while ($j < $c && $diff[$j]->type === \Psalm\Internal\Diff\DiffElem::TYPE_REMOVE) { ++$j; } $k = $j; while ($k < $c && $diff[$k]->type === \Psalm\Internal\Diff\DiffElem::TYPE_ADD) { ++$k; } if ($j - $i === $k - $j) { $len = $j - $i; for ($n = 0; $n < $len; ++$n) { $newDiff[] = new \Psalm\Internal\Diff\DiffElem(\Psalm\Internal\Diff\DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new); } } else { for (; $i < $k; ++$i) { $newDiff[] = $diff[$i]; } } $i = $k - 1; } return $newDiff; } } type = $type; $this->old = $old; $this->new = $new; } } $a * @param list $b * * @return array{ * 0: list, * 1: list, * 2: list, * 3: list * } */ public static function diff(array $a, array $b, string $a_code, string $b_code) : array { [$trace, $x, $y, $bc] = self::calculateTrace( /** * @param string $a_code * @param string $b_code * * @return bool */ function (\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt $a, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt $b, $a_code, $b_code, bool &$body_change = \false) : bool { if (\get_class($a) !== \get_class($b)) { return \false; } if ($a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_ && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_ || $a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ || $a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ || $a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_ && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_) { return (string) $a->name === (string) $b->name; } if ($a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ || $a instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse && $b instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { $a_start = (int) $a->getAttribute('startFilePos'); $a_end = (int) $a->getAttribute('endFilePos'); $b_start = (int) $b->getAttribute('startFilePos'); $b_end = (int) $b->getAttribute('endFilePos'); $a_size = $a_end - $a_start; $b_size = $b_end - $b_start; if (\substr($a_code, $a_start, $a_size) === \substr($b_code, $b_start, $b_size)) { return \true; } } return \false; }, $a, $b, $a_code, $b_code ); $diff = self::extractDiff($trace, $x, $y, $a, $b, $bc); $keep = []; $keep_signature = []; $add_or_delete = []; $diff_map = []; foreach ($diff as $diff_elem) { if ($diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_KEEP) { if ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_ && $diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { $namespace_keep = \Psalm\Internal\Diff\NamespaceStatementsDiffer::diff((string) $diff_elem->old->name, $diff_elem->old->stmts, $diff_elem->new->stmts, $a_code, $b_code); $keep = \array_merge($keep, $namespace_keep[0]); $keep_signature = \array_merge($keep_signature, $namespace_keep[1]); $add_or_delete = \array_merge($add_or_delete, $namespace_keep[2]); $diff_map = \array_merge($diff_map, $namespace_keep[3]); } elseif ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ && $diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ || $diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ && $diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_ || $diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_ && $diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_) { $class_keep = \Psalm\Internal\Diff\ClassStatementsDiffer::diff((string) $diff_elem->old->name, $diff_elem->old->stmts, $diff_elem->new->stmts, $a_code, $b_code); $keep = \array_merge($keep, $class_keep[0]); $keep_signature = \array_merge($keep_signature, $class_keep[1]); $add_or_delete = \array_merge($add_or_delete, $class_keep[2]); $diff_map = \array_merge($diff_map, $class_keep[3]); } } elseif ($diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_REMOVE) { if ($diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ || $diff_elem->old instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { foreach ($diff_elem->old->uses as $use) { if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { $name_parts = $use->name->parts; $add_or_delete[] = 'use:' . \end($name_parts); } } } } elseif ($diff_elem->type === \Psalm\Internal\Diff\DiffElem::TYPE_ADD) { if ($diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ || $diff_elem->new instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { foreach ($diff_elem->new->uses as $use) { if ($use->alias) { $add_or_delete[] = 'use:' . (string) $use->alias; } else { $name_parts = $use->name->parts; $add_or_delete[] = 'use:' . \end($name_parts); } } } } } return [$keep, $keep_signature, $add_or_delete, $diff_map]; } } $unescaped_taints * @param ?array $escaped_taints */ public function __construct(string $type, ?array $unescaped_taints, ?array $escaped_taints) { $this->type = $type; $this->unescaped_taints = $unescaped_taints; $this->escaped_taints = $escaped_taints; } } */ public $taints; /** @var ?self */ public $previous; /** @var list */ public $path_types = []; /** * @var array> */ public $specialized_calls = []; /** * @param array $taints */ public function __construct(string $id, string $label, ?\Psalm\CodeLocation $code_location, ?string $specialization_key = null, array $taints = []) { $this->id = $id; if ($specialization_key) { $this->unspecialized_id = $id; $this->id .= '-' . $specialization_key; } $this->label = $label; $this->code_location = $code_location; $this->specialization_key = $specialization_key; $this->taints = $taints; } /** * @return static */ public static final function getForMethodArgument(string $method_id, string $cased_method_id, int $argument_offset, ?\Psalm\CodeLocation $arg_location, ?\Psalm\CodeLocation $code_location = null) : self { $arg_id = \strtolower($method_id) . '#' . ($argument_offset + 1); $label = $cased_method_id . '#' . ($argument_offset + 1); $specialization_key = null; if ($code_location) { $specialization_key = \strtolower($code_location->file_name) . ':' . $code_location->raw_file_start; } return new static($arg_id, $label, $arg_location, $specialization_key); } /** * @return static */ public static final function getForAssignment(string $var_id, \Psalm\CodeLocation $assignment_location) : self { $id = $var_id . '-' . $assignment_location->file_name . ':' . $assignment_location->raw_file_start . '-' . $assignment_location->raw_file_end; return new static($id, $var_id, $assignment_location, null); } /** * @return static */ public static final function getForMethodReturn(string $method_id, string $cased_method_id, ?\Psalm\CodeLocation $code_location, ?\Psalm\CodeLocation $function_location = null) : self { $specialization_key = null; if ($function_location) { $specialization_key = \strtolower($function_location->file_name) . ':' . $function_location->raw_file_start; } return new static(\strtolower($method_id), $cased_method_id, $code_location, $specialization_key); } public function __toString() : string { return $this->id; } } */ public static function getReferenceMap(\Psalm\Internal\Provider\ClassLikeStorageProvider $classlike_storage_provider, array $expected_references) : array { $reference_dictionary = []; foreach ($classlike_storage_provider->getAll() as $storage) { if (!$storage->location) { continue; } $fq_classlike_name = $storage->name; if (isset($expected_references[$fq_classlike_name])) { $reference_dictionary[$fq_classlike_name] = $storage->location->file_name . ':' . $storage->location->getLineNumber() . ':' . $storage->location->getColumn(); } foreach ($storage->methods as $method_name => $method_storage) { if (!$method_storage->location) { continue; } if (isset($expected_references[$fq_classlike_name . '::' . $method_name . '()'])) { $reference_dictionary[$fq_classlike_name . '::' . $method_name . '()'] = $method_storage->location->file_name . ':' . $method_storage->location->getLineNumber() . ':' . $method_storage->location->getColumn(); } } foreach ($storage->properties as $property_name => $property_storage) { if (!$property_storage->location) { continue; } if (isset($expected_references[$fq_classlike_name . '::$' . $property_name])) { $reference_dictionary[$fq_classlike_name . '::$' . $property_name] = $property_storage->location->file_name . ':' . $property_storage->location->getLineNumber() . ':' . $property_storage->location->getColumn(); } } } return $reference_dictionary; } } value); } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedBinaryOp) { $left = self::resolve($classlikes, $c->left, $statements_analyzer, $visited_constant_ids + [$c_id => \true]); $right = self::resolve($classlikes, $c->right, $statements_analyzer, $visited_constant_ids + [$c_id => \true]); if ($left instanceof \Psalm\Type\Atomic\TMixed || $right instanceof \Psalm\Type\Atomic\TMixed) { return new \Psalm\Type\Atomic\TMixed(); } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedConcatOp) { if ($left instanceof \Psalm\Type\Atomic\TLiteralString && $right instanceof \Psalm\Type\Atomic\TLiteralString) { return new \Psalm\Type\Atomic\TLiteralString($left->value . $right->value); } return new \Psalm\Type\Atomic\TMixed(); } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedAdditionOp || $c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedSubtractionOp || $c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedDivisionOp || $c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedMultiplicationOp || $c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedBitwiseOr) { if (($left instanceof \Psalm\Type\Atomic\TLiteralFloat || $left instanceof \Psalm\Type\Atomic\TLiteralInt) && ($right instanceof \Psalm\Type\Atomic\TLiteralFloat || $right instanceof \Psalm\Type\Atomic\TLiteralInt)) { if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedAdditionOp) { return self::getLiteralTypeFromScalarValue($left->value + $right->value); } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedSubtractionOp) { return self::getLiteralTypeFromScalarValue($left->value - $right->value); } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedDivisionOp) { return self::getLiteralTypeFromScalarValue($left->value / $right->value); } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedBitwiseOr) { return self::getLiteralTypeFromScalarValue($left->value | $right->value); } return self::getLiteralTypeFromScalarValue($left->value * $right->value); } return new \Psalm\Type\Atomic\TMixed(); } return new \Psalm\Type\Atomic\TMixed(); } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedTernary) { $cond = self::resolve($classlikes, $c->cond, $statements_analyzer, $visited_constant_ids + [$c_id => \true]); $if = $c->if ? self::resolve($classlikes, $c->if, $statements_analyzer, $visited_constant_ids + [$c_id => \true]) : null; $else = self::resolve($classlikes, $c->else, $statements_analyzer, $visited_constant_ids + [$c_id => \true]); if ($cond instanceof \Psalm\Type\Atomic\TLiteralFloat || $cond instanceof \Psalm\Type\Atomic\TLiteralInt || $cond instanceof \Psalm\Type\Atomic\TLiteralString) { if ($cond->value) { return $if ? $if : $cond; } } elseif ($cond instanceof \Psalm\Type\Atomic\TFalse || $cond instanceof \Psalm\Type\Atomic\TNull) { return $else; } elseif ($cond instanceof \Psalm\Type\Atomic\TTrue) { return $if ? $if : $cond; } } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\ArrayValue) { $properties = []; if (!$c->entries) { return new \Psalm\Type\Atomic\TArray([\Psalm\Type::getEmpty(), \Psalm\Type::getEmpty()]); } $is_list = \true; foreach ($c->entries as $i => $entry) { if ($entry->key) { $key_type = self::resolve($classlikes, $entry->key, $statements_analyzer, $visited_constant_ids + [$c_id => \true]); if (!$key_type instanceof \Psalm\Type\Atomic\TLiteralInt || $key_type->value !== $i) { $is_list = \false; } } else { $key_type = new \Psalm\Type\Atomic\TLiteralInt($i); } if ($key_type instanceof \Psalm\Type\Atomic\TLiteralInt || $key_type instanceof \Psalm\Type\Atomic\TLiteralString) { $key_value = $key_type->value; } else { return new \Psalm\Type\Atomic\TArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getMixed()]); } $value_type = new \Psalm\Type\Union([self::resolve($classlikes, $entry->value, $statements_analyzer, $visited_constant_ids + [$c_id => \true])]); $properties[$key_value] = $value_type; } $objectlike = new \Psalm\Type\Atomic\TKeyedArray($properties); $objectlike->is_list = $is_list; $objectlike->sealed = \true; return $objectlike; } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\ClassConstant) { if ($c->name === 'class') { return new \Psalm\Type\Atomic\TLiteralClassString($c->fqcln); } $found_type = $classlikes->getClassConstantType($c->fqcln, $c->name, \ReflectionProperty::IS_PRIVATE, $statements_analyzer, $visited_constant_ids + [$c_id => \true]); if ($found_type) { return \array_values($found_type->getAtomicTypes())[0]; } } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\ArrayOffsetFetch) { $var_type = self::resolve($classlikes, $c->array, $statements_analyzer, $visited_constant_ids + [$c_id => \true]); $offset_type = self::resolve($classlikes, $c->offset, $statements_analyzer, $visited_constant_ids + [$c_id => \true]); if ($var_type instanceof \Psalm\Type\Atomic\TKeyedArray && ($offset_type instanceof \Psalm\Type\Atomic\TLiteralInt || $offset_type instanceof \Psalm\Type\Atomic\TLiteralString)) { $union = $var_type->properties[$offset_type->value] ?? null; if ($union && $union->isSingle()) { return \array_values($union->getAtomicTypes())[0]; } } } if ($c instanceof \Psalm\Internal\Scanner\UnresolvedConstant\Constant) { if ($statements_analyzer) { $found_type = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::getConstType($statements_analyzer, $c->name, $c->is_fully_qualified, null); if ($found_type) { return \array_values($found_type->getAtomicTypes())[0]; } } } return new \Psalm\Type\Atomic\TMixed(); } /** * @param string|int|float|bool|null $value */ private static function getLiteralTypeFromScalarValue($value) : \Psalm\Type\Atomic { if (\is_string($value)) { return new \Psalm\Type\Atomic\TLiteralString($value); } elseif (\is_int($value)) { return new \Psalm\Type\Atomic\TLiteralInt($value); } elseif (\is_float($value)) { return new \Psalm\Type\Atomic\TLiteralFloat($value); } elseif ($value === \false) { return new \Psalm\Type\Atomic\TFalse(); } elseif ($value === \true) { return new \Psalm\Type\Atomic\TTrue(); } else { return new \Psalm\Type\Atomic\TNull(); } } } > */ protected $forward_edges = []; public abstract function addNode(\Psalm\Internal\DataFlow\DataFlowNode $node) : void; /** * @param array $added_taints * @param array $removed_taints */ public function addPath(\Psalm\Internal\DataFlow\DataFlowNode $from, \Psalm\Internal\DataFlow\DataFlowNode $to, string $path_type, ?array $added_taints = null, ?array $removed_taints = null) : void { $from_id = $from->id; $to_id = $to->id; if ($from_id === $to_id) { return; } $this->forward_edges[$from_id][$to_id] = new \Psalm\Internal\DataFlow\Path($path_type, $added_taints, $removed_taints); } /** * @param array $previous_path_types * * @psalm-pure */ protected static function shouldIgnoreFetch(string $path_type, string $expression_type, array $previous_path_types) : bool { $el = \strlen($expression_type); if (\substr($path_type, 0, $el + 7) === $expression_type . '-fetch-') { $fetch_nesting = 0; $previous_path_types = \array_reverse($previous_path_types); foreach ($previous_path_types as $previous_path_type) { if ($previous_path_type === $expression_type . '-assignment') { if ($fetch_nesting === 0) { return \false; } $fetch_nesting--; } if (\substr($previous_path_type, 0, $el + 6) === $expression_type . '-fetch') { $fetch_nesting++; } if (\substr($previous_path_type, 0, $el + 12) === $expression_type . '-assignment-') { if ($fetch_nesting > 0) { $fetch_nesting--; continue; } if (\substr($previous_path_type, $el + 12) === \substr($path_type, $el + 7)) { return \false; } return \true; } } } return \false; } } classlike_storage_provider = $storage_provider; $this->file_reference_provider = $file_reference_provider; $this->classlikes = $classlikes; $this->return_type_provider = new \Psalm\Internal\Provider\MethodReturnTypeProvider(); $this->existence_provider = new \Psalm\Internal\Provider\MethodExistenceProvider(); $this->visibility_provider = new \Psalm\Internal\Provider\MethodVisibilityProvider(); $this->params_provider = new \Psalm\Internal\Provider\MethodParamsProvider(); } /** * Whether or not a given method exists * @param lowercase-string|null $calling_method_id */ public function methodExists(\Psalm\Internal\MethodIdentifier $method_id, ?string $calling_method_id = null, ?\Psalm\CodeLocation $code_location = null, ?\Psalm\StatementsSource $source = null, ?string $source_file_path = null, bool $use_method_existence_provider = \true) : bool { $fq_class_name = $method_id->fq_class_name; $method_name = $method_id->method_name; if ($use_method_existence_provider && $this->existence_provider->has($fq_class_name)) { $method_exists = $this->existence_provider->doesMethodExist($fq_class_name, $method_name, $source, $code_location); if ($method_exists !== null) { return $method_exists; } } $old_method_id = null; $fq_class_name = \strtolower($this->classlikes->getUnAliasedName($fq_class_name)); try { $class_storage = $this->classlike_storage_provider->get($fq_class_name); } catch (\InvalidArgumentException $e) { return \false; } $source_file_path = $source ? $source->getFilePath() : $source_file_path; $calling_class_name = $source ? $source->getFQCLN() : null; if (!$calling_class_name && $calling_method_id) { $calling_class_name = \explode('::', $calling_method_id)[0]; } if (isset($class_storage->declaring_method_ids[$method_name])) { $declaring_method_id = $class_storage->declaring_method_ids[$method_name]; if ($calling_method_id === \strtolower((string) $declaring_method_id)) { return \true; } $declaring_fq_class_name = \strtolower($declaring_method_id->fq_class_name); if ($declaring_fq_class_name !== \strtolower((string) $calling_class_name)) { if ($calling_method_id) { $this->file_reference_provider->addMethodReferenceToClass($calling_method_id, $declaring_fq_class_name); } elseif ($source_file_path) { $this->file_reference_provider->addNonMethodReferenceToClass($source_file_path, $declaring_fq_class_name); } } if ((string) $method_id !== (string) $declaring_method_id && $class_storage->user_defined && isset($class_storage->potential_declaring_method_ids[$method_name])) { foreach ($class_storage->potential_declaring_method_ids[$method_name] as $potential_id => $_) { if ($calling_method_id) { $this->file_reference_provider->addMethodReferenceToClassMember($calling_method_id, $potential_id); } elseif ($source_file_path) { $this->file_reference_provider->addFileReferenceToClassMember($source_file_path, $potential_id); } } } else { if ($calling_method_id) { $this->file_reference_provider->addMethodReferenceToClassMember($calling_method_id, \strtolower((string) $declaring_method_id)); } elseif ($source_file_path) { $this->file_reference_provider->addFileReferenceToClassMember($source_file_path, \strtolower((string) $declaring_method_id)); } } if ($this->collect_locations && $code_location) { $this->file_reference_provider->addCallingLocationForClassMethod($code_location, \strtolower((string) $declaring_method_id)); } foreach ($class_storage->class_implements as $fq_interface_name) { $interface_method_id_lc = \strtolower($fq_interface_name . '::' . $method_name); if ($this->collect_locations && $code_location) { $this->file_reference_provider->addCallingLocationForClassMethod($code_location, $interface_method_id_lc); } if ($calling_method_id) { $this->file_reference_provider->addMethodReferenceToClassMember($calling_method_id, $interface_method_id_lc); } elseif ($source_file_path) { $this->file_reference_provider->addFileReferenceToClassMember($source_file_path, $interface_method_id_lc); } } $declaring_method_class = $declaring_method_id->fq_class_name; $declaring_method_name = $declaring_method_id->method_name; $declaring_class_storage = $this->classlike_storage_provider->get($declaring_method_class); if (isset($declaring_class_storage->overridden_method_ids[$declaring_method_name])) { $overridden_method_ids = $declaring_class_storage->overridden_method_ids[$declaring_method_name]; foreach ($overridden_method_ids as $overridden_method_id) { if ($this->collect_locations && $code_location) { $this->file_reference_provider->addCallingLocationForClassMethod($code_location, \strtolower((string) $overridden_method_id)); } if ($calling_method_id) { // also store failures in case the method is added later $this->file_reference_provider->addMethodReferenceToClassMember($calling_method_id, \strtolower((string) $overridden_method_id)); } elseif ($source_file_path) { $this->file_reference_provider->addFileReferenceToClassMember($source_file_path, \strtolower((string) $overridden_method_id)); } } } return \true; } if ($source_file_path && $fq_class_name !== \strtolower((string) $calling_class_name)) { if ($calling_method_id) { $this->file_reference_provider->addMethodReferenceToClass($calling_method_id, $fq_class_name); } else { $this->file_reference_provider->addNonMethodReferenceToClass($source_file_path, $fq_class_name); } } if ($class_storage->abstract && isset($class_storage->overridden_method_ids[$method_name])) { return \true; } // support checking oldstyle constructors if ($method_name === '__construct') { $method_name_parts = \explode('\\', $fq_class_name); $old_constructor_name = \array_pop($method_name_parts); $old_method_id = $fq_class_name . '::' . $old_constructor_name; } if (!$class_storage->user_defined && (\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap((string) $method_id) || $old_method_id && \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($old_method_id))) { return \true; } foreach ($class_storage->parent_classes + $class_storage->used_traits as $potential_future_declaring_fqcln) { $potential_id = \strtolower($potential_future_declaring_fqcln) . '::' . $method_name; if ($calling_method_id) { // also store failures in case the method is added later $this->file_reference_provider->addMethodReferenceToMissingClassMember($calling_method_id, $potential_id); } elseif ($source_file_path) { $this->file_reference_provider->addFileReferenceToMissingClassMember($source_file_path, $potential_id); } } if ($calling_method_id) { // also store failures in case the method is added later $this->file_reference_provider->addMethodReferenceToMissingClassMember($calling_method_id, \strtolower((string) $method_id)); } elseif ($source_file_path) { $this->file_reference_provider->addFileReferenceToMissingClassMember($source_file_path, \strtolower((string) $method_id)); } return \false; } /** * @param array $args * * @return array */ public function getMethodParams(\Psalm\Internal\MethodIdentifier $method_id, ?\Psalm\StatementsSource $source = null, ?array $args = null, ?\Psalm\Context $context = null) : array { $fq_class_name = $method_id->fq_class_name; $method_name = $method_id->method_name; if ($this->params_provider->has($fq_class_name)) { $method_params = $this->params_provider->getMethodParams($fq_class_name, $method_name, $args, $source, $context); if ($method_params !== null) { return $method_params; } } $declaring_method_id = $this->getDeclaringMethodId($method_id); $callmap_id = $declaring_method_id ?: $method_id; // functions if (\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap((string) $callmap_id)) { $class_storage = $this->classlike_storage_provider->get($callmap_id->fq_class_name); if (!$class_storage->stubbed) { $function_callables = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallablesFromCallMap((string) $callmap_id); if ($function_callables === null) { throw new \UnexpectedValueException('Not expecting $function_callables to be null for ' . $callmap_id); } if (!$source || $args === null || \count($function_callables) === 1) { \assert($function_callables[0]->params !== null); return $function_callables[0]->params; } if ($context && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $was_inside_call = $context->inside_call; $context->inside_call = \true; foreach ($args as $arg) { \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($source, $arg->value, $context); } if (!$was_inside_call) { $context->inside_call = \false; } } $matching_callable = \Psalm\Internal\Codebase\InternalCallMapHandler::getMatchingCallableFromCallMapOptions($source->getCodebase(), $function_callables, $args, $source->getNodeTypeProvider(), (string) $callmap_id); \assert($matching_callable->params !== null); return $matching_callable->params; } } if ($declaring_method_id) { $storage = $this->getStorage($declaring_method_id); $params = $storage->params; if ($storage->has_docblock_param_types) { return $params; } $appearing_method_id = $this->getAppearingMethodId($declaring_method_id); if (!$appearing_method_id) { return $params; } $appearing_fq_class_name = $appearing_method_id->fq_class_name; $appearing_method_name = $appearing_method_id->method_name; $class_storage = $this->classlike_storage_provider->get($appearing_fq_class_name); if (!isset($class_storage->overridden_method_ids[$appearing_method_name])) { return $params; } if (!isset($class_storage->documenting_method_ids[$appearing_method_name])) { return $params; } $overridden_method_id = $class_storage->documenting_method_ids[$appearing_method_name]; $overridden_storage = $this->getStorage($overridden_method_id); $overriding_fq_class_name = $overridden_method_id->fq_class_name; foreach ($params as $i => $param) { if (isset($overridden_storage->params[$i]->type) && $overridden_storage->params[$i]->has_docblock_type) { $params[$i] = clone $param; /** @var Type\Union $params[$i]->type */ $params[$i]->type = clone $overridden_storage->params[$i]->type; if ($source) { $overridden_class_storage = $this->classlike_storage_provider->get($overriding_fq_class_name); $params[$i]->type = self::localizeType($source->getCodebase(), $params[$i]->type, $appearing_fq_class_name, $overridden_class_storage->name); } if ($params[$i]->signature_type && $params[$i]->signature_type->isNullable()) { $params[$i]->type->addType(new \Psalm\Type\Atomic\TNull()); } $params[$i]->type_location = $overridden_storage->params[$i]->type_location; } } return $params; } throw new \UnexpectedValueException('Cannot get method params for ' . $method_id); } public static function localizeType(\Psalm\Codebase $codebase, \Psalm\Type\Union $type, string $appearing_fq_class_name, string $base_fq_class_name) : \Psalm\Type\Union { $class_storage = $codebase->classlike_storage_provider->get($appearing_fq_class_name); $extends = $class_storage->template_type_extends; if (!$extends) { return $type; } $type = clone $type; foreach ($type->getAtomicTypes() as $key => $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam && ($atomic_type->defining_class === $base_fq_class_name || isset($extends[$atomic_type->defining_class]))) { $types_to_add = self::getExtendedTemplatedTypes($atomic_type, $extends); if ($types_to_add) { $type->removeType($key); foreach ($types_to_add as $extra_added_type) { $type->addType($extra_added_type); } } } if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { if ($atomic_type->defining_class === $base_fq_class_name) { if (isset($extends[$base_fq_class_name][$atomic_type->param_name])) { $extended_param = $extends[$base_fq_class_name][$atomic_type->param_name]; $types = \array_values($extended_param->getAtomicTypes()); if (\count($types) === 1 && $types[0] instanceof \Psalm\Type\Atomic\TNamedObject) { $atomic_type->as_type = $types[0]; } else { $atomic_type->as_type = null; } } } } if ($atomic_type instanceof \Psalm\Type\Atomic\TArray || $atomic_type instanceof \Psalm\Type\Atomic\TIterable || $atomic_type instanceof \Psalm\Type\Atomic\TGenericObject) { foreach ($atomic_type->type_params as &$type_param) { $type_param = self::localizeType($codebase, $type_param, $appearing_fq_class_name, $base_fq_class_name); } } if ($atomic_type instanceof \Psalm\Type\Atomic\TList) { $atomic_type->type_param = self::localizeType($codebase, $atomic_type->type_param, $appearing_fq_class_name, $base_fq_class_name); } if ($atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { foreach ($atomic_type->properties as &$property_type) { $property_type = self::localizeType($codebase, $property_type, $appearing_fq_class_name, $base_fq_class_name); } } if ($atomic_type instanceof \Psalm\Type\Atomic\TCallable || $atomic_type instanceof \Psalm\Type\Atomic\TClosure) { if ($atomic_type->params) { foreach ($atomic_type->params as $param) { if ($param->type) { $param->type = self::localizeType($codebase, $param->type, $appearing_fq_class_name, $base_fq_class_name); } } } if ($atomic_type->return_type) { $atomic_type->return_type = self::localizeType($codebase, $atomic_type->return_type, $appearing_fq_class_name, $base_fq_class_name); } } } $type->bustCache(); return $type; } /** * @param array> $extends * @return list */ public static function getExtendedTemplatedTypes(\Psalm\Type\Atomic\TTemplateParam $atomic_type, array $extends) : array { $extra_added_types = []; if (isset($extends[$atomic_type->defining_class][$atomic_type->param_name])) { $extended_param = clone $extends[$atomic_type->defining_class][$atomic_type->param_name]; foreach ($extended_param->getAtomicTypes() as $extended_atomic_type) { if ($extended_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $extra_added_types = \array_merge($extra_added_types, self::getExtendedTemplatedTypes($extended_atomic_type, $extends)); } else { $extra_added_types[] = $extended_atomic_type; } } } else { $extra_added_types[] = $atomic_type; } return $extra_added_types; } public function isVariadic(\Psalm\Internal\MethodIdentifier $method_id) : bool { $declaring_method_id = $this->getDeclaringMethodId($method_id); if (!$declaring_method_id) { return \false; } return $this->getStorage($declaring_method_id)->variadic; } /** * @param array|null $args * */ public function getMethodReturnType(\Psalm\Internal\MethodIdentifier $method_id, ?string &$self_class, ?\Psalm\Internal\Analyzer\SourceAnalyzer $source_analyzer = null, ?array $args = null) : ?\Psalm\Type\Union { $original_fq_class_name = $method_id->fq_class_name; $original_method_name = $method_id->method_name; $adjusted_fq_class_name = $this->classlikes->getUnAliasedName($original_fq_class_name); if ($adjusted_fq_class_name !== $original_fq_class_name) { $original_fq_class_name = \strtolower($adjusted_fq_class_name); } $original_class_storage = $this->classlike_storage_provider->get($original_fq_class_name); if (isset($original_class_storage->pseudo_methods[$original_method_name])) { return $original_class_storage->pseudo_methods[$original_method_name]->return_type; } $declaring_method_id = $this->getDeclaringMethodId($method_id); if (!$declaring_method_id) { return null; } $appearing_method_id = $this->getAppearingMethodId($method_id); if (!$appearing_method_id) { $class_storage = $this->classlike_storage_provider->get($original_fq_class_name); if ($class_storage->abstract && isset($class_storage->overridden_method_ids[$original_method_name])) { $appearing_method_id = \reset($class_storage->overridden_method_ids[$original_method_name]); } else { return null; } } $appearing_fq_class_name = $appearing_method_id->fq_class_name; $appearing_method_name = $appearing_method_id->method_name; $appearing_fq_class_storage = $this->classlike_storage_provider->get($appearing_fq_class_name); if (!$appearing_fq_class_storage->user_defined && !$appearing_fq_class_storage->stubbed && \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap((string) $appearing_method_id)) { if ((string) $appearing_method_id === 'Closure::fromcallable' && isset($args[0]) && $source_analyzer && ($first_arg_type = $source_analyzer->getNodeTypeProvider()->getType($args[0]->value)) && $first_arg_type->isSingle()) { foreach ($first_arg_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TCallable || $atomic_type instanceof \Psalm\Type\Atomic\TClosure) { $callable_type = clone $atomic_type; return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClosure('Closure', $callable_type->params, $callable_type->return_type)]); } if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject && $this->methodExists(new \Psalm\Internal\MethodIdentifier($atomic_type->value, '__invoke'))) { $invokable_storage = $this->getStorage(new \Psalm\Internal\MethodIdentifier($atomic_type->value, '__invoke')); return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClosure('Closure', $invokable_storage->params, $invokable_storage->return_type)]); } } } $callmap_callables = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallablesFromCallMap((string) $appearing_method_id); if (!$callmap_callables || $callmap_callables[0]->return_type === null) { throw new \UnexpectedValueException('Shouldn’t get here'); } $return_type_candidate = $callmap_callables[0]->return_type; if ($return_type_candidate->isFalsable()) { $return_type_candidate->ignore_falsable_issues = \true; } return $return_type_candidate; } $storage = $this->getStorage($declaring_method_id); if ($storage->return_type) { $self_class = $appearing_fq_class_storage->name; return clone $storage->return_type; } $class_storage = $this->classlike_storage_provider->get($appearing_fq_class_name); if (!isset($class_storage->overridden_method_ids[$appearing_method_name])) { return null; } $candidate_type = null; foreach ($class_storage->overridden_method_ids[$appearing_method_name] as $overridden_method_id) { $overridden_storage = $this->getStorage($overridden_method_id); if ($overridden_storage->return_type) { if ($overridden_storage->return_type->isNull()) { if ($candidate_type && !$candidate_type->isVoid()) { return null; } $candidate_type = \Psalm\Type::getVoid(); continue; } $fq_overridden_class = $overridden_method_id->fq_class_name; $overridden_class_storage = $this->classlike_storage_provider->get($fq_overridden_class); $overridden_return_type = clone $overridden_storage->return_type; $self_class = $overridden_class_storage->name; if ($candidate_type && $source_analyzer) { $old_contained_by_new = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($source_analyzer->getCodebase(), $candidate_type, $overridden_return_type); $new_contained_by_old = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($source_analyzer->getCodebase(), $overridden_return_type, $candidate_type); if (!$old_contained_by_new && !$new_contained_by_old) { $attempted_intersection = \Psalm\Type::intersectUnionTypes($candidate_type, $overridden_return_type, $source_analyzer->getCodebase()); if ($attempted_intersection) { $candidate_type = $attempted_intersection; continue; } return null; } if ($old_contained_by_new) { continue; } } $candidate_type = $overridden_return_type; } } return $candidate_type; } public function getMethodReturnsByRef(\Psalm\Internal\MethodIdentifier $method_id) : bool { $method_id = $this->getDeclaringMethodId($method_id); if (!$method_id) { return \false; } $fq_class_storage = $this->classlike_storage_provider->get($method_id->fq_class_name); if (!$fq_class_storage->user_defined && \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap((string) $method_id)) { return \false; } $storage = $this->getStorage($method_id); return $storage->returns_by_ref; } /** * @param CodeLocation|null $defined_location * */ public function getMethodReturnTypeLocation(\Psalm\Internal\MethodIdentifier $method_id, \Psalm\CodeLocation &$defined_location = null) : ?\Psalm\CodeLocation { $method_id = $this->getDeclaringMethodId($method_id); if ($method_id === null) { return null; } $storage = $this->getStorage($method_id); if (!$storage->return_type_location) { $overridden_method_ids = $this->getOverriddenMethodIds($method_id); foreach ($overridden_method_ids as $overridden_method_id) { $overridden_storage = $this->getStorage($overridden_method_id); if ($overridden_storage->return_type_location) { $defined_location = $overridden_storage->return_type_location; break; } } } return $storage->return_type_location; } /** * @param lowercase-string $method_name_lc * @param lowercase-string $declaring_method_name_lc * */ public function setDeclaringMethodId(string $fq_class_name, string $method_name_lc, string $declaring_fq_class_name, string $declaring_method_name_lc) : void { $class_storage = $this->classlike_storage_provider->get($fq_class_name); $class_storage->declaring_method_ids[$method_name_lc] = new \Psalm\Internal\MethodIdentifier($declaring_fq_class_name, $declaring_method_name_lc); } /** * @param lowercase-string $method_name_lc * @param lowercase-string $appearing_method_name_lc * */ public function setAppearingMethodId(string $fq_class_name, string $method_name_lc, string $appearing_fq_class_name, string $appearing_method_name_lc) : void { $class_storage = $this->classlike_storage_provider->get($fq_class_name); $class_storage->appearing_method_ids[$method_name_lc] = new \Psalm\Internal\MethodIdentifier($appearing_fq_class_name, $appearing_method_name_lc); } public function getDeclaringMethodId(\Psalm\Internal\MethodIdentifier $method_id) : ?\Psalm\Internal\MethodIdentifier { $fq_class_name = $this->classlikes->getUnAliasedName($method_id->fq_class_name); $class_storage = $this->classlike_storage_provider->get($fq_class_name); $method_name = $method_id->method_name; if (isset($class_storage->declaring_method_ids[$method_name])) { return $class_storage->declaring_method_ids[$method_name]; } if ($class_storage->abstract && isset($class_storage->overridden_method_ids[$method_name])) { return \reset($class_storage->overridden_method_ids[$method_name]); } return null; } /** * Get the class this method appears in (vs is declared in, which could give a trait */ public function getAppearingMethodId(\Psalm\Internal\MethodIdentifier $method_id) : ?\Psalm\Internal\MethodIdentifier { $fq_class_name = $this->classlikes->getUnAliasedName($method_id->fq_class_name); $class_storage = $this->classlike_storage_provider->get($fq_class_name); $method_name = $method_id->method_name; if (isset($class_storage->appearing_method_ids[$method_name])) { return $class_storage->appearing_method_ids[$method_name]; } return null; } /** * @return array */ public function getOverriddenMethodIds(\Psalm\Internal\MethodIdentifier $method_id) : array { $class_storage = $this->classlike_storage_provider->get($method_id->fq_class_name); $method_name = $method_id->method_name; if (isset($class_storage->overridden_method_ids[$method_name])) { return $class_storage->overridden_method_ids[$method_name]; } return []; } public function getCasedMethodId(\Psalm\Internal\MethodIdentifier $original_method_id) : string { $method_id = $this->getDeclaringMethodId($original_method_id); if ($method_id === null) { return $original_method_id; } $fq_class_name = $method_id->fq_class_name; $new_method_name = $method_id->method_name; $old_fq_class_name = $original_method_id->fq_class_name; $old_method_name = $original_method_id->method_name; $storage = $this->getStorage($method_id); if ($old_method_name === $new_method_name && \strtolower($old_fq_class_name) !== $old_fq_class_name) { return $old_fq_class_name . '::' . $storage->cased_name; } return $fq_class_name . '::' . $storage->cased_name; } public function getUserMethodStorage(\Psalm\Internal\MethodIdentifier $method_id) : ?\Psalm\Storage\MethodStorage { $declaring_method_id = $this->getDeclaringMethodId($method_id); if (!$declaring_method_id) { throw new \UnexpectedValueException('$storage should not be null for ' . $method_id); } $storage = $this->getStorage($declaring_method_id); if (!$storage->location) { return null; } return $storage; } public function getClassLikeStorageForMethod(\Psalm\Internal\MethodIdentifier $method_id) : \Psalm\Storage\ClassLikeStorage { $fq_class_name = $method_id->fq_class_name; $method_name = $method_id->method_name; if ($this->existence_provider->has($fq_class_name)) { if ($this->existence_provider->doesMethodExist($fq_class_name, $method_name, null, null)) { return $this->classlike_storage_provider->get($fq_class_name); } } $declaring_method_id = $this->getDeclaringMethodId($method_id); if ($declaring_method_id === null) { if (\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap((string) $method_id)) { $declaring_method_id = $method_id; } else { throw new \UnexpectedValueException('$storage should not be null for ' . $method_id); } } $declaring_fq_class_name = $declaring_method_id->fq_class_name; return $this->classlike_storage_provider->get($declaring_fq_class_name); } public function getStorage(\Psalm\Internal\MethodIdentifier $method_id) : \Psalm\Storage\MethodStorage { try { $class_storage = $this->classlike_storage_provider->get($method_id->fq_class_name); } catch (\InvalidArgumentException $e) { throw new \UnexpectedValueException($e->getMessage()); } $method_name = $method_id->method_name; if (!isset($class_storage->methods[$method_name])) { throw new \UnexpectedValueException('$storage should not be null for ' . $method_id); } return $class_storage->methods[$method_name]; } public function hasStorage(\Psalm\Internal\MethodIdentifier $method_id) : bool { try { $class_storage = $this->classlike_storage_provider->get($method_id->fq_class_name); } catch (\InvalidArgumentException $e) { return \false; } $method_name = $method_id->method_name; if (!isset($class_storage->methods[$method_name])) { return \false; } return \true; } } > */ private $invalid_class_storages = []; /** * @var Progress */ private $progress; /** * @var ClassLikes */ private $classlikes; /** * @var Config */ private $config; /** * @var FileReferenceProvider */ private $file_reference_provider; public function __construct(\Psalm\Config $config, \Psalm\Internal\Provider\ClassLikeStorageProvider $classlike_storage_provider, \Psalm\Internal\Provider\FileStorageProvider $file_storage_provider, \Psalm\Internal\Codebase\ClassLikes $classlikes, \Psalm\Internal\Provider\FileReferenceProvider $file_reference_provider, \Psalm\Progress\Progress $progress) { $this->classlike_storage_provider = $classlike_storage_provider; $this->file_storage_provider = $file_storage_provider; $this->classlikes = $classlikes; $this->progress = $progress; $this->config = $config; $this->file_reference_provider = $file_reference_provider; } public function populateCodebase() : void { $this->progress->debug('ClassLikeStorage is populating' . "\n"); foreach ($this->classlike_storage_provider->getNew() as $class_storage) { $this->populateClassLikeStorage($class_storage); } $this->progress->debug('ClassLikeStorage is populated' . "\n"); $this->progress->debug('FileStorage is populating' . "\n"); $all_file_storage = $this->file_storage_provider->getNew(); foreach ($all_file_storage as $file_storage) { $this->populateFileStorage($file_storage); } foreach ($this->classlike_storage_provider->getNew() as $class_storage) { if ($this->config->allow_phpstorm_generics) { foreach ($class_storage->properties as $property_storage) { if ($property_storage->type) { $this->convertPhpStormGenericToPsalmGeneric($property_storage->type, \true); } } foreach ($class_storage->methods as $method_storage) { if ($method_storage->return_type) { $this->convertPhpStormGenericToPsalmGeneric($method_storage->return_type); } foreach ($method_storage->params as $param_storage) { if ($param_storage->type) { $this->convertPhpStormGenericToPsalmGeneric($param_storage->type); } } } } foreach ($class_storage->dependent_classlikes as $dependent_classlike_lc => $_) { $dependee_storage = $this->classlike_storage_provider->get($dependent_classlike_lc); $class_storage->dependent_classlikes += $dependee_storage->dependent_classlikes; } } if ($this->config->allow_phpstorm_generics) { foreach ($all_file_storage as $file_storage) { foreach ($file_storage->functions as $function_storage) { if ($function_storage->return_type) { $this->convertPhpStormGenericToPsalmGeneric($function_storage->return_type); } foreach ($function_storage->params as $param_storage) { if ($param_storage->type) { $this->convertPhpStormGenericToPsalmGeneric($param_storage->type); } } } } } $this->progress->debug('FileStorage is populated' . "\n"); $this->classlike_storage_provider->populated(); $this->file_storage_provider->populated(); } private function populateClassLikeStorage(\Psalm\Storage\ClassLikeStorage $storage, array $dependent_classlikes = []) : void { if ($storage->populated) { return; } $fq_classlike_name_lc = \strtolower($storage->name); if (isset($dependent_classlikes[$fq_classlike_name_lc])) { if ($storage->location && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\CircularReference('Circular reference discovered when loading ' . $storage->name, $storage->location))) { // fall through } return; } $storage_provider = $this->classlike_storage_provider; $dependent_classlikes[$fq_classlike_name_lc] = \true; $this->populateDataFromTraits($storage, $storage_provider, $dependent_classlikes); if ($storage->parent_classes) { $this->populateDataFromParentClass($storage, $storage_provider, $dependent_classlikes); } if (!\strpos($fq_classlike_name_lc, '\\') && !isset($storage->methods['__construct']) && isset($storage->methods[$fq_classlike_name_lc]) && !$storage->is_interface && !$storage->is_trait) { /** @psalm-suppress PropertyTypeCoercion */ $storage->methods['__construct'] = $storage->methods[$fq_classlike_name_lc]; } $this->populateInterfaceDataFromParentInterfaces($storage, $storage_provider, $dependent_classlikes); $this->populateDataFromImplementedInterfaces($storage, $storage_provider, $dependent_classlikes); if ($storage->location) { $file_path = $storage->location->file_path; foreach ($storage->parent_interfaces as $parent_interface_lc) { $this->file_reference_provider->addFileInheritanceToClass($file_path, $parent_interface_lc); } foreach ($storage->parent_classes as $parent_class_lc => $_) { $this->file_reference_provider->addFileInheritanceToClass($file_path, $parent_class_lc); } foreach ($storage->class_implements as $implemented_interface) { $this->file_reference_provider->addFileInheritanceToClass($file_path, \strtolower($implemented_interface)); } foreach ($storage->used_traits as $used_trait_lc => $_) { $this->file_reference_provider->addFileInheritanceToClass($file_path, $used_trait_lc); } } if ($storage->mutation_free || $storage->external_mutation_free) { foreach ($storage->methods as $method) { if (!$method->is_static && !$method->external_mutation_free) { $method->mutation_free = $storage->mutation_free; $method->external_mutation_free = $storage->external_mutation_free; } } if ($storage->mutation_free) { foreach ($storage->properties as $property) { if (!$property->is_static) { $property->readonly = \true; } } } } if ($storage->specialize_instance) { foreach ($storage->methods as $method) { if (!$method->is_static) { $method->specialize_call = \true; } } } if (!$storage->is_interface && !$storage->is_trait) { foreach ($storage->methods as $method) { if (\strlen($storage->internal) > \strlen($method->internal)) { $method->internal = $storage->internal; } } foreach ($storage->properties as $property) { if (\strlen($storage->internal) > \strlen($property->internal)) { $property->internal = $storage->internal; } } } $this->populateOverriddenMethods($storage); $this->progress->debug('Have populated ' . $storage->name . "\n"); $storage->populated = \true; if (isset($this->invalid_class_storages[$fq_classlike_name_lc])) { foreach ($this->invalid_class_storages[$fq_classlike_name_lc] as $dependency) { $dependency->populated = \false; $this->populateClassLikeStorage($dependency, $dependent_classlikes); } unset($this->invalid_class_storages[$fq_classlike_name_lc]); } } private function populateOverriddenMethods(\Psalm\Storage\ClassLikeStorage $storage) : void { foreach ($storage->methods as $method_name => $method_storage) { if (isset($storage->overridden_method_ids[$method_name])) { $overridden_method_ids = $storage->overridden_method_ids[$method_name]; $candidate_overridden_ids = null; $declaring_class_storages = []; foreach ($overridden_method_ids as $declaring_method_id) { $declaring_class = $declaring_method_id->fq_class_name; $declaring_class_storage = $declaring_class_storages[$declaring_class] = $this->classlike_storage_provider->get($declaring_class); if ($candidate_overridden_ids === null) { $candidate_overridden_ids = ($declaring_class_storage->overridden_method_ids[$method_name] ?? []) + [$declaring_method_id->fq_class_name => $declaring_method_id]; } else { $candidate_overridden_ids = \array_intersect_key($candidate_overridden_ids, ($declaring_class_storage->overridden_method_ids[$method_name] ?? []) + [$declaring_method_id->fq_class_name => $declaring_method_id]); } } foreach ($overridden_method_ids as $declaring_method_id) { $declaring_class = $declaring_method_id->fq_class_name; $declaring_method_name = $declaring_method_id->method_name; $declaring_class_storage = $declaring_class_storages[$declaring_class]; $declaring_method_storage = $declaring_class_storage->methods[$declaring_method_name]; if ($declaring_method_storage->has_docblock_param_types && !$method_storage->has_docblock_param_types && !isset($storage->documenting_method_ids[$method_name])) { $storage->documenting_method_ids[$method_name] = $declaring_method_id; } // tell the declaring class it's overridden downstream $declaring_method_storage->overridden_downstream = \true; $declaring_method_storage->overridden_somewhere = \true; if ($declaring_method_storage->mutation_free_inferred) { $declaring_method_storage->mutation_free = \false; $declaring_method_storage->external_mutation_free = \false; $declaring_method_storage->mutation_free_inferred = \false; } if ($declaring_method_storage->throws && (!$method_storage->throws || $method_storage->inheritdoc)) { $method_storage->throws += $declaring_method_storage->throws; } if ((\count($overridden_method_ids) === 1 || $candidate_overridden_ids) && $method_storage->signature_return_type && !$method_storage->signature_return_type->isVoid() && ($method_storage->return_type === $method_storage->signature_return_type || $method_storage->inherited_return_type)) { if (isset($declaring_class_storage->methods[$method_name])) { $declaring_method_storage = $declaring_class_storage->methods[$method_name]; if ($declaring_method_storage->return_type && $declaring_method_storage->return_type !== $declaring_method_storage->signature_return_type) { if ($declaring_method_storage->signature_return_type && \Psalm\Internal\Type\Comparator\UnionTypeComparator::isSimplyContainedBy($method_storage->signature_return_type, $declaring_method_storage->signature_return_type)) { $method_storage->return_type = clone $declaring_method_storage->return_type; $method_storage->inherited_return_type = \true; } elseif (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isSimplyContainedBy($declaring_method_storage->return_type, $method_storage->signature_return_type)) { $method_storage->return_type = clone $declaring_method_storage->return_type; $method_storage->inherited_return_type = \true; $method_storage->return_type->from_docblock = \false; } } } } } } } } private function populateDataFromTraits(\Psalm\Storage\ClassLikeStorage $storage, \Psalm\Internal\Provider\ClassLikeStorageProvider $storage_provider, array $dependent_classlikes) : void { foreach ($storage->used_traits as $used_trait_lc => $_) { try { $used_trait_lc = \strtolower($this->classlikes->getUnAliasedName($used_trait_lc)); $trait_storage = $storage_provider->get($used_trait_lc); } catch (\InvalidArgumentException $e) { continue; } $this->populateClassLikeStorage($trait_storage, $dependent_classlikes); $this->inheritMethodsFromParent($storage, $trait_storage); $this->inheritPropertiesFromParent($storage, $trait_storage); if ($trait_storage->template_types) { if (isset($storage->template_type_extends[$trait_storage->name])) { foreach ($storage->template_type_extends[$trait_storage->name] as $i => $type) { $trait_template_type_names = \array_keys($trait_storage->template_types); $mapped_name = $trait_template_type_names[$i] ?? null; if ($mapped_name) { $storage->template_type_extends[$trait_storage->name][$mapped_name] = $type; } } if ($trait_storage->template_type_extends) { foreach ($trait_storage->template_type_extends as $t_storage_class => $type_map) { foreach ($type_map as $i => $type) { if (\is_int($i)) { continue; } $storage->template_type_extends[$t_storage_class][$i] = self::extendType($type, $storage); } } } } else { $storage->template_type_extends[$trait_storage->name] = []; foreach ($trait_storage->template_types as $template_name => $template_type_map) { foreach ($template_type_map as $template_type) { $default_param = clone $template_type[0]; $default_param->from_docblock = \false; $storage->template_type_extends[$trait_storage->name][$template_name] = $default_param; } } } } elseif ($trait_storage->template_type_extends) { $storage->template_type_extends = \array_merge($storage->template_type_extends ?: [], $trait_storage->template_type_extends); } $storage->pseudo_property_get_types += $trait_storage->pseudo_property_get_types; $storage->pseudo_property_set_types += $trait_storage->pseudo_property_set_types; $storage->pseudo_methods += $trait_storage->pseudo_methods; } } private static function extendType(\Psalm\Type\Union $type, \Psalm\Storage\ClassLikeStorage $storage) : \Psalm\Type\Union { $extended_types = []; foreach ($type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $referenced_type = $storage->template_type_extends[$atomic_type->defining_class][$atomic_type->param_name] ?? null; if ($referenced_type) { foreach ($referenced_type->getAtomicTypes() as $atomic_referenced_type) { if (!$atomic_referenced_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $extended_types[] = $atomic_referenced_type; } else { $extended_types[] = $atomic_type; } } } else { $extended_types[] = $atomic_type; } } else { $extended_types[] = $atomic_type; } } return new \Psalm\Type\Union($extended_types); } private function populateDataFromParentClass(\Psalm\Storage\ClassLikeStorage $storage, \Psalm\Internal\Provider\ClassLikeStorageProvider $storage_provider, array $dependent_classlikes) : void { $parent_storage_class = \reset($storage->parent_classes); $parent_storage_class = \strtolower($this->classlikes->getUnAliasedName($parent_storage_class)); try { $parent_storage = $storage_provider->get($parent_storage_class); } catch (\InvalidArgumentException $e) { $this->progress->debug('Populator could not find dependency (' . __LINE__ . ")\n"); $storage->invalid_dependencies[] = $parent_storage_class; $this->invalid_class_storages[\strtolower($parent_storage_class)][] = $storage; return; } $this->populateClassLikeStorage($parent_storage, $dependent_classlikes); $storage->parent_classes = \array_merge($storage->parent_classes, $parent_storage->parent_classes); if ($parent_storage->template_types) { if (isset($storage->template_type_extends[$parent_storage->name])) { foreach ($storage->template_type_extends[$parent_storage->name] as $i => $type) { $parent_template_type_names = \array_keys($parent_storage->template_types); $mapped_name = $parent_template_type_names[$i] ?? null; if ($mapped_name) { $storage->template_type_extends[$parent_storage->name][$mapped_name] = $type; } } if ($parent_storage->template_type_extends) { foreach ($parent_storage->template_type_extends as $t_storage_class => $type_map) { foreach ($type_map as $i => $type) { if (\is_int($i)) { continue; } $storage->template_type_extends[$t_storage_class][$i] = self::extendType($type, $storage); } } } } else { $storage->template_type_extends[$parent_storage->name] = []; foreach ($parent_storage->template_types as $template_name => $template_type_map) { foreach ($template_type_map as $template_type) { $default_param = clone $template_type[0]; $default_param->from_docblock = \false; $storage->template_type_extends[$parent_storage->name][$template_name] = $default_param; } } if ($parent_storage->template_type_extends) { $storage->template_type_extends = \array_merge($storage->template_type_extends, $parent_storage->template_type_extends); } } } elseif ($parent_storage->template_type_extends) { $storage->template_type_extends = \array_merge($storage->template_type_extends ?: [], $parent_storage->template_type_extends); } $this->inheritMethodsFromParent($storage, $parent_storage); $this->inheritPropertiesFromParent($storage, $parent_storage); $storage->class_implements = \array_merge($storage->class_implements, $parent_storage->class_implements); $storage->invalid_dependencies = \array_merge($storage->invalid_dependencies, $parent_storage->invalid_dependencies); if ($parent_storage->has_visitor_issues) { $storage->has_visitor_issues = \true; } $storage->constants = \array_merge(\array_filter($parent_storage->constants, function ($constant) { return $constant->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC || $constant->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED; }), $storage->constants); if ($parent_storage->preserve_constructor_signature) { $storage->preserve_constructor_signature = \true; } if (($parent_storage->namedMixins || $parent_storage->templatedMixins) && (!$storage->namedMixins || !$storage->templatedMixins)) { $storage->mixin_declaring_fqcln = $parent_storage->mixin_declaring_fqcln; if (!$storage->namedMixins) { $storage->namedMixins = $parent_storage->namedMixins; } if (!$storage->templatedMixins) { $storage->templatedMixins = $parent_storage->templatedMixins; } } $storage->pseudo_property_get_types += $parent_storage->pseudo_property_get_types; $storage->pseudo_property_set_types += $parent_storage->pseudo_property_set_types; $parent_storage->dependent_classlikes[\strtolower($storage->name)] = \true; $storage->pseudo_methods += $parent_storage->pseudo_methods; } private function populateInterfaceDataFromParentInterfaces(\Psalm\Storage\ClassLikeStorage $storage, \Psalm\Internal\Provider\ClassLikeStorageProvider $storage_provider, array $dependent_classlikes) : void { $parent_interfaces = []; foreach ($storage->parent_interfaces as $parent_interface_lc => $_) { try { $parent_interface_lc = \strtolower($this->classlikes->getUnAliasedName($parent_interface_lc)); $parent_interface_storage = $storage_provider->get($parent_interface_lc); } catch (\InvalidArgumentException $e) { $this->progress->debug('Populator could not find dependency (' . __LINE__ . ")\n"); $storage->invalid_dependencies[] = $parent_interface_lc; continue; } $this->populateClassLikeStorage($parent_interface_storage, $dependent_classlikes); // copy over any constants $storage->constants = \array_merge(\array_filter($parent_interface_storage->constants, function ($constant) { return $constant->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; }), $storage->constants); $storage->invalid_dependencies = \array_merge($storage->invalid_dependencies, $parent_interface_storage->invalid_dependencies); if ($parent_interface_storage->template_types) { if (isset($storage->template_type_extends[$parent_interface_storage->name])) { foreach ($storage->template_type_extends[$parent_interface_storage->name] as $i => $type) { $parent_template_type_names = \array_keys($parent_interface_storage->template_types); $mapped_name = $parent_template_type_names[$i] ?? null; if ($mapped_name) { $storage->template_type_extends[$parent_interface_storage->name][$mapped_name] = $type; } } if ($parent_interface_storage->template_type_extends) { foreach ($parent_interface_storage->template_type_extends as $t_storage_class => $type_map) { foreach ($type_map as $i => $type) { if (\is_int($i)) { continue; } $storage->template_type_extends[$t_storage_class][$i] = self::extendType($type, $storage); } } } } else { $storage->template_type_extends[$parent_interface_storage->name] = []; foreach ($parent_interface_storage->template_types as $template_name => $template_type_map) { foreach ($template_type_map as $template_type) { $default_param = clone $template_type[0]; $default_param->from_docblock = \false; $storage->template_type_extends[$parent_interface_storage->name][$template_name] = $default_param; } } } } elseif ($parent_interface_storage->template_type_extends) { $storage->template_type_extends = \array_merge($storage->template_type_extends ?: [], $parent_interface_storage->template_type_extends); } $parent_interface_storage->dependent_classlikes[\strtolower($storage->name)] = \true; $parent_interfaces = \array_merge($parent_interfaces, $parent_interface_storage->parent_interfaces); $this->inheritMethodsFromParent($storage, $parent_interface_storage); $storage->pseudo_methods += $parent_interface_storage->pseudo_methods; } $storage->parent_interfaces = \array_merge($parent_interfaces, $storage->parent_interfaces); } private function populateDataFromImplementedInterfaces(\Psalm\Storage\ClassLikeStorage $storage, \Psalm\Internal\Provider\ClassLikeStorageProvider $storage_provider, array $dependent_classlikes) : void { $extra_interfaces = []; foreach ($storage->class_implements as $implemented_interface_lc => $_) { try { $implemented_interface_lc = \strtolower($this->classlikes->getUnAliasedName($implemented_interface_lc)); $implemented_interface_storage = $storage_provider->get($implemented_interface_lc); } catch (\InvalidArgumentException $e) { $this->progress->debug('Populator could not find dependency (' . __LINE__ . ")\n"); $storage->invalid_dependencies[] = $implemented_interface_lc; continue; } $this->populateClassLikeStorage($implemented_interface_storage, $dependent_classlikes); // copy over any constants $storage->constants = \array_merge(\array_filter($implemented_interface_storage->constants, function ($constant) { return $constant->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; }), $storage->constants); $storage->invalid_dependencies = \array_merge($storage->invalid_dependencies, $implemented_interface_storage->invalid_dependencies); if ($implemented_interface_storage->template_types) { if (isset($storage->template_type_extends[$implemented_interface_storage->name])) { foreach ($storage->template_type_extends[$implemented_interface_storage->name] as $i => $type) { $parent_template_type_names = \array_keys($implemented_interface_storage->template_types); $mapped_name = $parent_template_type_names[$i] ?? null; if ($mapped_name) { $storage->template_type_extends[$implemented_interface_storage->name][$mapped_name] = $type; } } if ($implemented_interface_storage->template_type_extends) { foreach ($implemented_interface_storage->template_type_extends as $e_i => $type_map) { foreach ($type_map as $i => $type) { if (\is_int($i)) { continue; } $storage->template_type_extends[$e_i][$i] = self::extendType($type, $storage); } } } } else { $storage->template_type_extends[$implemented_interface_storage->name] = []; foreach ($implemented_interface_storage->template_types as $template_name => $template_type_map) { foreach ($template_type_map as $template_type) { $default_param = clone $template_type[0]; $default_param->from_docblock = \false; $storage->template_type_extends[$implemented_interface_storage->name][$template_name] = $default_param; } } } } elseif ($implemented_interface_storage->template_type_extends) { $storage->template_type_extends = \array_merge($storage->template_type_extends ?: [], $implemented_interface_storage->template_type_extends); } $extra_interfaces = \array_merge($extra_interfaces, $implemented_interface_storage->parent_interfaces); } $storage->class_implements = \array_merge($storage->class_implements, $extra_interfaces); $interface_method_implementers = []; foreach ($storage->class_implements as $implemented_interface_lc => $_) { try { $implemented_interface = \strtolower($this->classlikes->getUnAliasedName($implemented_interface_lc)); $implemented_interface_storage = $storage_provider->get($implemented_interface); } catch (\InvalidArgumentException $e) { continue; } $implemented_interface_storage->dependent_classlikes[\strtolower($storage->name)] = \true; foreach ($implemented_interface_storage->methods as $method_name => $method) { if ($method->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC) { $interface_method_implementers[$method_name][] = new \Psalm\Internal\MethodIdentifier($implemented_interface_storage->name, $method_name); } } } foreach ($interface_method_implementers as $method_name => $interface_method_ids) { if (\count($interface_method_ids) === 1) { if (isset($storage->methods[$method_name])) { $method_storage = $storage->methods[$method_name]; if ($method_storage->signature_return_type && !$method_storage->signature_return_type->isVoid() && $method_storage->return_type === $method_storage->signature_return_type) { $interface_fqcln = $interface_method_ids[0]->fq_class_name; $interface_storage = $storage_provider->get($interface_fqcln); if (isset($interface_storage->methods[$method_name])) { $interface_method_storage = $interface_storage->methods[$method_name]; if ($interface_method_storage->throws && (!$method_storage->throws || $method_storage->inheritdoc)) { $method_storage->throws += $interface_method_storage->throws; } if ($interface_method_storage->return_type && $interface_method_storage->signature_return_type && $interface_method_storage->return_type !== $interface_method_storage->signature_return_type && \Psalm\Internal\Type\Comparator\UnionTypeComparator::isSimplyContainedBy($interface_method_storage->signature_return_type, $method_storage->signature_return_type)) { $method_storage->return_type = $interface_method_storage->return_type; $method_storage->inherited_return_type = \true; } } } } } foreach ($interface_method_ids as $interface_method_id) { $storage->overridden_method_ids[$method_name][$interface_method_id->fq_class_name] = $interface_method_id; } } } /** * @param array $dependent_file_paths */ private function populateFileStorage(\Psalm\Storage\FileStorage $storage, array $dependent_file_paths = []) : void { if ($storage->populated) { return; } $file_path_lc = \strtolower($storage->file_path); if (isset($dependent_file_paths[$file_path_lc])) { return; } $dependent_file_paths[$file_path_lc] = \true; $all_required_file_paths = $storage->required_file_paths; foreach ($storage->required_file_paths as $included_file_path => $_) { try { $included_file_storage = $this->file_storage_provider->get($included_file_path); } catch (\InvalidArgumentException $e) { continue; } $this->populateFileStorage($included_file_storage, $dependent_file_paths); $all_required_file_paths = $all_required_file_paths + $included_file_storage->required_file_paths; } foreach ($all_required_file_paths as $included_file_path => $_) { try { $included_file_storage = $this->file_storage_provider->get($included_file_path); } catch (\InvalidArgumentException $e) { continue; } $storage->declaring_function_ids = \array_merge($included_file_storage->declaring_function_ids, $storage->declaring_function_ids); $storage->declaring_constants = \array_merge($included_file_storage->declaring_constants, $storage->declaring_constants); } foreach ($storage->referenced_classlikes as $fq_class_name) { try { $classlike_storage = $this->classlike_storage_provider->get($fq_class_name); } catch (\InvalidArgumentException $e) { continue; } if (!$classlike_storage->location) { continue; } try { $included_file_storage = $this->file_storage_provider->get($classlike_storage->location->file_path); } catch (\InvalidArgumentException $e) { continue; } foreach ($classlike_storage->used_traits as $used_trait) { try { $trait_storage = $this->classlike_storage_provider->get($used_trait); } catch (\InvalidArgumentException $e) { continue; } if (!$trait_storage->location) { continue; } try { $included_trait_file_storage = $this->file_storage_provider->get($trait_storage->location->file_path); } catch (\InvalidArgumentException $e) { continue; } $storage->declaring_function_ids = \array_merge($included_trait_file_storage->declaring_function_ids, $storage->declaring_function_ids); } $storage->declaring_function_ids = \array_merge($included_file_storage->declaring_function_ids, $storage->declaring_function_ids); } $storage->required_file_paths = $all_required_file_paths; foreach ($all_required_file_paths as $required_file_path) { try { $required_file_storage = $this->file_storage_provider->get($required_file_path); } catch (\InvalidArgumentException $e) { continue; } $required_file_storage->required_by_file_paths += [$file_path_lc => $storage->file_path]; } foreach ($storage->required_classes as $required_classlike) { try { $classlike_storage = $this->classlike_storage_provider->get($required_classlike); } catch (\InvalidArgumentException $e) { continue; } if (!$classlike_storage->location) { continue; } try { $required_file_storage = $this->file_storage_provider->get($classlike_storage->location->file_path); } catch (\InvalidArgumentException $e) { continue; } $required_file_storage->required_by_file_paths += [$file_path_lc => $storage->file_path]; } $storage->populated = \true; } private function convertPhpStormGenericToPsalmGeneric(\Psalm\Type\Union $candidate, bool $is_property = \false) : void { $atomic_types = $candidate->getAtomicTypes(); if (isset($atomic_types['array']) && \count($atomic_types) > 1 && !isset($atomic_types['null'])) { $iterator_name = null; $generic_params = null; $iterator_key = null; try { foreach ($atomic_types as $type_key => $type) { if ($type instanceof \Psalm\Type\Atomic\TIterable || $type instanceof \Psalm\Type\Atomic\TNamedObject && (!$type->from_docblock || $is_property) && (\strtolower($type->value) === 'traversable' || $this->classlikes->interfaceExtends($type->value, 'Traversable') || $this->classlikes->classImplements($type->value, 'Traversable'))) { $iterator_name = $type->value; $iterator_key = $type_key; } elseif ($type instanceof \Psalm\Type\Atomic\TArray) { $generic_params = $type->type_params; } } } catch (\InvalidArgumentException $e) { // ignore class-not-found issues } if ($iterator_name && $iterator_key && $generic_params) { if ($iterator_name === 'iterable') { $generic_iterator = new \Psalm\Type\Atomic\TIterable($generic_params); } else { if (\strtolower($iterator_name) === 'generator') { $generic_params[] = \Psalm\Type::getMixed(); $generic_params[] = \Psalm\Type::getMixed(); } $generic_iterator = new \Psalm\Type\Atomic\TGenericObject($iterator_name, $generic_params); } $candidate->removeType('array'); $candidate->removeType($iterator_key); $candidate->addType($generic_iterator); } } } protected function inheritMethodsFromParent(\Psalm\Storage\ClassLikeStorage $storage, \Psalm\Storage\ClassLikeStorage $parent_storage) : void { $fq_class_name = $storage->name; $fq_class_name_lc = \strtolower($fq_class_name); if ($parent_storage->sealed_methods) { $storage->sealed_methods = \true; } // register where they appear (can never be in a trait) foreach ($parent_storage->appearing_method_ids as $method_name_lc => $appearing_method_id) { $aliased_method_names = [$method_name_lc]; if ($parent_storage->is_trait && $storage->trait_alias_map) { $aliased_method_names = \array_merge($aliased_method_names, \array_keys($storage->trait_alias_map, $method_name_lc, \true)); } foreach ($aliased_method_names as $aliased_method_name) { if (isset($storage->appearing_method_ids[$aliased_method_name])) { continue; } $implemented_method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, $aliased_method_name); $storage->appearing_method_ids[$aliased_method_name] = $parent_storage->is_trait ? $implemented_method_id : $appearing_method_id; $this_method_id = $fq_class_name_lc . '::' . $method_name_lc; if (isset($storage->methods[$aliased_method_name])) { $storage->potential_declaring_method_ids[$aliased_method_name] = [$this_method_id => \true]; } else { if (isset($parent_storage->potential_declaring_method_ids[$aliased_method_name])) { $storage->potential_declaring_method_ids[$aliased_method_name] = $parent_storage->potential_declaring_method_ids[$aliased_method_name]; } $storage->potential_declaring_method_ids[$aliased_method_name][$this_method_id] = \true; $parent_method_id = \strtolower($parent_storage->name) . '::' . $method_name_lc; $storage->potential_declaring_method_ids[$aliased_method_name][$parent_method_id] = \true; } } } // register where they're declared foreach ($parent_storage->inheritable_method_ids as $method_name_lc => $declaring_method_id) { if ($method_name_lc !== '__construct' || $parent_storage->preserve_constructor_signature) { if ($parent_storage->is_trait) { $declaring_class = $declaring_method_id->fq_class_name; $declaring_class_storage = $this->classlike_storage_provider->get($declaring_class); if (isset($declaring_class_storage->methods[$method_name_lc]) && $declaring_class_storage->methods[$method_name_lc]->abstract) { $storage->overridden_method_ids[$method_name_lc][$declaring_method_id->fq_class_name] = $declaring_method_id; } } else { $storage->overridden_method_ids[$method_name_lc][$declaring_method_id->fq_class_name] = $declaring_method_id; } if (isset($parent_storage->overridden_method_ids[$method_name_lc]) && isset($storage->overridden_method_ids[$method_name_lc])) { $storage->overridden_method_ids[$method_name_lc] += $parent_storage->overridden_method_ids[$method_name_lc]; } } $aliased_method_names = [$method_name_lc]; if ($parent_storage->is_trait && $storage->trait_alias_map) { $aliased_method_names = \array_merge($aliased_method_names, \array_keys($storage->trait_alias_map, $method_name_lc, \true)); } foreach ($aliased_method_names as $aliased_method_name) { if (isset($storage->declaring_method_ids[$aliased_method_name])) { $implementing_method_id = $storage->declaring_method_ids[$aliased_method_name]; $implementing_class_storage = $this->classlike_storage_provider->get($implementing_method_id->fq_class_name); if (!$implementing_class_storage->methods[$implementing_method_id->method_name]->abstract || !empty($storage->methods[$implementing_method_id->method_name]->abstract)) { continue; } } /** @psalm-suppress PropertyTypeCoercion */ $storage->declaring_method_ids[$aliased_method_name] = $declaring_method_id; /** @psalm-suppress PropertyTypeCoercion */ $storage->inheritable_method_ids[$aliased_method_name] = $declaring_method_id; } } } private function inheritPropertiesFromParent(\Psalm\Storage\ClassLikeStorage $storage, \Psalm\Storage\ClassLikeStorage $parent_storage) : void { if ($parent_storage->sealed_properties) { $storage->sealed_properties = \true; } // register where they appear (can never be in a trait) foreach ($parent_storage->appearing_property_ids as $property_name => $appearing_property_id) { if (isset($storage->appearing_property_ids[$property_name])) { continue; } if (!$parent_storage->is_trait && isset($parent_storage->properties[$property_name]) && $parent_storage->properties[$property_name]->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { continue; } $implemented_property_id = $storage->name . '::$' . $property_name; $storage->appearing_property_ids[$property_name] = $parent_storage->is_trait ? $implemented_property_id : $appearing_property_id; } // register where they're declared foreach ($parent_storage->declaring_property_ids as $property_name => $declaring_property_class) { if (isset($storage->declaring_property_ids[$property_name])) { continue; } if (!$parent_storage->is_trait && isset($parent_storage->properties[$property_name]) && $parent_storage->properties[$property_name]->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { continue; } $storage->declaring_property_ids[$property_name] = $declaring_property_class; } // register where they're declared foreach ($parent_storage->inheritable_property_ids as $property_name => $inheritable_property_id) { if (!$parent_storage->is_trait && isset($parent_storage->properties[$property_name]) && $parent_storage->properties[$property_name]->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { continue; } if (!$parent_storage->is_trait) { $storage->overridden_property_ids[$property_name][] = $inheritable_property_id; } $storage->inheritable_property_ids[$property_name] = $inheritable_property_id; } } } */ private $existing_classlikes_lc = []; /** * @var array */ private $existing_classes_lc = []; /** * @var array */ private $existing_classes = []; /** * @var array */ private $existing_interfaces_lc = []; /** * @var array */ private $existing_interfaces = []; /** * @var array */ private $existing_traits_lc = []; /** * @var array */ private $existing_traits = []; /** * @var array */ private $classlike_aliases = []; /** * @var array */ private $trait_nodes = []; /** * @var bool */ public $collect_references = \false; /** * @var bool */ public $collect_locations = \false; /** * @var StatementsProvider */ private $statements_provider; /** * @var Config */ private $config; /** * @var Scanner */ private $scanner; public function __construct(\Psalm\Config $config, \Psalm\Internal\Provider\ClassLikeStorageProvider $storage_provider, \Psalm\Internal\Provider\FileReferenceProvider $file_reference_provider, \Psalm\Internal\Provider\StatementsProvider $statements_provider, \Psalm\Internal\Codebase\Scanner $scanner) { $this->config = $config; $this->classlike_storage_provider = $storage_provider; $this->file_reference_provider = $file_reference_provider; $this->statements_provider = $statements_provider; $this->scanner = $scanner; $this->collectPredefinedClassLikes(); } private function collectPredefinedClassLikes() : void { /** @var array */ $predefined_classes = \get_declared_classes(); foreach ($predefined_classes as $predefined_class) { $predefined_class = \preg_replace('/^\\\\/', '', $predefined_class); /** @psalm-suppress ArgumentTypeCoercion */ $reflection_class = new \ReflectionClass($predefined_class); if (!$reflection_class->isUserDefined()) { $predefined_class_lc = \strtolower($predefined_class); $this->existing_classlikes_lc[$predefined_class_lc] = \true; $this->existing_classes_lc[$predefined_class_lc] = \true; $this->existing_classes[$predefined_class] = \true; } } /** @var array */ $predefined_interfaces = \get_declared_interfaces(); foreach ($predefined_interfaces as $predefined_interface) { $predefined_interface = \preg_replace('/^\\\\/', '', $predefined_interface); /** @psalm-suppress ArgumentTypeCoercion */ $reflection_class = new \ReflectionClass($predefined_interface); if (!$reflection_class->isUserDefined()) { $predefined_interface_lc = \strtolower($predefined_interface); $this->existing_classlikes_lc[$predefined_interface_lc] = \true; $this->existing_interfaces_lc[$predefined_interface_lc] = \true; $this->existing_interfaces[$predefined_interface] = \true; } } } public function addFullyQualifiedClassName(string $fq_class_name, ?string $file_path = null) : void { $fq_class_name_lc = \strtolower($fq_class_name); $this->existing_classlikes_lc[$fq_class_name_lc] = \true; $this->existing_classes_lc[$fq_class_name_lc] = \true; $this->existing_traits_lc[$fq_class_name_lc] = \false; $this->existing_interfaces_lc[$fq_class_name_lc] = \false; $this->existing_classes[$fq_class_name] = \true; if ($file_path) { $this->scanner->setClassLikeFilePath($fq_class_name_lc, $file_path); } } public function addFullyQualifiedInterfaceName(string $fq_class_name, ?string $file_path = null) : void { $fq_class_name_lc = \strtolower($fq_class_name); $this->existing_classlikes_lc[$fq_class_name_lc] = \true; $this->existing_interfaces_lc[$fq_class_name_lc] = \true; $this->existing_classes_lc[$fq_class_name_lc] = \false; $this->existing_traits_lc[$fq_class_name_lc] = \false; $this->existing_interfaces[$fq_class_name] = \true; if ($file_path) { $this->scanner->setClassLikeFilePath($fq_class_name_lc, $file_path); } } public function addFullyQualifiedTraitName(string $fq_class_name, ?string $file_path = null) : void { $fq_class_name_lc = \strtolower($fq_class_name); $this->existing_classlikes_lc[$fq_class_name_lc] = \true; $this->existing_traits_lc[$fq_class_name_lc] = \true; $this->existing_classes_lc[$fq_class_name_lc] = \false; $this->existing_interfaces_lc[$fq_class_name_lc] = \false; $this->existing_traits[$fq_class_name] = \true; if ($file_path) { $this->scanner->setClassLikeFilePath($fq_class_name_lc, $file_path); } } public function addFullyQualifiedClassLikeName(string $fq_class_name_lc, ?string $file_path = null) : void { if ($file_path) { $this->scanner->setClassLikeFilePath($fq_class_name_lc, $file_path); } } /** * @return list */ public function getMatchingClassLikeNames(string $stub) : array { $matching_classes = []; if ($stub[0] === '*') { $stub = \substr($stub, 1); } $stub = \strtolower($stub); foreach ($this->existing_classes as $fq_classlike_name => $found) { if (!$found) { continue; } if (\preg_match('@(^|\\\\)' . $stub . '.*@i', $fq_classlike_name)) { $matching_classes[] = $fq_classlike_name; } } foreach ($this->existing_interfaces as $fq_classlike_name => $found) { if (!$found) { continue; } if (\preg_match('@(^|\\\\)' . $stub . '.*@i', $fq_classlike_name)) { $matching_classes[] = $fq_classlike_name; } } return $matching_classes; } public function hasFullyQualifiedClassName(string $fq_class_name, ?\Psalm\CodeLocation $code_location = null, ?string $calling_fq_class_name = null, ?string $calling_method_id = null) : bool { $fq_class_name_lc = \strtolower($fq_class_name); if (isset($this->classlike_aliases[$fq_class_name_lc])) { $fq_class_name_lc = \strtolower($this->classlike_aliases[$fq_class_name_lc]); } if ($code_location) { if ($calling_method_id) { $this->file_reference_provider->addMethodReferenceToClass($calling_method_id, $fq_class_name_lc); } elseif (!$calling_fq_class_name || \strtolower($calling_fq_class_name) !== $fq_class_name_lc) { $this->file_reference_provider->addNonMethodReferenceToClass($code_location->file_path, $fq_class_name_lc); if ($calling_fq_class_name) { $class_storage = $this->classlike_storage_provider->get($calling_fq_class_name); if ($class_storage->location && $class_storage->location->file_path !== $code_location->file_path) { $this->file_reference_provider->addNonMethodReferenceToClass($class_storage->location->file_path, $fq_class_name_lc); } } } } if (!isset($this->existing_classes_lc[$fq_class_name_lc]) || !$this->existing_classes_lc[$fq_class_name_lc] || !$this->classlike_storage_provider->has($fq_class_name_lc)) { if ((!isset($this->existing_classes_lc[$fq_class_name_lc]) || $this->existing_classes_lc[$fq_class_name_lc]) && !$this->classlike_storage_provider->has($fq_class_name_lc)) { if (!isset($this->existing_classes_lc[$fq_class_name_lc])) { $this->existing_classes_lc[$fq_class_name_lc] = \false; return \false; } return $this->existing_classes_lc[$fq_class_name_lc]; } return \false; } if ($this->collect_locations && $code_location) { $this->file_reference_provider->addCallingLocationForClass($code_location, \strtolower($fq_class_name)); } return \true; } public function hasFullyQualifiedInterfaceName(string $fq_class_name, ?\Psalm\CodeLocation $code_location = null, ?string $calling_fq_class_name = null, ?string $calling_method_id = null) : bool { $fq_class_name_lc = \strtolower($fq_class_name); if (isset($this->classlike_aliases[$fq_class_name_lc])) { $fq_class_name_lc = \strtolower($this->classlike_aliases[$fq_class_name_lc]); } if (!isset($this->existing_interfaces_lc[$fq_class_name_lc]) || !$this->existing_interfaces_lc[$fq_class_name_lc] || !$this->classlike_storage_provider->has($fq_class_name_lc)) { if ((!isset($this->existing_classes_lc[$fq_class_name_lc]) || $this->existing_classes_lc[$fq_class_name_lc]) && !$this->classlike_storage_provider->has($fq_class_name_lc)) { if (!isset($this->existing_interfaces_lc[$fq_class_name_lc])) { $this->existing_interfaces_lc[$fq_class_name_lc] = \false; return \false; } return $this->existing_interfaces_lc[$fq_class_name_lc]; } return \false; } if ($this->collect_references && $code_location) { if ($calling_method_id) { $this->file_reference_provider->addMethodReferenceToClass($calling_method_id, $fq_class_name_lc); } else { $this->file_reference_provider->addNonMethodReferenceToClass($code_location->file_path, $fq_class_name_lc); if ($calling_fq_class_name) { $class_storage = $this->classlike_storage_provider->get($calling_fq_class_name); if ($class_storage->location && $class_storage->location->file_path !== $code_location->file_path) { $this->file_reference_provider->addNonMethodReferenceToClass($class_storage->location->file_path, $fq_class_name_lc); } } } } if ($this->collect_locations && $code_location) { $this->file_reference_provider->addCallingLocationForClass($code_location, \strtolower($fq_class_name)); } return \true; } public function hasFullyQualifiedTraitName(string $fq_class_name, ?\Psalm\CodeLocation $code_location = null) : bool { $fq_class_name_lc = \strtolower($fq_class_name); if (isset($this->classlike_aliases[$fq_class_name_lc])) { $fq_class_name_lc = \strtolower($this->classlike_aliases[$fq_class_name_lc]); } if (!isset($this->existing_traits_lc[$fq_class_name_lc]) || !$this->existing_traits_lc[$fq_class_name_lc]) { return \false; } if ($this->collect_references && $code_location) { $this->file_reference_provider->addNonMethodReferenceToClass($code_location->file_path, $fq_class_name_lc); } return \true; } /** * Check whether a class/interface exists */ public function classOrInterfaceExists(string $fq_class_name, ?\Psalm\CodeLocation $code_location = null, ?string $calling_fq_class_name = null, ?string $calling_method_id = null) : bool { if (!$this->classExists($fq_class_name, $code_location, $calling_fq_class_name, $calling_method_id) && !$this->interfaceExists($fq_class_name, $code_location, $calling_fq_class_name, $calling_method_id)) { return \false; } return \true; } /** * Determine whether or not a given class exists */ public function classExists(string $fq_class_name, ?\Psalm\CodeLocation $code_location = null, ?string $calling_fq_class_name = null, ?string $calling_method_id = null) : bool { if (isset(\Psalm\Internal\Analyzer\ClassLikeAnalyzer::SPECIAL_TYPES[$fq_class_name])) { return \false; } if ($fq_class_name === 'Generator') { return \true; } return $this->hasFullyQualifiedClassName($fq_class_name, $code_location, $calling_fq_class_name, $calling_method_id); } /** * Determine whether or not a class extends a parent * * @throws UnpopulatedClasslikeException when called on unpopulated class * @throws \InvalidArgumentException when class does not exist */ public function classExtends(string $fq_class_name, string $possible_parent, bool $from_api = \false) : bool { $fq_class_name_lc = \strtolower($fq_class_name); if ($fq_class_name_lc === 'generator') { return \false; } $fq_class_name = $this->classlike_aliases[$fq_class_name_lc] ?? $fq_class_name; $class_storage = $this->classlike_storage_provider->get($fq_class_name_lc); if ($from_api && !$class_storage->populated) { throw new \Psalm\Exception\UnpopulatedClasslikeException($fq_class_name); } return isset($class_storage->parent_classes[\strtolower($possible_parent)]); } /** * Check whether a class implements an interface */ public function classImplements(string $fq_class_name, string $interface) : bool { $interface_id = \strtolower($interface); $fq_class_name = \strtolower($fq_class_name); if ($interface_id === 'callable' && $fq_class_name === 'closure') { return \true; } if ($interface_id === 'traversable' && $fq_class_name === 'generator') { return \true; } if ($interface_id === 'traversable' && $fq_class_name === 'iterator') { return \true; } if (isset(\Psalm\Internal\Analyzer\ClassLikeAnalyzer::SPECIAL_TYPES[$interface_id]) || isset(\Psalm\Internal\Analyzer\ClassLikeAnalyzer::SPECIAL_TYPES[$fq_class_name])) { return \false; } if (isset($this->classlike_aliases[$fq_class_name])) { $fq_class_name = $this->classlike_aliases[$fq_class_name]; } $class_storage = $this->classlike_storage_provider->get($fq_class_name); return isset($class_storage->class_implements[$interface_id]); } public function interfaceExists(string $fq_interface_name, ?\Psalm\CodeLocation $code_location = null, ?string $calling_fq_class_name = null, ?string $calling_method_id = null) : bool { if (isset(\Psalm\Internal\Analyzer\ClassLikeAnalyzer::SPECIAL_TYPES[\strtolower($fq_interface_name)])) { return \false; } return $this->hasFullyQualifiedInterfaceName($fq_interface_name, $code_location, $calling_fq_class_name, $calling_method_id); } public function interfaceExtends(string $interface_name, string $possible_parent) : bool { return isset($this->getParentInterfaces($interface_name)[\strtolower($possible_parent)]); } /** * @return array all interfaces extended by $interface_name */ public function getParentInterfaces(string $fq_interface_name) : array { $fq_interface_name = \strtolower($fq_interface_name); $storage = $this->classlike_storage_provider->get($fq_interface_name); return $storage->parent_interfaces; } public function traitExists(string $fq_trait_name, ?\Psalm\CodeLocation $code_location = null) : bool { return $this->hasFullyQualifiedTraitName($fq_trait_name, $code_location); } /** * Determine whether or not a class has the correct casing */ public function classHasCorrectCasing(string $fq_class_name) : bool { if ($fq_class_name === 'Generator') { return \true; } if (isset($this->classlike_aliases[\strtolower($fq_class_name)])) { return \true; } return isset($this->existing_classes[$fq_class_name]); } public function interfaceHasCorrectCasing(string $fq_interface_name) : bool { if (isset($this->classlike_aliases[\strtolower($fq_interface_name)])) { return \true; } return isset($this->existing_interfaces[$fq_interface_name]); } public function traitHasCorrectCase(string $fq_trait_name) : bool { if (isset($this->classlike_aliases[\strtolower($fq_trait_name)])) { return \true; } return isset($this->existing_traits[$fq_trait_name]); } /** * @param lowercase-string $fq_class_name */ public function isUserDefined(string $fq_class_name) : bool { return $this->classlike_storage_provider->get($fq_class_name)->user_defined; } public function getTraitNode(string $fq_trait_name) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_ { $fq_trait_name_lc = \strtolower($fq_trait_name); if (isset($this->trait_nodes[$fq_trait_name_lc])) { return $this->trait_nodes[$fq_trait_name_lc]; } $storage = $this->classlike_storage_provider->get($fq_trait_name); if (!$storage->location) { throw new \UnexpectedValueException('Storage should exist for ' . $fq_trait_name); } $file_statements = $this->statements_provider->getStatementsForFile($storage->location->file_path, '7.4'); $trait_finder = new \Psalm\Internal\PhpVisitor\TraitFinder($fq_trait_name); $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $traverser->addVisitor($trait_finder); $traverser->traverse($file_statements); $trait_node = $trait_finder->getNode(); if ($trait_node) { $this->trait_nodes[$fq_trait_name_lc] = $trait_node; return $trait_node; } throw new \UnexpectedValueException('Could not locate trait statement'); } /** * @param lowercase-string $alias_name */ public function addClassAlias(string $fq_class_name, string $alias_name) : void { $this->classlike_aliases[$alias_name] = $fq_class_name; } public function getUnAliasedName(string $alias_name) : string { $alias_name_lc = \strtolower($alias_name); if ($this->existing_classlikes_lc[$alias_name_lc] ?? \false) { return $alias_name; } return $this->classlike_aliases[$alias_name_lc] ?? $alias_name; } public function consolidateAnalyzedData(\Psalm\Internal\Codebase\Methods $methods, ?\Psalm\Progress\Progress $progress, bool $find_unused_code) : void { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } $progress->debug('Checking class references' . \PHP_EOL); $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); foreach ($this->existing_classlikes_lc as $fq_class_name_lc => $_) { try { $classlike_storage = $this->classlike_storage_provider->get($fq_class_name_lc); } catch (\InvalidArgumentException $e) { continue; } if ($classlike_storage->location && $this->config->isInProjectDirs($classlike_storage->location->file_path) && !$classlike_storage->is_trait) { if ($find_unused_code) { if (!$this->file_reference_provider->isClassReferenced($fq_class_name_lc)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnusedClass('Class ' . $classlike_storage->name . ' is never used', $classlike_storage->location, $classlike_storage->name), $classlike_storage->suppressed_issues)) { // fall through } } else { $this->checkMethodReferences($classlike_storage, $methods); $this->checkPropertyReferences($classlike_storage); } } $this->findPossibleMethodParamTypes($classlike_storage); if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['MissingImmutableAnnotation']) && !isset($codebase->analyzer->mutable_classes[$fq_class_name_lc]) && !$classlike_storage->external_mutation_free && $classlike_storage->properties && isset($classlike_storage->methods['__construct'])) { $stmts = $codebase->getStatementsForFile($classlike_storage->location->file_path); foreach ($stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { foreach ($stmt->stmts as $namespace_stmt) { if ($namespace_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ && \strtolower((string) $stmt->name . '\\' . (string) $namespace_stmt->name) === $fq_class_name_lc) { self::makeImmutable($namespace_stmt, $project_analyzer, $classlike_storage->location->file_path); } } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ && \strtolower((string) $stmt->name) === $fq_class_name_lc) { self::makeImmutable($stmt, $project_analyzer, $classlike_storage->location->file_path); } } } } } } public static function makeImmutable(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ $class_stmt, \Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, string $file_path) : void { $manipulator = \Psalm\Internal\FileManipulation\ClassDocblockManipulator::getForClass($project_analyzer, $file_path, $class_stmt); $manipulator->makeImmutable(); } public function moveMethods(\Psalm\Internal\Codebase\Methods $methods, ?\Psalm\Progress\Progress $progress = null) : void { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); if (!$codebase->methods_to_move) { return; } $progress->debug('Refactoring methods ' . \PHP_EOL); $code_migrations = []; foreach ($codebase->methods_to_move as $source => $destination) { $source_parts = \explode('::', $source); try { $source_method_storage = $methods->getStorage(new \Psalm\Internal\MethodIdentifier(...$source_parts)); } catch (\InvalidArgumentException $e) { continue; } [$destination_fq_class_name, $destination_name] = \explode('::', $destination); try { $classlike_storage = $this->classlike_storage_provider->get($destination_fq_class_name); } catch (\InvalidArgumentException $e) { continue; } if ($classlike_storage->stmt_location && $this->config->isInProjectDirs($classlike_storage->stmt_location->file_path) && $source_method_storage->stmt_location && $source_method_storage->stmt_location->file_path && $source_method_storage->location) { $new_class_bounds = $classlike_storage->stmt_location->getSnippetBounds(); $old_method_bounds = $source_method_storage->stmt_location->getSnippetBounds(); $old_method_name_bounds = $source_method_storage->location->getSelectionBounds(); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source_method_storage->stmt_location->file_path, [new \Psalm\FileManipulation($old_method_name_bounds[0], $old_method_name_bounds[1], $destination_name)]); $selection = $classlike_storage->stmt_location->getSnippet(); $insert_pos = \strrpos($selection, "\n", -1); if (!$insert_pos) { $insert_pos = \strlen($selection) - 1; } else { ++$insert_pos; } $code_migrations[] = new \Psalm\Internal\FileManipulation\CodeMigration($source_method_storage->stmt_location->file_path, $old_method_bounds[0], $old_method_bounds[1], $classlike_storage->stmt_location->file_path, $new_class_bounds[0] + $insert_pos); } } \Psalm\Internal\FileManipulation\FileManipulationBuffer::addCodeMigrations($code_migrations); } public function moveProperties(\Psalm\Internal\Codebase\Properties $properties, ?\Psalm\Progress\Progress $progress = null) : void { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); if (!$codebase->properties_to_move) { return; } $progress->debug('Refacting properties ' . \PHP_EOL); $code_migrations = []; foreach ($codebase->properties_to_move as $source => $destination) { try { $source_property_storage = $properties->getStorage($source); } catch (\InvalidArgumentException $e) { continue; } [$source_fq_class_name] = \explode('::$', $source); [$destination_fq_class_name, $destination_name] = \explode('::$', $destination); $source_classlike_storage = $this->classlike_storage_provider->get($source_fq_class_name); $destination_classlike_storage = $this->classlike_storage_provider->get($destination_fq_class_name); if ($destination_classlike_storage->stmt_location && $this->config->isInProjectDirs($destination_classlike_storage->stmt_location->file_path) && $source_property_storage->stmt_location && $source_property_storage->stmt_location->file_path && $source_property_storage->location) { if ($source_property_storage->type && $source_property_storage->type_location && $source_property_storage->type_location !== $source_property_storage->signature_type_location) { $bounds = $source_property_storage->type_location->getSelectionBounds(); $replace_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $source_property_storage->type, $source_classlike_storage->name, $source_classlike_storage->name, $source_classlike_storage->parent_class); $this->airliftClassDefinedDocblockType($replace_type, $destination_fq_class_name, $source_property_storage->stmt_location->file_path, $bounds[0], $bounds[1]); } $new_class_bounds = $destination_classlike_storage->stmt_location->getSnippetBounds(); $old_property_bounds = $source_property_storage->stmt_location->getSnippetBounds(); $old_property_name_bounds = $source_property_storage->location->getSelectionBounds(); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source_property_storage->stmt_location->file_path, [new \Psalm\FileManipulation($old_property_name_bounds[0], $old_property_name_bounds[1], '$' . $destination_name)]); $selection = $destination_classlike_storage->stmt_location->getSnippet(); $insert_pos = \strrpos($selection, "\n", -1); if (!$insert_pos) { $insert_pos = \strlen($selection) - 1; } else { ++$insert_pos; } $code_migrations[] = new \Psalm\Internal\FileManipulation\CodeMigration($source_property_storage->stmt_location->file_path, $old_property_bounds[0], $old_property_bounds[1], $destination_classlike_storage->stmt_location->file_path, $new_class_bounds[0] + $insert_pos); } } \Psalm\Internal\FileManipulation\FileManipulationBuffer::addCodeMigrations($code_migrations); } public function moveClassConstants(?\Psalm\Progress\Progress $progress = null) : void { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); if (!$codebase->class_constants_to_move) { return; } $progress->debug('Refacting constants ' . \PHP_EOL); $code_migrations = []; foreach ($codebase->class_constants_to_move as $source => $destination) { [$source_fq_class_name, $source_const_name] = \explode('::', $source); [$destination_fq_class_name, $destination_name] = \explode('::', $destination); $source_classlike_storage = $this->classlike_storage_provider->get($source_fq_class_name); $destination_classlike_storage = $this->classlike_storage_provider->get($destination_fq_class_name); $constant_storage = $source_classlike_storage->constants[$source_const_name]; $source_const_stmt_location = $constant_storage->stmt_location; $source_const_location = $constant_storage->location; if (!$source_const_location || !$source_const_stmt_location) { continue; } if ($destination_classlike_storage->stmt_location && $this->config->isInProjectDirs($destination_classlike_storage->stmt_location->file_path) && $source_const_stmt_location->file_path) { $new_class_bounds = $destination_classlike_storage->stmt_location->getSnippetBounds(); $old_const_bounds = $source_const_stmt_location->getSnippetBounds(); $old_const_name_bounds = $source_const_location->getSelectionBounds(); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source_const_stmt_location->file_path, [new \Psalm\FileManipulation($old_const_name_bounds[0], $old_const_name_bounds[1], $destination_name)]); $selection = $destination_classlike_storage->stmt_location->getSnippet(); $insert_pos = \strrpos($selection, "\n", -1); if (!$insert_pos) { $insert_pos = \strlen($selection) - 1; } else { ++$insert_pos; } $code_migrations[] = new \Psalm\Internal\FileManipulation\CodeMigration($source_const_stmt_location->file_path, $old_const_bounds[0], $old_const_bounds[1], $destination_classlike_storage->stmt_location->file_path, $new_class_bounds[0] + $insert_pos); } } \Psalm\Internal\FileManipulation\FileManipulationBuffer::addCodeMigrations($code_migrations); } /** * @param lowercase-string|null $calling_method_id */ public function handleClassLikeReferenceInMigration(\Psalm\Codebase $codebase, \Psalm\StatementsSource $source, \_HumbugBoxd02f763d3c56\PhpParser\Node $class_name_node, string $fq_class_name, ?string $calling_method_id, bool $force_change = \false, bool $was_self = \false) : bool { $calling_fq_class_name = $source->getFQCLN(); // if we're inside a moved class static method if ($codebase->methods_to_move && $calling_fq_class_name && $calling_method_id && isset($codebase->methods_to_move[$calling_method_id])) { $destination_class = \explode('::', $codebase->methods_to_move[$calling_method_id])[0]; $intended_fq_class_name = \strtolower($calling_fq_class_name) === \strtolower($fq_class_name) && isset($codebase->classes_to_move[\strtolower($calling_fq_class_name)]) ? $destination_class : $fq_class_name; $this->airliftClassLikeReference($intended_fq_class_name, $destination_class, $source->getFilePath(), (int) $class_name_node->getAttribute('startFilePos'), (int) $class_name_node->getAttribute('endFilePos') + 1, $class_name_node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Class_, $was_self); return \true; } // if we're outside a moved class, but we're changing all references to a class if (isset($codebase->class_transforms[\strtolower($fq_class_name)])) { $new_fq_class_name = $codebase->class_transforms[\strtolower($fq_class_name)]; $file_manipulations = []; if ($class_name_node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $destination_parts = \explode('\\', $new_fq_class_name); $destination_class_name = \array_pop($destination_parts); $file_manipulations = []; $file_manipulations[] = new \Psalm\FileManipulation((int) $class_name_node->getAttribute('startFilePos'), (int) $class_name_node->getAttribute('endFilePos') + 1, $destination_class_name); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source->getFilePath(), $file_manipulations); return \true; } $uses_flipped = $source->getAliasedClassesFlipped(); $uses_flipped_replaceable = $source->getAliasedClassesFlippedReplaceable(); $old_fq_class_name = \strtolower($fq_class_name); $migrated_source_fqcln = $calling_fq_class_name; if ($calling_fq_class_name && isset($codebase->class_transforms[\strtolower($calling_fq_class_name)])) { $migrated_source_fqcln = $codebase->class_transforms[\strtolower($calling_fq_class_name)]; } $source_namespace = $source->getNamespace(); if ($migrated_source_fqcln && $calling_fq_class_name !== $migrated_source_fqcln) { $new_source_parts = \explode('\\', $migrated_source_fqcln, -1); $source_namespace = \implode('\\', $new_source_parts); } if (isset($uses_flipped_replaceable[$old_fq_class_name])) { $alias = $uses_flipped_replaceable[$old_fq_class_name]; unset($uses_flipped[$old_fq_class_name]); $old_class_name_parts = \explode('\\', $old_fq_class_name); $old_class_name = \end($old_class_name_parts); if ($old_class_name === \strtolower($alias)) { $new_class_name_parts = \explode('\\', $new_fq_class_name); $new_class_name = \end($new_class_name_parts); $uses_flipped[\strtolower($new_fq_class_name)] = $new_class_name; } else { $uses_flipped[\strtolower($new_fq_class_name)] = $alias; } } $file_manipulations[] = new \Psalm\FileManipulation((int) $class_name_node->getAttribute('startFilePos'), (int) $class_name_node->getAttribute('endFilePos') + 1, \Psalm\Type::getStringFromFQCLN($new_fq_class_name, $source_namespace, $uses_flipped, $migrated_source_fqcln, $was_self) . ($class_name_node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Class_ ? '::class' : '')); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source->getFilePath(), $file_manipulations); return \true; } // if we're inside a moved class (could be a method, could be a property/class const default) if ($codebase->classes_to_move && $calling_fq_class_name && isset($codebase->classes_to_move[\strtolower($calling_fq_class_name)])) { $destination_class = $codebase->classes_to_move[\strtolower($calling_fq_class_name)]; if ($class_name_node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $destination_parts = \explode('\\', $destination_class); $destination_class_name = \array_pop($destination_parts); $file_manipulations = []; $file_manipulations[] = new \Psalm\FileManipulation((int) $class_name_node->getAttribute('startFilePos'), (int) $class_name_node->getAttribute('endFilePos') + 1, $destination_class_name); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source->getFilePath(), $file_manipulations); } else { $this->airliftClassLikeReference(\strtolower($calling_fq_class_name) === \strtolower($fq_class_name) ? $destination_class : $fq_class_name, $destination_class, $source->getFilePath(), (int) $class_name_node->getAttribute('startFilePos'), (int) $class_name_node->getAttribute('endFilePos') + 1, $class_name_node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Class_); } return \true; } if ($force_change) { if ($calling_fq_class_name) { $this->airliftClassLikeReference($fq_class_name, $calling_fq_class_name, $source->getFilePath(), (int) $class_name_node->getAttribute('startFilePos'), (int) $class_name_node->getAttribute('endFilePos') + 1); } else { $file_manipulations = []; $file_manipulations[] = new \Psalm\FileManipulation((int) $class_name_node->getAttribute('startFilePos'), (int) $class_name_node->getAttribute('endFilePos') + 1, \Psalm\Type::getStringFromFQCLN($fq_class_name, $source->getNamespace(), $source->getAliasedClassesFlipped(), null)); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source->getFilePath(), $file_manipulations); } return \true; } return \false; } /** * @param lowercase-string|null $calling_method_id */ public function handleDocblockTypeInMigration(\Psalm\Codebase $codebase, \Psalm\StatementsSource $source, \Psalm\Type\Union $type, \Psalm\CodeLocation $type_location, ?string $calling_method_id) : void { $calling_fq_class_name = $source->getFQCLN(); $moved_type = \false; // if we're inside a moved class static method if ($codebase->methods_to_move && $calling_fq_class_name && $calling_method_id && isset($codebase->methods_to_move[$calling_method_id])) { $bounds = $type_location->getSelectionBounds(); $destination_class = \explode('::', $codebase->methods_to_move[$calling_method_id])[0]; $this->airliftClassDefinedDocblockType($type, $destination_class, $source->getFilePath(), $bounds[0], $bounds[1]); $moved_type = \true; } // if we're outside a moved class, but we're changing all references to a class if (!$moved_type && $codebase->class_transforms) { $uses_flipped = $source->getAliasedClassesFlipped(); $uses_flipped_replaceable = $source->getAliasedClassesFlippedReplaceable(); $migrated_source_fqcln = $calling_fq_class_name; if ($calling_fq_class_name && isset($codebase->class_transforms[\strtolower($calling_fq_class_name)])) { $migrated_source_fqcln = $codebase->class_transforms[\strtolower($calling_fq_class_name)]; } $source_namespace = $source->getNamespace(); if ($migrated_source_fqcln && $calling_fq_class_name !== $migrated_source_fqcln) { $new_source_parts = \explode('\\', $migrated_source_fqcln, -1); $source_namespace = \implode('\\', $new_source_parts); } foreach ($codebase->class_transforms as $old_fq_class_name => $new_fq_class_name) { if (isset($uses_flipped_replaceable[$old_fq_class_name])) { $alias = $uses_flipped_replaceable[$old_fq_class_name]; unset($uses_flipped[$old_fq_class_name]); $old_class_name_parts = \explode('\\', $old_fq_class_name); $old_class_name = \end($old_class_name_parts); if ($old_class_name === \strtolower($alias)) { $new_class_name_parts = \explode('\\', $new_fq_class_name); $new_class_name = \end($new_class_name_parts); $uses_flipped[\strtolower($new_fq_class_name)] = $new_class_name; } else { $uses_flipped[\strtolower($new_fq_class_name)] = $alias; } } } foreach ($codebase->class_transforms as $old_fq_class_name => $new_fq_class_name) { if ($type->containsClassLike($old_fq_class_name)) { $type = clone $type; $type->replaceClassLike($old_fq_class_name, $new_fq_class_name); $bounds = $type_location->getSelectionBounds(); $file_manipulations = []; $file_manipulations[] = new \Psalm\FileManipulation($bounds[0], $bounds[1], $type->toNamespacedString($source_namespace, $uses_flipped, $migrated_source_fqcln, \false)); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source->getFilePath(), $file_manipulations); $moved_type = \true; } } } // if we're inside a moved class (could be a method, could be a property/class const default) if (!$moved_type && $codebase->classes_to_move && $calling_fq_class_name && isset($codebase->classes_to_move[\strtolower($calling_fq_class_name)])) { $bounds = $type_location->getSelectionBounds(); $destination_class = $codebase->classes_to_move[\strtolower($calling_fq_class_name)]; if ($type->containsClassLike(\strtolower($calling_fq_class_name))) { $type = clone $type; $type->replaceClassLike(\strtolower($calling_fq_class_name), $destination_class); } $this->airliftClassDefinedDocblockType($type, $destination_class, $source->getFilePath(), $bounds[0], $bounds[1]); } } public function airliftClassLikeReference(string $fq_class_name, string $destination_fq_class_name, string $source_file_path, int $source_start, int $source_end, bool $add_class_constant = \false, bool $allow_self = \false) : void { $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); $destination_class_storage = $codebase->classlike_storage_provider->get($destination_fq_class_name); if (!$destination_class_storage->aliases) { throw new \UnexpectedValueException('Aliases should not be null'); } $file_manipulations = []; $file_manipulations[] = new \Psalm\FileManipulation($source_start, $source_end, \Psalm\Type::getStringFromFQCLN($fq_class_name, $destination_class_storage->aliases->namespace, $destination_class_storage->aliases->uses_flipped, $destination_class_storage->name, $allow_self) . ($add_class_constant ? '::class' : '')); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source_file_path, $file_manipulations); } public function airliftClassDefinedDocblockType(\Psalm\Type\Union $type, string $destination_fq_class_name, string $source_file_path, int $source_start, int $source_end) : void { $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); $destination_class_storage = $codebase->classlike_storage_provider->get($destination_fq_class_name); if (!$destination_class_storage->aliases) { throw new \UnexpectedValueException('Aliases should not be null'); } $file_manipulations = []; $file_manipulations[] = new \Psalm\FileManipulation($source_start, $source_end, $type->toNamespacedString($destination_class_storage->aliases->namespace, $destination_class_storage->aliases->uses_flipped, $destination_class_storage->name, \false)); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($source_file_path, $file_manipulations); } /** * @param ReflectionProperty::IS_PUBLIC|ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PRIVATE * $visibility * * @return array */ public function getConstantsForClass(string $class_name, int $visibility) : array { $class_name = \strtolower($class_name); $storage = $this->classlike_storage_provider->get($class_name); if ($visibility === \ReflectionProperty::IS_PUBLIC) { return \array_filter($storage->constants, function ($constant) { return $constant->type && $constant->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; }); } if ($visibility === \ReflectionProperty::IS_PROTECTED) { return \array_filter($storage->constants, function ($constant) { return $constant->type && ($constant->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC || $constant->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED); }); } return \array_filter($storage->constants, function ($constant) { return $constant->type !== null; }); } /** * @param ReflectionProperty::IS_PUBLIC|ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PRIVATE * $visibility */ public function getClassConstantType(string $class_name, string $constant_name, int $visibility, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null, array $visited_constant_ids = []) : ?\Psalm\Type\Union { $class_name = \strtolower($class_name); $storage = $this->classlike_storage_provider->get($class_name); if (!isset($storage->constants[$constant_name])) { return null; } $constant_storage = $storage->constants[$constant_name]; if ($visibility === \ReflectionProperty::IS_PUBLIC && $constant_storage->visibility !== \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC) { return null; } if ($visibility === \ReflectionProperty::IS_PROTECTED && $constant_storage->visibility !== \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC && $constant_storage->visibility !== \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED) { return null; } if ($constant_storage->unresolved_node) { return new \Psalm\Type\Union([\Psalm\Internal\Codebase\ConstantTypeResolver::resolve($this, $constant_storage->unresolved_node, $statements_analyzer, $visited_constant_ids)]); } return $constant_storage->type; } private function checkMethodReferences(\Psalm\Storage\ClassLikeStorage $classlike_storage, \Psalm\Internal\Codebase\Methods $methods) : void { $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); foreach ($classlike_storage->appearing_method_ids as $method_name => $appearing_method_id) { $appearing_fq_classlike_name = $appearing_method_id->fq_class_name; if ($appearing_fq_classlike_name !== $classlike_storage->name) { continue; } $method_id = $appearing_method_id; $declaring_classlike_storage = $classlike_storage; if (isset($classlike_storage->methods[$method_name])) { $method_storage = $classlike_storage->methods[$method_name]; } else { $declaring_method_id = $classlike_storage->declaring_method_ids[$method_name]; $declaring_fq_classlike_name = $declaring_method_id->fq_class_name; $declaring_method_name = $declaring_method_id->method_name; try { $declaring_classlike_storage = $this->classlike_storage_provider->get($declaring_fq_classlike_name); } catch (\InvalidArgumentException $e) { continue; } $method_storage = $declaring_classlike_storage->methods[$declaring_method_name]; $method_id = $declaring_method_id; } if ($method_storage->location && !$project_analyzer->canReportIssues($method_storage->location->file_path) && !$codebase->analyzer->canReportIssues($method_storage->location->file_path)) { continue; } $method_referenced = $this->file_reference_provider->isClassMethodReferenced(\strtolower((string) $method_id)); if (!$method_referenced && $method_name !== '__destruct' && $method_name !== '__clone' && $method_name !== '__invoke' && $method_name !== '__unset' && $method_name !== '__isset' && $method_name !== '__sleep' && $method_name !== '__wakeup' && $method_name !== '__serialize' && $method_name !== '__unserialize' && $method_name !== '__set_state' && $method_name !== '__debuginfo' && $method_name !== '__tostring' && $method_storage->location) { $method_location = $method_storage->location; $method_id = $classlike_storage->name . '::' . $method_storage->cased_name; if ($method_storage->visibility !== \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { $has_parent_references = \false; if ($codebase->classImplements($classlike_storage->name, 'Serializable') && ($method_name === 'serialize' || $method_name === 'unserialize')) { continue; } $has_variable_calls = $codebase->analyzer->hasMixedMemberName($method_name) || $codebase->analyzer->hasMixedMemberName(\strtolower($classlike_storage->name . '::')); if (isset($classlike_storage->overridden_method_ids[$method_name])) { foreach ($classlike_storage->overridden_method_ids[$method_name] as $parent_method_id) { $parent_method_storage = $methods->getStorage($parent_method_id); if ($parent_method_storage->location && !$project_analyzer->canReportIssues($parent_method_storage->location->file_path)) { // here we just don’t know $has_parent_references = \true; break; } $parent_method_referenced = $this->file_reference_provider->isClassMethodReferenced(\strtolower((string) $parent_method_id)); if (!$parent_method_storage->abstract || $parent_method_referenced) { $has_parent_references = \true; break; } } } foreach ($classlike_storage->parent_classes as $parent_method_fqcln) { if ($codebase->analyzer->hasMixedMemberName(\strtolower($parent_method_fqcln) . '::')) { $has_variable_calls = \true; break; } } foreach ($classlike_storage->class_implements as $fq_interface_name_lc => $_) { try { $interface_storage = $this->classlike_storage_provider->get($fq_interface_name_lc); } catch (\InvalidArgumentException $e) { continue; } if ($codebase->analyzer->hasMixedMemberName($fq_interface_name_lc . '::')) { $has_variable_calls = \true; } if (isset($interface_storage->methods[$method_name])) { $interface_method_referenced = $this->file_reference_provider->isClassMethodReferenced($fq_interface_name_lc . '::' . $method_name); if ($interface_method_referenced) { $has_parent_references = \true; } } } if (!$has_parent_references) { $issue = new \Psalm\Issue\PossiblyUnusedMethod('Cannot find ' . ($has_variable_calls ? 'explicit' : 'any') . ' calls to method ' . $method_id . ($has_variable_calls ? ' (but did find some potential callers)' : ''), $method_storage->location, $method_id); if ($codebase->alter_code) { if ($method_storage->stmt_location && !$declaring_classlike_storage->is_trait && isset($project_analyzer->getIssuesToFix()['PossiblyUnusedMethod']) && !$has_variable_calls && !\Psalm\IssueBuffer::isSuppressed($issue, $method_storage->suppressed_issues)) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::addForCodeLocation($method_storage->stmt_location, '', \true); } } elseif (\Psalm\IssueBuffer::accepts($issue, $method_storage->suppressed_issues, $method_storage->stmt_location && !$declaring_classlike_storage->is_trait && !$has_variable_calls)) { // fall through } } } elseif (!isset($classlike_storage->declaring_method_ids['__call'])) { $has_variable_calls = $codebase->analyzer->hasMixedMemberName(\strtolower($classlike_storage->name . '::')) || $codebase->analyzer->hasMixedMemberName($method_name); $issue = new \Psalm\Issue\UnusedMethod('Cannot find ' . ($has_variable_calls ? 'explicit' : 'any') . ' calls to private method ' . $method_id . ($has_variable_calls ? ' (but did find some potential callers)' : ''), $method_location, $method_id); if ($codebase->alter_code) { if ($method_storage->stmt_location && !$declaring_classlike_storage->is_trait && isset($project_analyzer->getIssuesToFix()['UnusedMethod']) && !$has_variable_calls && !\Psalm\IssueBuffer::isSuppressed($issue, $method_storage->suppressed_issues)) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::addForCodeLocation($method_storage->stmt_location, '', \true); } } elseif (\Psalm\IssueBuffer::accepts($issue, $method_storage->suppressed_issues, $method_storage->stmt_location && !$declaring_classlike_storage->is_trait && !$has_variable_calls)) { // fall through } } } else { if ($method_storage->visibility !== \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE && !$classlike_storage->is_interface) { foreach ($method_storage->params as $offset => $param_storage) { if (!$this->file_reference_provider->isMethodParamUsed(\strtolower((string) $method_id), $offset) && $param_storage->location) { if ($method_storage->final) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnusedParam('Param #' . ($offset + 1) . ' is never referenced in this method', $param_storage->location), $method_storage->suppressed_issues)) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUnusedParam('Param #' . ($offset + 1) . ' is never referenced in this method', $param_storage->location), $method_storage->suppressed_issues)) { // fall through } } } } } } } } private function findPossibleMethodParamTypes(\Psalm\Storage\ClassLikeStorage $classlike_storage) : void { $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); foreach ($classlike_storage->appearing_method_ids as $method_name => $appearing_method_id) { $appearing_fq_classlike_name = $appearing_method_id->fq_class_name; if ($appearing_fq_classlike_name !== $classlike_storage->name) { continue; } $method_id = $appearing_method_id; $declaring_classlike_storage = $classlike_storage; if (isset($classlike_storage->methods[$method_name])) { $method_storage = $classlike_storage->methods[$method_name]; } else { $declaring_method_id = $classlike_storage->declaring_method_ids[$method_name]; $declaring_fq_classlike_name = $declaring_method_id->fq_class_name; $declaring_method_name = $declaring_method_id->method_name; try { $declaring_classlike_storage = $this->classlike_storage_provider->get($declaring_fq_classlike_name); } catch (\InvalidArgumentException $e) { continue; } $method_storage = $declaring_classlike_storage->methods[$declaring_method_name]; $method_id = $declaring_method_id; } if ($method_storage->location && !$project_analyzer->canReportIssues($method_storage->location->file_path) && !$codebase->analyzer->canReportIssues($method_storage->location->file_path)) { continue; } if ($declaring_classlike_storage->is_trait) { continue; } $method_id_lc = \strtolower((string) $method_id); if (isset($codebase->analyzer->possible_method_param_types[$method_id_lc])) { if ($method_storage->location) { $possible_param_types = $codebase->analyzer->possible_method_param_types[$method_id_lc]; if ($possible_param_types) { foreach ($possible_param_types as $offset => $possible_type) { if (!isset($method_storage->params[$offset])) { continue; } $param_name = $method_storage->params[$offset]->name; if ($possible_type->hasMixed() || $possible_type->isNull()) { continue; } if ($method_storage->params[$offset]->default_type) { $possible_type = \Psalm\Type::combineUnionTypes($possible_type, $method_storage->params[$offset]->default_type); } if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['MissingParamType'])) { $function_analyzer = $project_analyzer->getFunctionLikeAnalyzer($method_id, $method_storage->location->file_path); $has_variable_calls = $codebase->analyzer->hasMixedMemberName($method_name) || $codebase->analyzer->hasMixedMemberName(\strtolower($classlike_storage->name . '::')); if ($has_variable_calls) { $possible_type->from_docblock = \true; } if ($function_analyzer) { $function_analyzer->addOrUpdateParamType($project_analyzer, $param_name, $possible_type, $possible_type->from_docblock && $project_analyzer->only_replace_php_types_with_non_docblock_types); } } else { \Psalm\IssueBuffer::addFixableIssue('MissingParamType'); } } } } } } } private function checkPropertyReferences(\Psalm\Storage\ClassLikeStorage $classlike_storage) : void { $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); foreach ($classlike_storage->properties as $property_name => $property_storage) { $referenced_property_name = \strtolower($classlike_storage->name) . '::$' . $property_name; $property_referenced = $this->file_reference_provider->isClassPropertyReferenced($referenced_property_name); $property_constructor_referenced = \false; if ($property_referenced && $property_storage->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { $all_method_references = $this->file_reference_provider->getAllMethodReferencesToClassMembers(); if (isset($all_method_references[$referenced_property_name]) && \count($all_method_references[$referenced_property_name]) === 1) { $constructor_name = \strtolower($classlike_storage->name) . '::__construct'; $property_references = $all_method_references[$referenced_property_name]; $property_constructor_referenced = isset($property_references[$constructor_name]) && !$property_storage->is_static; } } if ((!$property_referenced || $property_constructor_referenced) && $property_storage->location) { $property_id = $classlike_storage->name . '::$' . $property_name; if ($property_storage->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC || $property_storage->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED) { $has_parent_references = isset($classlike_storage->overridden_property_ids[$property_name]); $has_variable_calls = $codebase->analyzer->hasMixedMemberName('$' . $property_name) || $codebase->analyzer->hasMixedMemberName(\strtolower($classlike_storage->name) . '::$'); foreach ($classlike_storage->parent_classes as $parent_method_fqcln) { if ($codebase->analyzer->hasMixedMemberName(\strtolower($parent_method_fqcln) . '::$')) { $has_variable_calls = \true; break; } } foreach ($classlike_storage->class_implements as $fq_interface_name) { if ($codebase->analyzer->hasMixedMemberName(\strtolower($fq_interface_name) . '::$')) { $has_variable_calls = \true; break; } } if (!$has_parent_references && ($property_storage->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC || !isset($classlike_storage->declaring_method_ids['__get']))) { $issue = new \Psalm\Issue\PossiblyUnusedProperty('Cannot find ' . ($has_variable_calls ? 'explicit' : 'any') . ' references to property ' . $property_id . ($has_variable_calls ? ' (but did find some potential references)' : ''), $property_storage->location); if ($codebase->alter_code) { if ($property_storage->stmt_location && isset($project_analyzer->getIssuesToFix()['PossiblyUnusedProperty']) && !$has_variable_calls && !\Psalm\IssueBuffer::isSuppressed($issue, $classlike_storage->suppressed_issues)) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::addForCodeLocation($property_storage->stmt_location, '', \true); } } elseif (\Psalm\IssueBuffer::accepts($issue, $classlike_storage->suppressed_issues)) { // fall through } } } elseif (!isset($classlike_storage->declaring_method_ids['__get'])) { $has_variable_calls = $codebase->analyzer->hasMixedMemberName('$' . $property_name); $issue = new \Psalm\Issue\UnusedProperty('Cannot find ' . ($has_variable_calls ? 'explicit' : 'any') . ' references to private property ' . $property_id . ($has_variable_calls ? ' (but did find some potential references)' : ''), $property_storage->location); if ($codebase->alter_code) { if (!$property_constructor_referenced && $property_storage->stmt_location && isset($project_analyzer->getIssuesToFix()['UnusedProperty']) && !$has_variable_calls && !\Psalm\IssueBuffer::isSuppressed($issue, $classlike_storage->suppressed_issues)) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::addForCodeLocation($property_storage->stmt_location, '', \true); } } elseif (\Psalm\IssueBuffer::accepts($issue, $classlike_storage->suppressed_issues)) { // fall through } } } } } /** * @param lowercase-string $fq_classlike_name_lc */ public function registerMissingClassLike(string $fq_classlike_name_lc) : void { $this->existing_classlikes_lc[$fq_classlike_name_lc] = \false; } /** * @param lowercase-string $fq_classlike_name_lc */ public function isMissingClassLike(string $fq_classlike_name_lc) : bool { return isset($this->existing_classlikes_lc[$fq_classlike_name_lc]) && $this->existing_classlikes_lc[$fq_classlike_name_lc] === \false; } /** * @param lowercase-string $fq_classlike_name_lc */ public function doesClassLikeExist(string $fq_classlike_name_lc) : bool { return isset($this->existing_classlikes_lc[$fq_classlike_name_lc]) && $this->existing_classlikes_lc[$fq_classlike_name_lc]; } public function forgetMissingClassLikes() : void { $this->existing_classlikes_lc = \array_filter($this->existing_classlikes_lc); } public function removeClassLike(string $fq_class_name) : void { $fq_class_name_lc = \strtolower($fq_class_name); unset($this->existing_classlikes_lc[$fq_class_name_lc], $this->existing_classes_lc[$fq_class_name_lc], $this->existing_traits_lc[$fq_class_name_lc], $this->existing_traits[$fq_class_name], $this->existing_interfaces_lc[$fq_class_name_lc], $this->existing_interfaces[$fq_class_name], $this->existing_classes[$fq_class_name], $this->trait_nodes[$fq_class_name_lc]); $this->scanner->removeClassLike($fq_class_name_lc); } /** * @return array{ * 0: array, * 1: array, * 2: array, * 3: array, * 4: array, * 5: array, * 6: array, * } */ public function getThreadData() : array { return [$this->existing_classlikes_lc, $this->existing_classes_lc, $this->existing_traits_lc, $this->existing_traits, $this->existing_interfaces_lc, $this->existing_interfaces, $this->existing_classes]; } /** * @param array{ * 0: array, * 1: array, * 2: array, * 3: array, * 4: array, * 5: array, * 6: array, * } $thread_data * */ public function addThreadData(array $thread_data) : void { [$existing_classlikes_lc, $existing_classes_lc, $existing_traits_lc, $existing_traits, $existing_interfaces_lc, $existing_interfaces, $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_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); } } >|null */ private static $call_map = null; /** * @var array>|null */ private static $call_map_callables = []; /** * @var array>> */ private static $taint_sink_map = []; /** * @param array $args */ public static function getCallableFromCallMapById(\Psalm\Codebase $codebase, string $method_id, array $args, ?\Psalm\Internal\Provider\NodeDataProvider $nodes) : \Psalm\Type\Atomic\TCallable { $possible_callables = self::getCallablesFromCallMap($method_id); if ($possible_callables === null) { throw new \UnexpectedValueException('Not expecting $function_param_options to be null for ' . $method_id); } return self::getMatchingCallableFromCallMapOptions($codebase, $possible_callables, $args, $nodes, $method_id); } /** * @param array $callables * @param array $args * */ public static function getMatchingCallableFromCallMapOptions(\Psalm\Codebase $codebase, array $callables, array $args, ?\Psalm\NodeTypeProvider $nodes, string $method_id) : \Psalm\Type\Atomic\TCallable { if (\count($callables) === 1) { return $callables[0]; } $matching_param_count_callable = null; $matching_coerced_param_count_callable = null; foreach ($callables as $possible_callable) { $possible_function_params = $possible_callable->params; \assert($possible_function_params !== null); $all_args_match = \true; $type_coerced = \false; $last_param = \count($possible_function_params) ? $possible_function_params[\count($possible_function_params) - 1] : null; $mandatory_param_count = \count($possible_function_params); foreach ($possible_function_params as $i => $possible_function_param) { if ($possible_function_param->is_optional) { $mandatory_param_count = $i; break; } } if ($mandatory_param_count > \count($args) && !($last_param && $last_param->is_variadic)) { continue; } foreach ($args as $argument_offset => $arg) { if ($argument_offset >= \count($possible_function_params)) { if (!$last_param || !$last_param->is_variadic) { $all_args_match = \false; break; } $function_param = $last_param; } else { $function_param = $possible_function_params[$argument_offset]; } $param_type = $function_param->type; if (!$param_type) { continue; } if (!$nodes || !($arg_type = $nodes->getType($arg->value))) { continue; } if ($arg_type->hasMixed()) { continue; } if ($arg->unpack && !$function_param->is_variadic) { if ($arg_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var Type\Atomic\TArray|Type\Atomic\TKeyedArray|Type\Atomic\TList */ $array_atomic_type = $arg_type->getAtomicTypes()['array']; if ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $arg_type = $array_atomic_type->getGenericValueType(); } elseif ($array_atomic_type instanceof \Psalm\Type\Atomic\TList) { $arg_type = $array_atomic_type->type_param; } else { $arg_type = $array_atomic_type->type_params[1]; } } } $arg_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $arg_type, $param_type, \true, \true, $arg_result) || $arg_result->type_coerced) { if ($arg_result->type_coerced) { $type_coerced = \true; } continue; } $all_args_match = \false; break; } if (\count($args) === \count($possible_function_params)) { $matching_param_count_callable = $possible_callable; } if ($all_args_match && (!$type_coerced || $method_id === 'max' || $method_id === 'min')) { return $possible_callable; } if ($all_args_match) { $matching_coerced_param_count_callable = $possible_callable; } } if ($matching_coerced_param_count_callable) { return $matching_coerced_param_count_callable; } if ($matching_param_count_callable) { return $matching_param_count_callable; } // if we don't succeed in finding a match, set to the first possible and wait for issues below return $callables[0]; } /** * @return array|null */ public static function getCallablesFromCallMap(string $function_id) : ?array { $call_map_key = \strtolower($function_id); if (isset(self::$call_map_callables[$call_map_key])) { return self::$call_map_callables[$call_map_key]; } $call_map = self::getCallMap(); if (!isset($call_map[$call_map_key])) { return null; } $call_map_functions = []; $call_map_functions[] = $call_map[$call_map_key]; for ($i = 1; $i < 10; ++$i) { if (!isset($call_map[$call_map_key . '\'' . $i])) { break; } $call_map_functions[] = $call_map[$call_map_key . '\'' . $i]; } $possible_callables = []; foreach ($call_map_functions as $call_map_function_args) { $return_type_string = \array_shift($call_map_function_args); if (!$return_type_string) { $return_type = \Psalm\Type::getMixed(); } else { $return_type = \Psalm\Type::parseString($return_type_string); } $function_params = []; $arg_offset = 0; /** @var string $arg_name - key type changed with above array_shift */ foreach ($call_map_function_args as $arg_name => $arg_type) { $by_reference = \false; $optional = \false; $variadic = \false; if ($arg_name[0] === '&') { $arg_name = \substr($arg_name, 1); $by_reference = \true; } if (\substr($arg_name, -1) === '=') { $arg_name = \substr($arg_name, 0, -1); $optional = \true; } if (\substr($arg_name, 0, 3) === '...') { $arg_name = \substr($arg_name, 3); $variadic = \true; } $param_type = $arg_type ? \Psalm\Type::parseString($arg_type) : \Psalm\Type::getMixed(); $out_type = null; if (\strlen($arg_name) > 2 && $arg_name[0] === 'w' && $arg_name[1] === '_') { $out_type = $param_type; $param_type = \Psalm\Type::getMixed(); } $function_param = new \Psalm\Storage\FunctionLikeParameter($arg_name, $by_reference, $param_type, null, null, $optional, \false, $variadic); if ($out_type) { $function_param->out_type = $out_type; } if ($arg_name === 'haystack') { $function_param->expect_variable = \true; } if (isset(self::$taint_sink_map[$call_map_key][$arg_offset])) { $function_param->sinks = self::$taint_sink_map[$call_map_key][$arg_offset]; } $function_param->signature_type = null; $function_params[] = $function_param; $arg_offset++; } $possible_callables[] = new \Psalm\Type\Atomic\TCallable('callable', $function_params, $return_type); } self::$call_map_callables[$call_map_key] = $possible_callables; return $possible_callables; } /** * Gets the method/function call map * * @return array> * @psalm-suppress MixedInferredReturnType as the use of require buggers things up * @psalm-suppress MixedReturnStatement * @psalm-suppress MixedReturnTypeCoercion */ public static function getCallMap() : array { $codebase = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance()->getCodebase(); $analyzer_major_version = $codebase->php_major_version; $analyzer_minor_version = $codebase->php_minor_version; $analyzer_version = $analyzer_major_version . '.' . $analyzer_minor_version; $current_version = self::PHP_MAJOR_VERSION . '.' . self::PHP_MINOR_VERSION; $analyzer_version_int = (int) ($analyzer_major_version . $analyzer_minor_version); $current_version_int = (int) (self::PHP_MAJOR_VERSION . self::PHP_MINOR_VERSION); if (self::$call_map !== null && $analyzer_major_version === self::$loaded_php_major_version && $analyzer_minor_version === self::$loaded_php_minor_version) { return self::$call_map; } /** @var array> */ $call_map = (require \dirname(__DIR__, 4) . '/dictionaries/CallMap.php'); self::$call_map = []; foreach ($call_map as $key => $value) { $cased_key = \strtolower($key); self::$call_map[$cased_key] = $value; } /** * @var array>> */ $taint_map = (require \dirname(__DIR__, 4) . '/dictionaries/InternalTaintSinkMap.php'); foreach ($taint_map as $key => $value) { $cased_key = \strtolower($key); self::$taint_sink_map[$cased_key] = $value; } if (\version_compare($analyzer_version, $current_version, '<')) { // the following assumes both minor and major versions a single digits for ($i = $current_version_int; $i > $analyzer_version_int && $i >= self::LOWEST_AVAILABLE_DELTA; --$i) { $delta_file = \dirname(__DIR__, 4) . '/dictionaries/CallMap_' . $i . '_delta.php'; if (!\file_exists($delta_file)) { continue; } /** * @var array{ * old: array>, * new: array> * } * @psalm-suppress UnresolvableInclude */ $diff_call_map = (require $delta_file); foreach ($diff_call_map['new'] as $key => $_) { $cased_key = \strtolower($key); unset(self::$call_map[$cased_key]); } foreach ($diff_call_map['old'] as $key => $value) { $cased_key = \strtolower($key); self::$call_map[$cased_key] = $value; } } } self::$loaded_php_major_version = $analyzer_major_version; self::$loaded_php_minor_version = $analyzer_minor_version; return self::$call_map; } public static function inCallMap(string $key) : bool { return isset(self::getCallMap()[\strtolower($key)]); } public static function clearCache() : void { self::$call_map_callables = []; } } , * 1: array, * 2: array, * 3: array, * 4: array, * 5: array, * 6: array, * 7: array, * 8: array * } * * @psalm-type PoolData = array{ * classlikes_data:array{ * 0:array, * 1:array, * 2:array, * 3:array, * 4:array, * 5:array, * 6:array * }, * scanner_data: ThreadData, * issues:array>, * changed_members:array>, * unchanged_signature_members:array>, * diff_map:array>, * classlike_storage:array, * file_storage:array, * new_file_content_hashes: array, * taint_data: ?TaintFlowGraph * } */ /** * @internal * * Contains methods that aid in the scanning of Psalm's codebase */ class Scanner { /** * @var Codebase */ private $codebase; /** * @var array */ private $classlike_files = []; /** * @var array */ private $deep_scanned_classlike_files = []; /** * @var array */ private $files_to_scan = []; /** * @var array */ private $classes_to_scan = []; /** * @var array */ private $classes_to_deep_scan = []; /** * @var array */ private $files_to_deep_scan = []; /** * @var array */ private $scanned_files = []; /** * @var array */ private $store_scan_failure = []; /** * @var array */ private $reflected_classlikes_lc = []; /** * @var Reflection */ private $reflection; /** * @var Config */ private $config; /** * @var Progress */ private $progress; /** * @var FileStorageProvider */ private $file_storage_provider; /** * @var FileProvider */ private $file_provider; /** * @var FileReferenceProvider */ private $file_reference_provider; /** * @var bool */ private $is_forked = \false; public function __construct(\Psalm\Codebase $codebase, \Psalm\Config $config, \Psalm\Internal\Provider\FileStorageProvider $file_storage_provider, \Psalm\Internal\Provider\FileProvider $file_provider, \Psalm\Internal\Codebase\Reflection $reflection, \Psalm\Internal\Provider\FileReferenceProvider $file_reference_provider, \Psalm\Progress\Progress $progress) { $this->codebase = $codebase; $this->reflection = $reflection; $this->file_provider = $file_provider; $this->progress = $progress; $this->file_storage_provider = $file_storage_provider; $this->config = $config; $this->file_reference_provider = $file_reference_provider; } /** * @param array $files_to_scan * */ public function addFilesToShallowScan(array $files_to_scan) : void { $this->files_to_scan += $files_to_scan; } /** * @param array $files_to_scan */ public function addFilesToDeepScan(array $files_to_scan) : void { $this->files_to_scan += $files_to_scan; $this->files_to_deep_scan += $files_to_scan; } public function addFileToShallowScan(string $file_path) : void { $this->files_to_scan[$file_path] = $file_path; } public function addFileToDeepScan(string $file_path) : void { $this->files_to_scan[$file_path] = $file_path; $this->files_to_deep_scan[$file_path] = $file_path; } public function removeFile(string $file_path) : void { unset($this->scanned_files[$file_path]); } public function removeClassLike(string $fq_classlike_name_lc) : void { unset($this->classlike_files[$fq_classlike_name_lc], $this->deep_scanned_classlike_files[$fq_classlike_name_lc]); } public function setClassLikeFilePath(string $fq_classlike_name_lc, string $file_path) : void { $this->classlike_files[$fq_classlike_name_lc] = $file_path; } public function getClassLikeFilePath(string $fq_classlike_name_lc) : string { if (!isset($this->classlike_files[$fq_classlike_name_lc])) { throw new \UnexpectedValueException('Could not find file for ' . $fq_classlike_name_lc); } return $this->classlike_files[$fq_classlike_name_lc]; } /** * @param array $phantom_classes */ public function queueClassLikeForScanning(string $fq_classlike_name, bool $analyze_too = \false, bool $store_failure = \true, array $phantom_classes = []) : void { if ($fq_classlike_name[0] === '\\') { $fq_classlike_name = \substr($fq_classlike_name, 1); } $fq_classlike_name_lc = \strtolower($fq_classlike_name); if ($fq_classlike_name_lc === 'static') { return; } // avoid checking classes that we know will just end in failure if ($fq_classlike_name_lc === 'null' || \substr($fq_classlike_name_lc, -5) === '\\null') { return; } if (!isset($this->classlike_files[$fq_classlike_name_lc]) || $analyze_too && !isset($this->deep_scanned_classlike_files[$fq_classlike_name_lc])) { if (!isset($this->classes_to_scan[$fq_classlike_name_lc]) || $store_failure) { $this->classes_to_scan[$fq_classlike_name_lc] = $fq_classlike_name; } if ($analyze_too) { $this->classes_to_deep_scan[$fq_classlike_name_lc] = \true; } $this->store_scan_failure[$fq_classlike_name] = $store_failure; if (\Psalm\Internal\Codebase\PropertyMap::inPropertyMap($fq_classlike_name_lc)) { $public_mapped_properties = \Psalm\Internal\Codebase\PropertyMap::getPropertyMap()[$fq_classlike_name_lc]; foreach ($public_mapped_properties as $public_mapped_property) { $property_type = \Psalm\Type::parseString($public_mapped_property); $property_type->queueClassLikesForScanning($this->codebase, null, $phantom_classes + [$fq_classlike_name_lc => \true]); } } } } public function scanFiles(\Psalm\Internal\Codebase\ClassLikes $classlikes, int $pool_size = 1) : bool { $has_changes = \false; while ($this->files_to_scan || $this->classes_to_scan) { if ($this->files_to_scan) { if ($this->scanFilePaths($pool_size)) { $has_changes = \true; } } else { $this->convertClassesToFilePaths($classlikes); } } return $has_changes; } private function scanFilePaths(int $pool_size) : bool { $filetype_scanners = $this->config->getFiletypeScanners(); $files_to_scan = \array_filter($this->files_to_scan, function (string $file_path) : bool { return $this->file_provider->fileExists($file_path) && (!isset($this->scanned_files[$file_path]) || isset($this->files_to_deep_scan[$file_path]) && !$this->scanned_files[$file_path]); }); $this->files_to_scan = []; if (!$files_to_scan) { return \false; } $files_to_deep_scan = $this->files_to_deep_scan; $scanner_worker = function (int $_, string $file_path) use($filetype_scanners, $files_to_deep_scan) : void { $this->scanFile($file_path, $filetype_scanners, isset($files_to_deep_scan[$file_path])); }; if (!$this->is_forked && $pool_size > 1 && \count($files_to_scan) > 512) { $pool_size = \ceil(\min($pool_size, \count($files_to_scan) / 256)); } else { $pool_size = 1; } if ($pool_size > 1) { $process_file_paths = []; $i = 0; foreach ($files_to_scan as $file_path) { $process_file_paths[$i % $pool_size][] = $file_path; ++$i; } $this->progress->debug('Forking process for scanning' . \PHP_EOL); // Run scanning one file at a time, splitting the set of // files up among a given number of child processes. $pool = new \Psalm\Internal\Fork\Pool( $process_file_paths, function () { $this->progress->debug('Initialising forked process for scanning' . \PHP_EOL); $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); $statements_provider = $codebase->statements_provider; $codebase->scanner->isForked(); $codebase->file_storage_provider->deleteAll(); $codebase->classlike_storage_provider->deleteAll(); $statements_provider->resetDiffs(); $this->progress->debug('Have initialised forked process for scanning' . \PHP_EOL); }, $scanner_worker, /** * @return PoolData */ function () { $this->progress->debug('Collecting data from forked scanner process' . \PHP_EOL); $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); $statements_provider = $codebase->statements_provider; return ['classlikes_data' => $codebase->classlikes->getThreadData(), 'scanner_data' => $codebase->scanner->getThreadData(), 'issues' => \Psalm\IssueBuffer::getIssuesData(), 'changed_members' => $statements_provider->getChangedMembers(), 'unchanged_signature_members' => $statements_provider->getUnchangedSignatureMembers(), 'diff_map' => $statements_provider->getDiffMap(), 'classlike_storage' => $codebase->classlike_storage_provider->getAll(), 'file_storage' => $codebase->file_storage_provider->getAll(), 'new_file_content_hashes' => $statements_provider->parser_cache_provider ? $statements_provider->parser_cache_provider->getNewFileContentHashes() : [], 'taint_data' => $codebase->taint_flow_graph]; } ); // Wait for all tasks to complete and collect the results. /** * @var array */ $forked_pool_data = $pool->wait(); foreach ($forked_pool_data as $pool_data) { \Psalm\IssueBuffer::addIssues($pool_data['issues']); $this->codebase->statements_provider->addChangedMembers($pool_data['changed_members']); $this->codebase->statements_provider->addUnchangedSignatureMembers($pool_data['unchanged_signature_members']); $this->codebase->statements_provider->addDiffMap($pool_data['diff_map']); if ($this->codebase->taint_flow_graph && $pool_data['taint_data']) { $this->codebase->taint_flow_graph->addGraph($pool_data['taint_data']); } $this->codebase->file_storage_provider->addMore($pool_data['file_storage']); $this->codebase->classlike_storage_provider->addMore($pool_data['classlike_storage']); $this->codebase->classlikes->addThreadData($pool_data['classlikes_data']); $this->addThreadData($pool_data['scanner_data']); if ($this->codebase->statements_provider->parser_cache_provider) { $this->codebase->statements_provider->parser_cache_provider->addNewFileContentHashes($pool_data['new_file_content_hashes']); } } if ($pool->didHaveError()) { exit(1); } } else { $i = 0; foreach ($files_to_scan as $file_path => $_) { $scanner_worker($i, $file_path); ++$i; } } if ($this->codebase->statements_provider->parser_cache_provider) { $this->codebase->statements_provider->parser_cache_provider->saveFileContentHashes(); } foreach ($files_to_scan as $scanned_file) { if ($this->config->hasStubFile($scanned_file)) { $file_storage = $this->file_storage_provider->get($scanned_file); foreach ($file_storage->functions as $function_storage) { if ($function_storage->cased_name && !$this->codebase->functions->hasStubbedFunction($function_storage->cased_name)) { $this->codebase->functions->addGlobalFunction($function_storage->cased_name, $function_storage); } } foreach ($file_storage->constants as $name => $type) { $this->codebase->addGlobalConstantType($name, $type); } } } $this->file_reference_provider->addClassLikeFiles($this->classlike_files); return \true; } private function convertClassesToFilePaths(\Psalm\Internal\Codebase\ClassLikes $classlikes) : void { $classes_to_scan = $this->classes_to_scan; $this->classes_to_scan = []; foreach ($classes_to_scan as $fq_classlike_name) { $fq_classlike_name_lc = \strtolower($fq_classlike_name); if (isset($this->reflected_classlikes_lc[$fq_classlike_name_lc])) { continue; } if ($classlikes->isMissingClassLike($fq_classlike_name_lc)) { continue; } if (!isset($this->classlike_files[$fq_classlike_name_lc])) { if ($classlikes->doesClassLikeExist($fq_classlike_name_lc)) { if ($fq_classlike_name_lc === 'self') { continue; } $this->progress->debug('Using reflection to get metadata for ' . $fq_classlike_name . "\n"); /** @psalm-suppress ArgumentTypeCoercion */ $reflected_class = new \ReflectionClass($fq_classlike_name); $this->reflection->registerClass($reflected_class); $this->reflected_classlikes_lc[$fq_classlike_name_lc] = \true; } elseif ($this->fileExistsForClassLike($classlikes, $fq_classlike_name)) { $fq_classlike_name_lc = \strtolower($classlikes->getUnAliasedName($fq_classlike_name_lc)); // even though we've checked this above, calling the method invalidates it if (isset($this->classlike_files[$fq_classlike_name_lc])) { $file_path = $this->classlike_files[$fq_classlike_name_lc]; $this->files_to_scan[$file_path] = $file_path; if (isset($this->classes_to_deep_scan[$fq_classlike_name_lc])) { unset($this->classes_to_deep_scan[$fq_classlike_name_lc]); $this->files_to_deep_scan[$file_path] = $file_path; } } } elseif ($this->store_scan_failure[$fq_classlike_name]) { $classlikes->registerMissingClassLike($fq_classlike_name_lc); } } elseif (isset($this->classes_to_deep_scan[$fq_classlike_name_lc]) && !isset($this->deep_scanned_classlike_files[$fq_classlike_name_lc])) { $file_path = $this->classlike_files[$fq_classlike_name_lc]; $this->files_to_scan[$file_path] = $file_path; unset($this->classes_to_deep_scan[$fq_classlike_name_lc]); $this->files_to_deep_scan[$file_path] = $file_path; $this->deep_scanned_classlike_files[$fq_classlike_name_lc] = \true; } } } /** * @param array> $filetype_scanners */ private function scanFile(string $file_path, array $filetype_scanners, bool $will_analyze = \false) : \Psalm\Internal\Scanner\FileScanner { $file_scanner = $this->getScannerForPath($file_path, $filetype_scanners, $will_analyze); if (isset($this->scanned_files[$file_path]) && (!$will_analyze || $this->scanned_files[$file_path])) { throw new \UnexpectedValueException('Should not be rescanning ' . $file_path); } $file_contents = $this->file_provider->getContents($file_path); $from_cache = $this->file_storage_provider->has($file_path, $file_contents); if (!$from_cache) { $this->file_storage_provider->create($file_path); } $this->scanned_files[$file_path] = $will_analyze; $file_storage = $this->file_storage_provider->get($file_path); $file_scanner->scan($this->codebase, $file_storage, $from_cache, $this->progress); if (!$from_cache) { if (!$file_storage->has_visitor_issues && $this->file_storage_provider->cache) { $this->file_storage_provider->cache->writeToCache($file_storage, $file_contents); } } else { $this->codebase->statements_provider->setUnchangedFile($file_path); foreach ($file_storage->required_file_paths as $required_file_path) { if ($will_analyze) { $this->addFileToDeepScan($required_file_path); } else { $this->addFileToShallowScan($required_file_path); } } foreach ($file_storage->classlikes_in_file as $fq_classlike_name) { $this->codebase->exhumeClassLikeStorage(\strtolower($fq_classlike_name), $file_path); } foreach ($file_storage->required_classes as $fq_classlike_name) { $this->queueClassLikeForScanning($fq_classlike_name, $will_analyze, \false); } foreach ($file_storage->required_interfaces as $fq_classlike_name) { $this->queueClassLikeForScanning($fq_classlike_name, \false, \false); } foreach ($file_storage->referenced_classlikes as $fq_classlike_name) { $this->queueClassLikeForScanning($fq_classlike_name, \false, \false); } if ($this->codebase->register_autoload_files) { foreach ($file_storage->functions as $function_storage) { if ($function_storage->cased_name && !$this->codebase->functions->hasStubbedFunction($function_storage->cased_name)) { $this->codebase->functions->addGlobalFunction($function_storage->cased_name, $function_storage); } } foreach ($file_storage->constants as $name => $type) { $this->codebase->addGlobalConstantType($name, $type); } } foreach ($file_storage->classlike_aliases as $aliased_name => $unaliased_name) { $this->codebase->classlikes->addClassAlias($unaliased_name, $aliased_name); } } return $file_scanner; } /** * @param array> $filetype_scanners */ private function getScannerForPath(string $file_path, array $filetype_scanners, bool $will_analyze = \false) : \Psalm\Internal\Scanner\FileScanner { $path_parts = \explode(\DIRECTORY_SEPARATOR, $file_path); $file_name_parts = \explode('.', \array_pop($path_parts)); $extension = \count($file_name_parts) > 1 ? \array_pop($file_name_parts) : null; $file_name = $this->config->shortenFileName($file_path); if (isset($filetype_scanners[$extension])) { return new $filetype_scanners[$extension]($file_path, $file_name, $will_analyze); } return new \Psalm\Internal\Scanner\FileScanner($file_path, $file_name, $will_analyze); } /** * @return array */ public function getScannedFiles() : array { return $this->scanned_files; } /** * Checks whether a class exists, and if it does then records what file it's in * for later checking */ private function fileExistsForClassLike(\Psalm\Internal\Codebase\ClassLikes $classlikes, string $fq_class_name) : bool { $fq_class_name_lc = \strtolower($fq_class_name); if (isset($this->classlike_files[$fq_class_name_lc])) { return \true; } if ($fq_class_name === 'self') { return \false; } if (isset($this->existing_classlikes_lc[$fq_class_name_lc])) { throw new \InvalidArgumentException('Why are you asking about a builtin class?'); } $composer_file_path = $this->config->getComposerFilePathForClassLike($fq_class_name); if ($composer_file_path && \file_exists($composer_file_path)) { $this->progress->debug('Using composer to locate file for ' . $fq_class_name . "\n"); $classlikes->addFullyQualifiedClassLikeName($fq_class_name_lc, \realpath($composer_file_path)); return \true; } $old_level = \error_reporting(); $this->progress->setErrorReporting(); try { $this->progress->debug('Using reflection to locate file for ' . $fq_class_name . "\n"); /** @psalm-suppress ArgumentTypeCoercion */ $reflected_class = new \ReflectionClass($fq_class_name); } catch (\Throwable $e) { \error_reporting($old_level); // do not cache any results here (as case-sensitive filenames can screw things up) return \false; } \error_reporting($old_level); $file_path = (string) $reflected_class->getFileName(); // if the file was autoloaded but exists in evaled code only, return false if (!\file_exists($file_path)) { return \false; } $new_fq_class_name = $reflected_class->getName(); $new_fq_class_name_lc = \strtolower($new_fq_class_name); if ($new_fq_class_name_lc !== $fq_class_name_lc) { $classlikes->addClassAlias($new_fq_class_name, $fq_class_name_lc); $fq_class_name_lc = $new_fq_class_name_lc; } $fq_class_name = $new_fq_class_name; $classlikes->addFullyQualifiedClassLikeName($fq_class_name_lc); if ($reflected_class->isInterface()) { $classlikes->addFullyQualifiedInterfaceName($fq_class_name, $file_path); } elseif ($reflected_class->isTrait()) { $classlikes->addFullyQualifiedTraitName($fq_class_name, $file_path); } else { $classlikes->addFullyQualifiedClassName($fq_class_name, $file_path); } return \true; } /** * @return ThreadData */ public function getThreadData() : array { return [$this->files_to_scan, $this->files_to_deep_scan, $this->classes_to_scan, $this->classes_to_deep_scan, $this->store_scan_failure, $this->classlike_files, $this->deep_scanned_classlike_files, $this->scanned_files, $this->reflected_classlikes_lc]; } /** * @param ThreadData $thread_data * */ public function addThreadData(array $thread_data) : void { [$files_to_scan, $files_to_deep_scan, $classes_to_scan, $classes_to_deep_scan, $store_scan_failure, $classlike_files, $deep_scanned_classlike_files, $scanned_files, $reflected_classlikes_lc] = $thread_data; $this->files_to_scan = \array_merge($files_to_scan, $this->files_to_scan); $this->files_to_deep_scan = \array_merge($files_to_deep_scan, $this->files_to_deep_scan); $this->classes_to_scan = \array_merge($classes_to_scan, $this->classes_to_scan); $this->classes_to_deep_scan = \array_merge($classes_to_deep_scan, $this->classes_to_deep_scan); $this->store_scan_failure = \array_merge($store_scan_failure, $this->store_scan_failure); $this->classlike_files = \array_merge($classlike_files, $this->classlike_files); $this->deep_scanned_classlike_files = \array_merge($deep_scanned_classlike_files, $this->deep_scanned_classlike_files); $this->scanned_files = \array_merge($scanned_files, $this->scanned_files); $this->reflected_classlikes_lc = \array_merge($reflected_classlikes_lc, $this->reflected_classlikes_lc); } public function isForked() : void { $this->is_forked = \true; } } */ private static $stubbed_functions; /** @var FunctionReturnTypeProvider */ public $return_type_provider; /** @var FunctionExistenceProvider */ public $existence_provider; /** @var FunctionParamsProvider */ public $params_provider; /** * @var Reflection */ private $reflection; public function __construct(\Psalm\Internal\Provider\FileStorageProvider $storage_provider, \Psalm\Internal\Codebase\Reflection $reflection) { $this->file_storage_provider = $storage_provider; $this->reflection = $reflection; $this->return_type_provider = new \Psalm\Internal\Provider\FunctionReturnTypeProvider(); $this->existence_provider = new \Psalm\Internal\Provider\FunctionExistenceProvider(); $this->params_provider = new \Psalm\Internal\Provider\FunctionParamsProvider(); self::$stubbed_functions = []; } /** * @param non-empty-lowercase-string $function_id */ public function getStorage(?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $function_id, ?string $root_file_path = null, ?string $checked_file_path = null) : \Psalm\Storage\FunctionStorage { if ($function_id[0] === '\\') { $function_id = \substr($function_id, 1); } if (isset(self::$stubbed_functions[$function_id])) { return self::$stubbed_functions[$function_id]; } $file_storage = null; if ($statements_analyzer) { $root_file_path = $statements_analyzer->getRootFilePath(); $checked_file_path = $statements_analyzer->getFilePath(); $file_storage = $this->file_storage_provider->get($root_file_path); $function_analyzers = $statements_analyzer->getFunctionAnalyzers(); if (isset($function_analyzers[$function_id])) { $function_id = $function_analyzers[$function_id]->getFunctionId(); if (isset($file_storage->functions[$function_id])) { return $file_storage->functions[$function_id]; } } // closures can be returned here if (isset($file_storage->functions[$function_id])) { return $file_storage->functions[$function_id]; } } if (!$root_file_path || !$checked_file_path) { if ($this->reflection->hasFunction($function_id)) { return $this->reflection->getFunctionStorage($function_id); } throw new \UnexpectedValueException('Expecting non-empty $root_file_path and $checked_file_path'); } if ($this->reflection->hasFunction($function_id)) { return $this->reflection->getFunctionStorage($function_id); } if (!isset($file_storage->declaring_function_ids[$function_id])) { if ($checked_file_path !== $root_file_path) { $file_storage = $this->file_storage_provider->get($checked_file_path); if (isset($file_storage->functions[$function_id])) { return $file_storage->functions[$function_id]; } } throw new \UnexpectedValueException('Expecting ' . $function_id . ' to have storage in ' . $checked_file_path); } $declaring_file_path = $file_storage->declaring_function_ids[$function_id]; $declaring_file_storage = $this->file_storage_provider->get($declaring_file_path); if (!isset($declaring_file_storage->functions[$function_id])) { throw new \UnexpectedValueException('Not expecting ' . $function_id . ' to not have storage in ' . $declaring_file_path); } return $declaring_file_storage->functions[$function_id]; } public function addGlobalFunction(string $function_id, \Psalm\Storage\FunctionStorage $storage) : void { self::$stubbed_functions[\strtolower($function_id)] = $storage; } public function hasStubbedFunction(string $function_id) : bool { return isset(self::$stubbed_functions[\strtolower($function_id)]); } /** * @return array */ public function getAllStubbedFunctions() : array { return self::$stubbed_functions; } /** * @param lowercase-string $function_id */ public function functionExists(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $function_id) : bool { if ($this->existence_provider->has($function_id)) { $function_exists = $this->existence_provider->doesFunctionExist($statements_analyzer, $function_id); if ($function_exists !== null) { return $function_exists; } } $file_storage = $this->file_storage_provider->get($statements_analyzer->getRootFilePath()); if (isset($file_storage->declaring_function_ids[$function_id])) { return \true; } if ($this->reflection->hasFunction($function_id)) { return \true; } if (isset(self::$stubbed_functions[$function_id])) { return \true; } if (isset($statements_analyzer->getFunctionAnalyzers()[$function_id])) { return \true; } $predefined_functions = $statements_analyzer->getCodebase()->config->getPredefinedFunctions(); if (isset($predefined_functions[$function_id])) { /** @psalm-suppress ArgumentTypeCoercion */ if ($this->reflection->registerFunction($function_id) === \false) { return \false; } return \true; } return \false; } /** * @param non-empty-string $function_name * * @return non-empty-string */ public function getFullyQualifiedFunctionNameFromString(string $function_name, \Psalm\StatementsSource $source) : string { if ($function_name[0] === '\\') { $function_name = \substr($function_name, 1); if ($function_name === '') { throw new \UnexpectedValueException('Malformed function name'); } return $function_name; } $function_name_lcase = \strtolower($function_name); $aliases = $source->getAliases(); $imported_function_namespaces = $aliases->functions; $imported_namespaces = $aliases->uses; if (\strpos($function_name, '\\') !== \false) { $function_name_parts = \explode('\\', $function_name); $first_namespace = \array_shift($function_name_parts); $first_namespace_lcase = \strtolower($first_namespace); if (isset($imported_namespaces[$first_namespace_lcase])) { return $imported_namespaces[$first_namespace_lcase] . '\\' . \implode('\\', $function_name_parts); } if (isset($imported_function_namespaces[$first_namespace_lcase])) { return $imported_function_namespaces[$first_namespace_lcase] . '\\' . \implode('\\', $function_name_parts); } } elseif (isset($imported_function_namespaces[$function_name_lcase])) { return $imported_function_namespaces[$function_name_lcase]; } $namespace = $source->getNamespace(); return ($namespace ? $namespace . '\\' : '') . $function_name; } public static function isVariadic(\Psalm\Codebase $codebase, string $function_id, string $file_path) : bool { $file_storage = $codebase->file_storage_provider->get($file_path); if (!isset($file_storage->declaring_function_ids[$function_id])) { return \false; } $declaring_file_path = $file_storage->declaring_function_ids[$function_id]; $file_storage = $declaring_file_path === $file_path ? $file_storage : $codebase->file_storage_provider->get($declaring_file_path); return isset($file_storage->functions[$function_id]) && $file_storage->functions[$function_id]->variadic; } /** * @param ?array $args */ public function isCallMapFunctionPure(\Psalm\Codebase $codebase, ?\Psalm\NodeTypeProvider $type_provider, string $function_id, ?array $args, bool &$must_use = \true) : bool { $impure_functions = [ // file io 'chdir', 'chgrp', 'chmod', 'chown', 'chroot', 'copy', 'file_put_contents', 'opendir', 'readdir', 'closedir', 'rewinddir', 'scandir', 'fopen', 'fread', 'fwrite', 'fclose', 'touch', 'fpassthru', 'fputs', 'fscanf', 'fseek', 'ftruncate', 'fprintf', 'symlink', 'mkdir', 'unlink', 'rename', 'rmdir', 'popen', 'pclose', 'fgetcsv', 'fputcsv', 'umask', 'finfo_close', 'readline_add_history', 'stream_set_timeout', 'fgets', 'fflush', 'move_uploaded_file', 'file_exists', 'realpath', 'glob', // stream/socket io 'stream_context_set_option', 'socket_write', 'stream_set_blocking', 'socket_close', 'socket_set_option', 'stream_set_write_buffer', // meta calls 'call_user_func', 'call_user_func_array', 'define', 'create_function', // http 'header', 'header_remove', 'http_response_code', 'setcookie', // output buffer 'ob_start', 'ob_end_clean', 'readfile', 'printf', 'var_dump', 'phpinfo', 'ob_implicit_flush', 'vprintf', // mcrypt 'mcrypt_generic_init', 'mcrypt_generic_deinit', 'mcrypt_module_close', // internal optimisation 'opcache_compile_file', 'clearstatcache', // process-related 'pcntl_signal', 'posix_kill', 'cli_set_process_title', 'pcntl_async_signals', 'proc_close', 'proc_nice', 'proc_open', 'proc_terminate', // curl 'curl_setopt', 'curl_close', 'curl_multi_add_handle', 'curl_multi_remove_handle', 'curl_multi_select', 'curl_multi_close', 'curl_setopt_array', // apc, apcu 'apc_store', 'apc_delete', 'apc_clear_cache', 'apc_add', 'apc_inc', 'apc_dec', 'apc_cas', 'apcu_store', 'apcu_delete', 'apcu_clear_cache', 'apcu_add', 'apcu_inc', 'apcu_dec', 'apcu_cas', // gz 'gzwrite', 'gzrewind', 'gzseek', 'gzclose', // newrelic 'newrelic_start_transaction', 'newrelic_name_transaction', 'newrelic_add_custom_parameter', 'newrelic_add_custom_tracer', 'newrelic_background_job', 'newrelic_end_transaction', 'newrelic_set_appname', // execution 'shell_exec', 'exec', 'system', 'passthru', 'pcntl_exec', // well-known functions 'libxml_use_internal_errors', 'libxml_disable_entity_loader', 'curl_exec', 'mt_srand', 'openssl_pkcs7_sign', 'mt_rand', 'rand', 'random_int', 'random_bytes', 'wincache_ucache_delete', 'wincache_ucache_set', 'wincache_ucache_inc', 'class_alias', 'class_exists', // impure by virtue of triggering autoloader // php environment 'ini_set', 'sleep', 'usleep', 'register_shutdown_function', 'error_reporting', 'register_tick_function', 'unregister_tick_function', 'set_error_handler', 'user_error', 'trigger_error', 'restore_error_handler', 'date_default_timezone_set', 'assert_options', 'setlocale', 'set_exception_handler', 'set_time_limit', 'putenv', 'spl_autoload_register', 'microtime', 'array_rand', // logging 'openlog', 'syslog', 'error_log', 'define_syslog_variables', // session 'session_id', 'session_decode', 'session_name', 'session_set_cookie_params', 'session_set_save_handler', 'session_regenerate_id', 'mb_internal_encoding', 'session_start', // ldap 'ldap_set_option', // iterators 'rewind', 'iterator_apply', // mysqli 'mysqli_select_db', 'mysqli_dump_debug_info', 'mysqli_kill', 'mysqli_multi_query', 'mysqli_next_result', 'mysqli_options', 'mysqli_ping', 'mysqli_query', 'mysqli_report', 'mysqli_rollback', 'mysqli_savepoint', 'mysqli_set_charset', 'mysqli_ssl_set', // script execution 'ignore_user_abort', // ftp 'ftp_close', // bcmath 'bcscale', ]; if (\in_array(\strtolower($function_id), $impure_functions, \true)) { return \false; } if (\strpos($function_id, 'image') === 0) { return \false; } if (($function_id === 'var_export' || $function_id === 'print_r') && !isset($args[1])) { return \false; } if ($function_id === 'assert') { $must_use = \false; return \true; } if ($function_id === 'func_num_args' || $function_id === 'func_get_args') { return \true; } if ($function_id === 'count' && isset($args[0]) && $type_provider) { $count_type = $type_provider->getType($args[0]->value); if ($count_type) { foreach ($count_type->getAtomicTypes() as $atomic_count_type) { if ($atomic_count_type instanceof \Psalm\Type\Atomic\TNamedObject) { $count_method_id = new \Psalm\Internal\MethodIdentifier($atomic_count_type->value, 'count'); try { $method_storage = $codebase->methods->getStorage($count_method_id); return $method_storage->mutation_free; } catch (\Exception $e) { // do nothing } } } } } $function_callable = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallableFromCallMapById($codebase, $function_id, $args ?: [], null); if (!$function_callable->params || $args !== null && \count($args) === 0 || $function_callable->return_type && $function_callable->return_type->isVoid()) { return \false; } $must_use = $function_id !== 'array_map' || isset($args[0]) && !$args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure; foreach ($function_callable->params as $i => $param) { if ($type_provider && $param->type && $param->type->hasCallableType() && isset($args[$i])) { $arg_type = $type_provider->getType($args[$i]->value); if ($arg_type) { foreach ($arg_type->getAtomicTypes() as $possible_callable) { $possible_callable = \Psalm\Internal\Type\Comparator\CallableTypeComparator::getCallableFromAtomic($codebase, $possible_callable); if ($possible_callable && !$possible_callable->is_pure) { return \false; } } } } if ($param->by_ref && isset($args[$i])) { $must_use = \false; } } return \true; } public static function clearCache() : void { self::$stubbed_functions = []; } } * * @psalm-type FileMapType = array{ * 0: TaggedCodeType, * 1: TaggedCodeType, * 2: array * } * * @psalm-type WorkerData = array{ * issues: array>, * fixable_issue_counts: array, * nonmethod_references_to_classes: array>, * method_references_to_classes: array>, * file_references_to_class_members: array>, * file_references_to_missing_class_members: array>, * mixed_counts: array, * mixed_member_names: array>, * function_timings: array, * file_manipulations: array, * method_references_to_class_members: array>, * method_references_to_missing_class_members: array>, * method_param_uses: array>>, * analyzed_methods: array>, * file_maps: array, * class_locations: array>, * class_method_locations: array>, * class_property_locations: array>, * possible_method_param_types: array>, * taint_data: ?TaintFlowGraph, * unused_suppressions: array>, * used_suppressions: array>, * function_docblock_manipulators: array>, * mutable_classes: array, * } */ /** * @internal * * Called in the analysis phase of Psalm's execution */ class Analyzer { /** * @var Config */ private $config; /** * @var FileProvider */ private $file_provider; /** * @var FileStorageProvider */ private $file_storage_provider; /** * @var Progress */ private $progress; /** * Used to store counts of mixed vs non-mixed variables * * @var array */ private $mixed_counts = []; /** * Used to store member names of mixed property/method access * * @var array> */ private $mixed_member_names = []; /** * @var bool */ private $count_mixed = \true; /** * Used to store debug performance data * * @var array */ private $function_timings = []; /** * We analyze more files than we necessarily report errors in * * @var array */ private $files_to_analyze = []; /** * We can show analysis results on more files than we analyze * because the results can be cached * * @var array */ private $files_with_analysis_results = []; /** * We may update fewer files than we analyse (i.e. for dead code detection) * * @var array|null */ private $files_to_update = null; /** * @var array> */ private $analyzed_methods = []; /** * @var array> */ private $existing_issues = []; /** * @var array> */ private $reference_map = []; /** * @var array> */ private $type_map = []; /** * @var array> */ private $argument_map = []; /** * @var array> */ public $possible_method_param_types = []; /** * @var array */ public $mutable_classes = []; public function __construct(\Psalm\Config $config, \Psalm\Internal\Provider\FileProvider $file_provider, \Psalm\Internal\Provider\FileStorageProvider $file_storage_provider, \Psalm\Progress\Progress $progress) { $this->config = $config; $this->file_provider = $file_provider; $this->file_storage_provider = $file_storage_provider; $this->progress = $progress; } /** * @param array $files_to_analyze * */ public function addFilesToAnalyze(array $files_to_analyze) : void { $this->files_to_analyze += $files_to_analyze; $this->files_with_analysis_results += $files_to_analyze; } /** * @param array $files_to_analyze * */ public function addFilesToShowResults(array $files_to_analyze) : void { $this->files_with_analysis_results += $files_to_analyze; } /** * @param array $files_to_update * */ public function setFilesToUpdate(array $files_to_update) : void { $this->files_to_update = $files_to_update; } public function canReportIssues(string $file_path) : bool { return isset($this->files_with_analysis_results[$file_path]); } /** * @param array> $filetype_analyzers */ private function getFileAnalyzer(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, string $file_path, array $filetype_analyzers) : \Psalm\Internal\Analyzer\FileAnalyzer { $extension = \pathinfo($file_path, \PATHINFO_EXTENSION); $file_name = $this->config->shortenFileName($file_path); if (isset($filetype_analyzers[$extension])) { $file_analyzer = new $filetype_analyzers[$extension]($project_analyzer, $file_path, $file_name); } else { $file_analyzer = new \Psalm\Internal\Analyzer\FileAnalyzer($project_analyzer, $file_path, $file_name); } $this->progress->debug('Getting ' . $file_path . "\n"); return $file_analyzer; } public function analyzeFiles(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, int $pool_size, bool $alter_code, bool $consolidate_analyzed_data = \false) : void { $this->loadCachedResults($project_analyzer); $codebase = $project_analyzer->getCodebase(); if ($alter_code) { $project_analyzer->interpretRefactors(); } $this->files_to_analyze = \array_filter($this->files_to_analyze, function (string $file_path) : bool { return $this->file_provider->fileExists($file_path); }); $this->doAnalysis($project_analyzer, $pool_size); $scanned_files = $codebase->scanner->getScannedFiles(); if ($codebase->taint_flow_graph) { $codebase->taint_flow_graph->connectSinksAndSources(); } $this->progress->finish(); if ($consolidate_analyzed_data) { $project_analyzer->consolidateAnalyzedData(); } foreach (\Psalm\IssueBuffer::getIssuesData() as $file_path => $file_issues) { $codebase->file_reference_provider->clearExistingIssuesForFile($file_path); foreach ($file_issues as $issue_data) { $codebase->file_reference_provider->addIssue($file_path, $issue_data); } } $codebase->file_reference_provider->updateReferenceCache($codebase, $scanned_files); if ($codebase->track_unused_suppressions) { \Psalm\IssueBuffer::processUnusedSuppressions($codebase->file_provider); } $codebase->file_reference_provider->setAnalyzedMethods($this->analyzed_methods); $codebase->file_reference_provider->setFileMaps($this->getFileMaps()); $codebase->file_reference_provider->setTypeCoverage($this->mixed_counts); $codebase->file_reference_provider->updateReferenceCache($codebase, $scanned_files); if ($codebase->diff_methods) { $codebase->statements_provider->resetDiffs(); } if ($alter_code) { $this->progress->startAlteringFiles(); $project_analyzer->prepareMigration(); $files_to_update = $this->files_to_update !== null ? $this->files_to_update : $this->files_to_analyze; foreach ($files_to_update as $file_path) { $this->updateFile($file_path, $project_analyzer->dry_run); } $project_analyzer->migrateCode(); } } private function doAnalysis(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, int $pool_size) : void { $this->progress->start(\count($this->files_to_analyze)); \ksort($this->files_to_analyze); $codebase = $project_analyzer->getCodebase(); $filetype_analyzers = $this->config->getFiletypeAnalyzers(); $analysis_worker = function (int $_, string $file_path) use($project_analyzer, $filetype_analyzers) : array { $file_analyzer = $this->getFileAnalyzer($project_analyzer, $file_path, $filetype_analyzers); $this->progress->debug('Analyzing ' . $file_analyzer->getFilePath() . "\n"); $file_analyzer->analyze(null); $file_analyzer->context = null; $file_analyzer->clearSourceBeforeDestruction(); unset($file_analyzer); return \Psalm\IssueBuffer::getIssuesDataForFile($file_path); }; $task_done_closure = function (array $issues) : void { $has_error = \false; $has_info = \false; foreach ($issues as $issue) { if ($issue->severity === 'error') { $has_error = \true; break; } if ($issue->severity === 'info') { $has_info = \true; } } $this->progress->taskDone($has_error ? 2 : ($has_info ? 1 : 0)); }; if ($pool_size > 1 && \count($this->files_to_analyze) > $pool_size) { $shuffle_count = $pool_size + 1; $file_paths = \array_values($this->files_to_analyze); $count = \count($file_paths); $middle = \intdiv($count, $shuffle_count); $remainder = $count % $shuffle_count; $new_file_paths = []; for ($i = 0; $i < $shuffle_count; $i++) { for ($j = 0; $j < $middle; $j++) { if ($j * $shuffle_count + $i < $count) { $new_file_paths[] = $file_paths[$j * $shuffle_count + $i]; } } if ($remainder) { $new_file_paths[] = $file_paths[$middle * $shuffle_count + $remainder - 1]; $remainder--; } } $process_file_paths = []; $i = 0; foreach ($new_file_paths as $file_path) { $process_file_paths[$i % $pool_size][] = $file_path; ++$i; } // Run analysis one file at a time, splitting the set of // files up among a given number of child processes. $pool = new \Psalm\Internal\Fork\Pool( $process_file_paths, function () : void { $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); $file_reference_provider = $codebase->file_reference_provider; if ($codebase->taint_flow_graph) { $codebase->taint_flow_graph = new \Psalm\Internal\Codebase\TaintFlowGraph(); } $file_reference_provider->setNonMethodReferencesToClasses([]); $file_reference_provider->setCallingMethodReferencesToClassMembers([]); $file_reference_provider->setFileReferencesToClassMembers([]); $file_reference_provider->setCallingMethodReferencesToMissingClassMembers([]); $file_reference_provider->setFileReferencesToMissingClassMembers([]); $file_reference_provider->setReferencesToMixedMemberNames([]); $file_reference_provider->setMethodParamUses([]); }, $analysis_worker, /** @return WorkerData */ function () { $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); $analyzer = $codebase->analyzer; $file_reference_provider = $codebase->file_reference_provider; $this->progress->debug('Gathering data for forked process' . "\n"); // @codingStandardsIgnoreStart return ['issues' => \Psalm\IssueBuffer::getIssuesData(), 'fixable_issue_counts' => \Psalm\IssueBuffer::getFixableIssues(), 'nonmethod_references_to_classes' => $file_reference_provider->getAllNonMethodReferencesToClasses(), 'method_references_to_classes' => $file_reference_provider->getAllMethodReferencesToClasses(), 'file_references_to_class_members' => $file_reference_provider->getAllFileReferencesToClassMembers(), 'method_references_to_class_members' => $file_reference_provider->getAllMethodReferencesToClassMembers(), 'file_references_to_missing_class_members' => $file_reference_provider->getAllFileReferencesToMissingClassMembers(), 'method_references_to_missing_class_members' => $file_reference_provider->getAllMethodReferencesToMissingClassMembers(), 'method_param_uses' => $file_reference_provider->getAllMethodParamUses(), 'mixed_member_names' => $analyzer->getMixedMemberNames(), 'file_manipulations' => \Psalm\Internal\FileManipulation\FileManipulationBuffer::getAll(), 'mixed_counts' => $analyzer->getMixedCounts(), 'function_timings' => $analyzer->getFunctionTimings(), 'analyzed_methods' => $analyzer->getAnalyzedMethods(), 'file_maps' => $analyzer->getFileMaps(), 'class_locations' => $file_reference_provider->getAllClassLocations(), 'class_method_locations' => $file_reference_provider->getAllClassMethodLocations(), 'class_property_locations' => $file_reference_provider->getAllClassPropertyLocations(), 'possible_method_param_types' => $analyzer->getPossibleMethodParamTypes(), 'taint_data' => $codebase->taint_flow_graph, 'unused_suppressions' => $codebase->track_unused_suppressions ? \Psalm\IssueBuffer::getUnusedSuppressions() : [], 'used_suppressions' => $codebase->track_unused_suppressions ? \Psalm\IssueBuffer::getUsedSuppressions() : [], 'function_docblock_manipulators' => \Psalm\Internal\FileManipulation\FunctionDocblockManipulator::getManipulators(), 'mutable_classes' => $codebase->analyzer->mutable_classes]; // @codingStandardsIgnoreEnd }, $task_done_closure ); $this->progress->debug('Forking analysis' . "\n"); // Wait for all tasks to complete and collect the results. /** * @var array */ $forked_pool_data = $pool->wait(); $this->progress->debug('Collecting forked analysis results' . "\n"); foreach ($forked_pool_data as $pool_data) { \Psalm\IssueBuffer::addIssues($pool_data['issues']); \Psalm\IssueBuffer::addFixableIssues($pool_data['fixable_issue_counts']); if ($codebase->track_unused_suppressions) { \Psalm\IssueBuffer::addUnusedSuppressions($pool_data['unused_suppressions']); \Psalm\IssueBuffer::addUsedSuppressions($pool_data['used_suppressions']); } if ($codebase->taint_flow_graph && $pool_data['taint_data']) { $codebase->taint_flow_graph->addGraph($pool_data['taint_data']); } $codebase->file_reference_provider->addNonMethodReferencesToClasses($pool_data['nonmethod_references_to_classes']); $codebase->file_reference_provider->addMethodReferencesToClasses($pool_data['method_references_to_classes']); $codebase->file_reference_provider->addFileReferencesToClassMembers($pool_data['file_references_to_class_members']); $codebase->file_reference_provider->addMethodReferencesToClassMembers($pool_data['method_references_to_class_members']); $codebase->file_reference_provider->addFileReferencesToMissingClassMembers($pool_data['file_references_to_missing_class_members']); $codebase->file_reference_provider->addMethodReferencesToMissingClassMembers($pool_data['method_references_to_missing_class_members']); $codebase->file_reference_provider->addMethodParamUses($pool_data['method_param_uses']); $this->addMixedMemberNames($pool_data['mixed_member_names']); $this->function_timings += $pool_data['function_timings']; $codebase->file_reference_provider->addClassLocations($pool_data['class_locations']); $codebase->file_reference_provider->addClassMethodLocations($pool_data['class_method_locations']); $codebase->file_reference_provider->addClassPropertyLocations($pool_data['class_property_locations']); $this->mutable_classes = \array_merge($this->mutable_classes, $pool_data['mutable_classes']); \Psalm\Internal\FileManipulation\FunctionDocblockManipulator::addManipulators($pool_data['function_docblock_manipulators']); $this->analyzed_methods = \array_merge($pool_data['analyzed_methods'], $this->analyzed_methods); foreach ($pool_data['mixed_counts'] as $file_path => [$mixed_count, $nonmixed_count]) { if (!isset($this->mixed_counts[$file_path])) { $this->mixed_counts[$file_path] = [$mixed_count, $nonmixed_count]; } else { $this->mixed_counts[$file_path][0] += $mixed_count; $this->mixed_counts[$file_path][1] += $nonmixed_count; } } foreach ($pool_data['possible_method_param_types'] as $declaring_method_id => $possible_param_types) { if (!isset($this->possible_method_param_types[$declaring_method_id])) { $this->possible_method_param_types[$declaring_method_id] = $possible_param_types; } else { foreach ($possible_param_types as $offset => $possible_param_type) { if (!isset($this->possible_method_param_types[$declaring_method_id][$offset])) { $this->possible_method_param_types[$declaring_method_id][$offset] = $possible_param_type; } else { $this->possible_method_param_types[$declaring_method_id][$offset] = \Psalm\Type::combineUnionTypes($this->possible_method_param_types[$declaring_method_id][$offset], $possible_param_type, $codebase); } } } } foreach ($pool_data['file_manipulations'] as $file_path => $manipulations) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($file_path, $manipulations); } foreach ($pool_data['file_maps'] as $file_path => $file_maps) { [$reference_map, $type_map, $argument_map] = $file_maps; $this->reference_map[$file_path] = $reference_map; $this->type_map[$file_path] = $type_map; $this->argument_map[$file_path] = $argument_map; } } if ($pool->didHaveError()) { exit(1); } } else { $i = 0; foreach ($this->files_to_analyze as $file_path => $_) { $analysis_worker($i, $file_path); ++$i; $issues = \Psalm\IssueBuffer::getIssuesDataForFile($file_path); $task_done_closure($issues); } } } public function loadCachedResults(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer) : void { $codebase = $project_analyzer->getCodebase(); if ($codebase->diff_methods) { $this->analyzed_methods = $codebase->file_reference_provider->getAnalyzedMethods(); $this->existing_issues = $codebase->file_reference_provider->getExistingIssues(); $file_maps = $codebase->file_reference_provider->getFileMaps(); foreach ($file_maps as $file_path => [$reference_map, $type_map, $argument_map]) { $this->reference_map[$file_path] = $reference_map; $this->type_map[$file_path] = $type_map; $this->argument_map[$file_path] = $argument_map; } } $statements_provider = $codebase->statements_provider; $file_reference_provider = $codebase->file_reference_provider; $changed_members = $statements_provider->getChangedMembers(); $unchanged_signature_members = $statements_provider->getUnchangedSignatureMembers(); $diff_map = $statements_provider->getDiffMap(); $method_references_to_class_members = $file_reference_provider->getAllMethodReferencesToClassMembers(); $method_references_to_missing_class_members = $file_reference_provider->getAllMethodReferencesToMissingClassMembers(); $all_referencing_methods = $method_references_to_class_members + $method_references_to_missing_class_members; $nonmethod_references_to_classes = $file_reference_provider->getAllNonMethodReferencesToClasses(); $method_references_to_classes = $file_reference_provider->getAllMethodReferencesToClasses(); $method_param_uses = $file_reference_provider->getAllMethodParamUses(); $file_references_to_class_members = $file_reference_provider->getAllFileReferencesToClassMembers(); $file_references_to_missing_class_members = $file_reference_provider->getAllFileReferencesToMissingClassMembers(); $references_to_mixed_member_names = $file_reference_provider->getAllReferencesToMixedMemberNames(); $this->mixed_counts = $file_reference_provider->getTypeCoverage(); foreach ($changed_members as $file_path => $members_by_file) { foreach ($members_by_file as $changed_member => $_) { if (!\strpos($changed_member, '&')) { continue; } [$base_class, $trait] = \explode('&', $changed_member); foreach ($all_referencing_methods as $member_id => $_) { if (\strpos($member_id, $base_class . '::') !== 0) { continue; } $member_bit = \substr($member_id, \strlen($base_class) + 2); if (isset($all_referencing_methods[$trait . '::' . $member_bit])) { $changed_members[$file_path][$member_id] = \true; } } } } $newly_invalidated_methods = []; foreach ($unchanged_signature_members as $file_unchanged_signature_members) { $newly_invalidated_methods = \array_merge($newly_invalidated_methods, $file_unchanged_signature_members); foreach ($file_unchanged_signature_members as $unchanged_signature_member_id => $_) { // also check for things that might invalidate constructor property initialisation if (isset($all_referencing_methods[$unchanged_signature_member_id])) { foreach ($all_referencing_methods[$unchanged_signature_member_id] as $referencing_method_id => $_) { if (\substr($referencing_method_id, -13) === '::__construct') { $referencing_base_classlike = \explode('::', $referencing_method_id)[0]; $unchanged_signature_classlike = \explode('::', $unchanged_signature_member_id)[0]; if ($referencing_base_classlike === $unchanged_signature_classlike) { $newly_invalidated_methods[$referencing_method_id] = \true; } else { try { $referencing_storage = $codebase->classlike_storage_provider->get($referencing_base_classlike); } catch (\InvalidArgumentException $_) { // Workaround for #3671 $newly_invalidated_methods[$referencing_method_id] = \true; $referencing_storage = null; } if (isset($referencing_storage->used_traits[$unchanged_signature_classlike]) || isset($referencing_storage->parent_classes[$unchanged_signature_classlike])) { $newly_invalidated_methods[$referencing_method_id] = \true; } } } } } } } foreach ($changed_members as $file_changed_members) { foreach ($file_changed_members as $member_id => $_) { $newly_invalidated_methods[$member_id] = \true; if (isset($all_referencing_methods[$member_id])) { $newly_invalidated_methods = \array_merge($all_referencing_methods[$member_id], $newly_invalidated_methods); } unset($method_references_to_class_members[$member_id], $file_references_to_class_members[$member_id], $method_references_to_missing_class_members[$member_id], $file_references_to_missing_class_members[$member_id], $references_to_mixed_member_names[$member_id], $method_param_uses[$member_id]); $member_stub = \preg_replace('/::.*$/', '::*', $member_id); if (isset($all_referencing_methods[$member_stub])) { $newly_invalidated_methods = \array_merge($all_referencing_methods[$member_stub], $newly_invalidated_methods); } } } foreach ($newly_invalidated_methods as $method_id => $_) { foreach ($method_references_to_class_members as $i => $_) { unset($method_references_to_class_members[$i][$method_id]); } foreach ($method_references_to_classes as $i => $_) { unset($method_references_to_classes[$i][$method_id]); } foreach ($method_references_to_missing_class_members as $i => $_) { unset($method_references_to_missing_class_members[$i][$method_id]); } foreach ($references_to_mixed_member_names as $i => $_) { unset($references_to_mixed_member_names[$i][$method_id]); } foreach ($method_param_uses as $i => $_) { foreach ($method_param_uses[$i] as $j => $_) { unset($method_param_uses[$i][$j][$method_id]); } } } foreach ($this->analyzed_methods as $file_path => $analyzed_methods) { foreach ($analyzed_methods as $correct_method_id => $_) { $trait_safe_method_id = $correct_method_id; $correct_method_ids = \explode('&', $correct_method_id); $correct_method_id = $correct_method_ids[0]; if (isset($newly_invalidated_methods[$correct_method_id]) || isset($correct_method_ids[1]) && isset($newly_invalidated_methods[$correct_method_ids[1]])) { unset($this->analyzed_methods[$file_path][$trait_safe_method_id]); } } } $this->shiftFileOffsets($diff_map); foreach ($this->files_to_analyze as $file_path) { $file_reference_provider->clearExistingIssuesForFile($file_path); $file_reference_provider->clearExistingFileMapsForFile($file_path); $this->setMixedCountsForFile($file_path, [0, 0]); foreach ($file_references_to_class_members as $i => $_) { unset($file_references_to_class_members[$i][$file_path]); } foreach ($nonmethod_references_to_classes as $i => $_) { unset($nonmethod_references_to_classes[$i][$file_path]); } foreach ($references_to_mixed_member_names as $i => $_) { unset($references_to_mixed_member_names[$i][$file_path]); } foreach ($file_references_to_missing_class_members as $i => $_) { unset($file_references_to_missing_class_members[$i][$file_path]); } } foreach ($this->existing_issues as $file_path => $issues) { if (!isset($this->files_to_analyze[$file_path])) { unset($this->existing_issues[$file_path]); if ($this->file_provider->fileExists($file_path)) { \Psalm\IssueBuffer::addIssues([$file_path => \array_values($issues)]); } } } $method_references_to_class_members = \array_filter($method_references_to_class_members); $method_references_to_missing_class_members = \array_filter($method_references_to_missing_class_members); $file_references_to_class_members = \array_filter($file_references_to_class_members); $file_references_to_missing_class_members = \array_filter($file_references_to_missing_class_members); $references_to_mixed_member_names = \array_filter($references_to_mixed_member_names); $nonmethod_references_to_classes = \array_filter($nonmethod_references_to_classes); $method_references_to_classes = \array_filter($method_references_to_classes); $method_param_uses = \array_filter($method_param_uses); $file_reference_provider->setCallingMethodReferencesToClassMembers($method_references_to_class_members); $file_reference_provider->setFileReferencesToClassMembers($file_references_to_class_members); $file_reference_provider->setCallingMethodReferencesToMissingClassMembers($method_references_to_missing_class_members); $file_reference_provider->setFileReferencesToMissingClassMembers($file_references_to_missing_class_members); $file_reference_provider->setReferencesToMixedMemberNames($references_to_mixed_member_names); $file_reference_provider->setCallingMethodReferencesToClasses($method_references_to_classes); $file_reference_provider->setNonMethodReferencesToClasses($nonmethod_references_to_classes); $file_reference_provider->setMethodParamUses($method_param_uses); } /** * @param array> $diff_map * */ public function shiftFileOffsets(array $diff_map) : void { foreach ($this->existing_issues as $file_path => &$file_issues) { if (!isset($this->analyzed_methods[$file_path])) { continue; } $file_diff_map = $diff_map[$file_path] ?? []; if (!$file_diff_map) { continue; } $first_diff_offset = $file_diff_map[0][0]; $last_diff_offset = $file_diff_map[\count($file_diff_map) - 1][1]; foreach ($file_issues as $i => &$issue_data) { if ($issue_data->to < $first_diff_offset || $issue_data->from > $last_diff_offset) { unset($file_issues[$i]); continue; } $matched = \false; foreach ($file_diff_map as [$from, $to, $file_offset, $line_offset]) { if ($issue_data->from >= $from && $issue_data->from <= $to && !$matched) { $issue_data->from += $file_offset; $issue_data->to += $file_offset; $issue_data->snippet_from += $file_offset; $issue_data->snippet_to += $file_offset; $issue_data->line_from += $line_offset; $issue_data->line_to += $line_offset; $matched = \true; } } if (!$matched) { unset($file_issues[$i]); } } } foreach ($this->reference_map as $file_path => &$reference_map) { if (!isset($this->analyzed_methods[$file_path])) { unset($this->reference_map[$file_path]); continue; } $file_diff_map = $diff_map[$file_path] ?? []; if (!$file_diff_map) { continue; } $first_diff_offset = $file_diff_map[0][0]; $last_diff_offset = $file_diff_map[\count($file_diff_map) - 1][1]; foreach ($reference_map as $reference_from => [$reference_to, $tag]) { if ($reference_to < $first_diff_offset || $reference_from > $last_diff_offset) { continue; } foreach ($file_diff_map as [$from, $to, $file_offset]) { if ($reference_from >= $from && $reference_from <= $to) { unset($reference_map[$reference_from]); $reference_map[$reference_from += $file_offset] = [$reference_to += $file_offset, $tag]; } } } } foreach ($this->type_map as $file_path => &$type_map) { if (!isset($this->analyzed_methods[$file_path])) { unset($this->type_map[$file_path]); continue; } $file_diff_map = $diff_map[$file_path] ?? []; if (!$file_diff_map) { continue; } $first_diff_offset = $file_diff_map[0][0]; $last_diff_offset = $file_diff_map[\count($file_diff_map) - 1][1]; foreach ($type_map as $type_from => [$type_to, $tag]) { if ($type_to < $first_diff_offset || $type_from > $last_diff_offset) { continue; } foreach ($file_diff_map as [$from, $to, $file_offset]) { if ($type_from >= $from && $type_from <= $to) { unset($type_map[$type_from]); $type_map[$type_from += $file_offset] = [$type_to += $file_offset, $tag]; } } } } foreach ($this->argument_map as $file_path => &$argument_map) { if (!isset($this->analyzed_methods[$file_path])) { unset($this->argument_map[$file_path]); continue; } $file_diff_map = $diff_map[$file_path] ?? []; if (!$file_diff_map) { continue; } $first_diff_offset = $file_diff_map[0][0]; $last_diff_offset = $file_diff_map[\count($file_diff_map) - 1][1]; foreach ($argument_map as $argument_from => [$argument_to, $method_id, $argument_number]) { if ($argument_to < $first_diff_offset || $argument_from > $last_diff_offset) { continue; } foreach ($file_diff_map as [$from, $to, $file_offset]) { if ($argument_from >= $from && $argument_from <= $to) { unset($argument_map[$argument_from]); $argument_map[$argument_from += $file_offset] = [$argument_to += $file_offset, $method_id, $argument_number]; } } } } } /** * @return array> */ public function getMixedMemberNames() : array { return $this->mixed_member_names; } public function addMixedMemberName(string $member_id, string $reference) : void { $this->mixed_member_names[$member_id][$reference] = \true; } public function hasMixedMemberName(string $member_id) : bool { return isset($this->mixed_member_names[$member_id]); } /** * @param array> $names * */ public function addMixedMemberNames(array $names) : void { foreach ($names as $key => $name) { if (isset($this->mixed_member_names[$key])) { $this->mixed_member_names[$key] = \array_merge($this->mixed_member_names[$key], $name); } else { $this->mixed_member_names[$key] = $name; } } } /** * @return array{0:int, 1:int} */ public function getMixedCountsForFile(string $file_path) : array { if (!isset($this->mixed_counts[$file_path])) { $this->mixed_counts[$file_path] = [0, 0]; } return $this->mixed_counts[$file_path]; } /** * @param array{0:int, 1:int} $mixed_counts * */ public function setMixedCountsForFile(string $file_path, array $mixed_counts) : void { $this->mixed_counts[$file_path] = $mixed_counts; } public function incrementMixedCount(string $file_path) : void { if (!$this->count_mixed) { return; } if (!isset($this->mixed_counts[$file_path])) { $this->mixed_counts[$file_path] = [0, 0]; } ++$this->mixed_counts[$file_path][0]; } public function decrementMixedCount(string $file_path) : void { if (!$this->count_mixed) { return; } if (!isset($this->mixed_counts[$file_path])) { return; } --$this->mixed_counts[$file_path][0]; } public function incrementNonMixedCount(string $file_path) : void { if (!$this->count_mixed) { return; } if (!isset($this->mixed_counts[$file_path])) { $this->mixed_counts[$file_path] = [0, 0]; } ++$this->mixed_counts[$file_path][1]; } /** * @return array */ public function getMixedCounts() : array { $all_deep_scanned_files = []; foreach ($this->files_to_analyze as $file_path => $_) { $all_deep_scanned_files[$file_path] = \true; } return \array_intersect_key($this->mixed_counts, $all_deep_scanned_files); } /** * @return array */ public function getFunctionTimings() : array { return $this->function_timings; } public function addFunctionTiming(string $function_id, float $time_per_node) : void { $this->function_timings[$function_id] = $time_per_node; } public function addNodeType(string $file_path, \_HumbugBoxd02f763d3c56\PhpParser\Node $node, string $node_type, \_HumbugBoxd02f763d3c56\PhpParser\Node $parent_node = null) : void { if (!$node_type) { throw new \UnexpectedValueException('non-empty node_type expected'); } $this->type_map[$file_path][(int) $node->getAttribute('startFilePos')] = [($parent_node ? (int) $parent_node->getAttribute('endFilePos') : (int) $node->getAttribute('endFilePos')) + 1, $node_type]; } public function addNodeArgument(string $file_path, int $start_position, int $end_position, string $reference, int $argument_number) : void { if (!$reference) { throw new \UnexpectedValueException('non-empty node_type expected'); } $this->argument_map[$file_path][$start_position] = [$end_position, $reference, $argument_number]; } public function addNodeReference(string $file_path, \_HumbugBoxd02f763d3c56\PhpParser\Node $node, string $reference) : void { if (!$reference) { throw new \UnexpectedValueException('non-empty node_type expected'); } $this->reference_map[$file_path][(int) $node->getAttribute('startFilePos')] = [(int) $node->getAttribute('endFilePos') + 1, $reference]; } public function addOffsetReference(string $file_path, int $start, int $end, string $reference) : void { if (!$reference) { throw new \UnexpectedValueException('non-empty node_type expected'); } $this->reference_map[$file_path][$start] = [$end, $reference]; } /** * @return array{int, int} */ public function getTotalTypeCoverage(\Psalm\Codebase $codebase) : array { $mixed_count = 0; $nonmixed_count = 0; foreach ($codebase->file_reference_provider->getTypeCoverage() as $file_path => $counts) { if (!$this->config->reportTypeStatsForFile($file_path)) { continue; } [$path_mixed_count, $path_nonmixed_count] = $counts; if (isset($this->mixed_counts[$file_path])) { $mixed_count += $path_mixed_count; $nonmixed_count += $path_nonmixed_count; } } return [$mixed_count, $nonmixed_count]; } public function getTypeInferenceSummary(\Psalm\Codebase $codebase) : string { $all_deep_scanned_files = []; foreach ($this->files_to_analyze as $file_path => $_) { $all_deep_scanned_files[$file_path] = \true; foreach ($this->file_storage_provider->get($file_path)->required_file_paths as $required_file_path) { $all_deep_scanned_files[$required_file_path] = \true; } } [$mixed_count, $nonmixed_count] = $this->getTotalTypeCoverage($codebase); $total = $mixed_count + $nonmixed_count; $total_files = \count($all_deep_scanned_files); if (!$total_files) { return 'No files analyzed'; } if (!$total) { return 'Psalm was unable to infer types in the codebase'; } $percentage = $nonmixed_count === $total ? '100' : \number_format(100 * $nonmixed_count / $total, 4); return 'Psalm was able to infer types for ' . $percentage . '%' . ' of the codebase'; } public function getNonMixedStats() : string { $stats = ''; $all_deep_scanned_files = []; foreach ($this->files_to_analyze as $file_path => $_) { $all_deep_scanned_files[$file_path] = \true; if (!$this->config->reportTypeStatsForFile($file_path)) { continue; } foreach ($this->file_storage_provider->get($file_path)->required_file_paths as $required_file_path) { $all_deep_scanned_files[$required_file_path] = \true; } } foreach ($all_deep_scanned_files as $file_path => $_) { if (isset($this->mixed_counts[$file_path])) { [$path_mixed_count, $path_nonmixed_count] = $this->mixed_counts[$file_path]; if ($path_mixed_count + $path_nonmixed_count) { $stats .= \number_format(100 * $path_nonmixed_count / ($path_mixed_count + $path_nonmixed_count), 0) . '% ' . $this->config->shortenFileName($file_path) . ' (' . $path_mixed_count . ' mixed)' . "\n"; } } } return $stats; } public function disableMixedCounts() : void { $this->count_mixed = \false; } public function enableMixedCounts() : void { $this->count_mixed = \true; } public function updateFile(string $file_path, bool $dry_run) : void { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($file_path, \Psalm\Internal\FileManipulation\FunctionDocblockManipulator::getManipulationsForFile($file_path)); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($file_path, \Psalm\Internal\FileManipulation\PropertyDocblockManipulator::getManipulationsForFile($file_path)); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($file_path, \Psalm\Internal\FileManipulation\ClassDocblockManipulator::getManipulationsForFile($file_path)); $file_manipulations = \Psalm\Internal\FileManipulation\FileManipulationBuffer::getManipulationsForFile($file_path); if (!$file_manipulations) { return; } \usort($file_manipulations, function (\Psalm\FileManipulation $a, \Psalm\FileManipulation $b) : int { if ($b->end === $a->end) { if ($a->start === $b->start) { return $b->insertion_text > $a->insertion_text ? 1 : -1; } return $b->start > $a->start ? 1 : -1; } return $b->end > $a->end ? 1 : -1; }); $last_start = \PHP_INT_MAX; $existing_contents = $this->file_provider->getContents($file_path); foreach ($file_manipulations as $manipulation) { if ($manipulation->start <= $last_start) { $existing_contents = $manipulation->transform($existing_contents); $last_start = $manipulation->start; } } if ($dry_run) { echo $file_path . ':' . "\n"; $differ = new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Differ(new \_HumbugBoxd02f763d3c56\SebastianBergmann\Diff\Output\StrictUnifiedDiffOutputBuilder(['fromFile' => $file_path, 'toFile' => $file_path])); echo $differ->diff($this->file_provider->getContents($file_path), $existing_contents); return; } $this->progress->alterFileDone($file_path); $this->file_provider->setContents($file_path, $existing_contents); } /** * @return list */ public function getExistingIssuesForFile(string $file_path, int $start, int $end, ?string $issue_type = null) : array { if (!isset($this->existing_issues[$file_path])) { return []; } $applicable_issues = []; foreach ($this->existing_issues[$file_path] as $issue_data) { if ($issue_data->from >= $start && $issue_data->from <= $end) { if ($issue_type === null || $issue_type === $issue_data->type) { $applicable_issues[] = $issue_data; } } } return $applicable_issues; } public function removeExistingDataForFile(string $file_path, int $start, int $end, ?string $issue_type = null) : void { if (isset($this->existing_issues[$file_path])) { foreach ($this->existing_issues[$file_path] as $i => $issue_data) { if ($issue_data->from >= $start && $issue_data->from <= $end) { if ($issue_type === null || $issue_type === $issue_data->type) { unset($this->existing_issues[$file_path][$i]); } } } } if (isset($this->type_map[$file_path])) { foreach ($this->type_map[$file_path] as $map_start => $_) { if ($map_start >= $start && $map_start <= $end) { unset($this->type_map[$file_path][$map_start]); } } } if (isset($this->reference_map[$file_path])) { foreach ($this->reference_map[$file_path] as $map_start => $_) { if ($map_start >= $start && $map_start <= $end) { unset($this->reference_map[$file_path][$map_start]); } } } if (isset($this->argument_map[$file_path])) { foreach ($this->argument_map[$file_path] as $map_start => $_) { if ($map_start >= $start && $map_start <= $end) { unset($this->argument_map[$file_path][$map_start]); } } } } /** * @return array> */ public function getAnalyzedMethods() : array { return $this->analyzed_methods; } /** * @return array */ public function getFileMaps() : array { $file_maps = []; foreach ($this->reference_map as $file_path => $reference_map) { $file_maps[$file_path] = [$reference_map, [], []]; } foreach ($this->type_map as $file_path => $type_map) { if (isset($file_maps[$file_path])) { $file_maps[$file_path][1] = $type_map; } else { $file_maps[$file_path] = [[], $type_map, []]; } } foreach ($this->argument_map as $file_path => $argument_map) { if (isset($file_maps[$file_path])) { $file_maps[$file_path][2] = $argument_map; } else { $file_maps[$file_path] = [[], [], $argument_map]; } } return $file_maps; } /** * @return FileMapType */ public function getMapsForFile(string $file_path) : array { return [$this->reference_map[$file_path] ?? [], $this->type_map[$file_path] ?? [], $this->argument_map[$file_path] ?? []]; } /** * @return array> */ public function getPossibleMethodParamTypes() : array { return $this->possible_method_param_types; } public function addMutableClass(string $fqcln) : void { $this->mutable_classes[\strtolower($fqcln)] = \true; } public function setAnalyzedMethod(string $file_path, string $method_id, bool $is_constructor = \false) : void { $this->analyzed_methods[$file_path][$method_id] = $is_constructor ? 2 : 1; } public function isMethodAlreadyAnalyzed(string $file_path, string $method_id, bool $is_constructor = \false) : bool { if ($is_constructor) { return isset($this->analyzed_methods[$file_path][$method_id]) && $this->analyzed_methods[$file_path][$method_id] === 2; } return isset($this->analyzed_methods[$file_path][$method_id]); } } */ private static $builtin_functions = []; public function __construct(\Psalm\Internal\Provider\ClassLikeStorageProvider $storage_provider, \Psalm\Codebase $codebase) { $this->storage_provider = $storage_provider; $this->codebase = $codebase; self::$builtin_functions = []; } public function registerClass(\ReflectionClass $reflected_class) : void { $class_name = $reflected_class->name; if ($class_name === 'LibXMLError') { $class_name = 'libXMLError'; } $class_name_lower = \strtolower($class_name); try { $this->storage_provider->get($class_name_lower); return; } catch (\Exception $e) { // this is fine } $reflected_parent_class = $reflected_class->getParentClass(); $storage = $this->storage_provider->create($class_name); $storage->abstract = $reflected_class->isAbstract(); $storage->is_interface = $reflected_class->isInterface(); /** @psalm-suppress PropertyTypeCoercion */ $storage->potential_declaring_method_ids['__construct'][$class_name_lower . '::__construct'] = \true; if ($reflected_parent_class) { $parent_class_name = $reflected_parent_class->getName(); $this->registerClass($reflected_parent_class); $parent_class_name_lc = \strtolower($parent_class_name); $parent_storage = $this->storage_provider->get($parent_class_name_lc); $this->registerInheritedMethods($class_name_lower, $parent_class_name_lc); $this->registerInheritedProperties($class_name_lower, $parent_class_name_lc); $storage->class_implements = $parent_storage->class_implements; $storage->constants = $parent_storage->constants; $storage->parent_classes = \array_merge([$parent_class_name_lc => $parent_class_name], $parent_storage->parent_classes); $storage->used_traits = $parent_storage->used_traits; } $class_properties = $reflected_class->getProperties(); $public_mapped_properties = \Psalm\Internal\Codebase\PropertyMap::inPropertyMap($class_name) ? \Psalm\Internal\Codebase\PropertyMap::getPropertyMap()[\strtolower($class_name)] : []; foreach ($class_properties as $class_property) { $property_name = $class_property->getName(); $storage->properties[$property_name] = new \Psalm\Storage\PropertyStorage(); $storage->properties[$property_name]->type = \Psalm\Type::getMixed(); if ($class_property->isStatic()) { $storage->properties[$property_name]->is_static = \true; } if ($class_property->isPublic()) { $storage->properties[$property_name]->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; } elseif ($class_property->isProtected()) { $storage->properties[$property_name]->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED; } elseif ($class_property->isPrivate()) { $storage->properties[$property_name]->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE; } $property_id = (string) $class_property->class . '::$' . $property_name; $storage->declaring_property_ids[$property_name] = (string) $class_property->class; $storage->appearing_property_ids[$property_name] = $property_id; if (!$class_property->isPrivate()) { $storage->inheritable_property_ids[$property_name] = $property_id; } } // have to do this separately as there can be new properties here foreach ($public_mapped_properties as $property_name => $type_string) { $property_id = $class_name . '::$' . $property_name; if (!isset($storage->properties[$property_name])) { $storage->properties[$property_name] = new \Psalm\Storage\PropertyStorage(); $storage->properties[$property_name]->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; $storage->declaring_property_ids[$property_name] = $class_name; $storage->appearing_property_ids[$property_name] = $property_id; $storage->inheritable_property_ids[$property_name] = $property_id; } $type = \Psalm\Type::parseString($type_string); if ($property_id === 'DateInterval::$days') { $type->ignore_falsable_issues = \true; } $storage->properties[$property_name]->type = $type; } /** @var array */ $class_constants = $reflected_class->getConstants(); foreach ($class_constants as $name => $value) { $storage->constants[$name] = new \Psalm\Storage\ClassConstantStorage(\Psalm\Internal\Analyzer\ClassLikeAnalyzer::getTypeFromValue($value), \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC, null); } if ($reflected_class->isInterface()) { $this->codebase->classlikes->addFullyQualifiedInterfaceName($class_name); } elseif ($reflected_class->isTrait()) { $this->codebase->classlikes->addFullyQualifiedTraitName($class_name); } else { $this->codebase->classlikes->addFullyQualifiedClassName($class_name); } $reflection_methods = $reflected_class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED); if ($class_name_lower === 'generator') { $storage->template_types = ['TKey' => ['Generator' => [\Psalm\Type::getMixed()]], 'TValue' => ['Generator' => [\Psalm\Type::getMixed()]]]; } $interfaces = $reflected_class->getInterfaces(); foreach ($interfaces as $interface) { $interface_name = $interface->getName(); $this->registerClass($interface); if ($reflected_class->isInterface()) { $storage->parent_interfaces[\strtolower($interface_name)] = $interface_name; } else { $storage->class_implements[\strtolower($interface_name)] = $interface_name; } } foreach ($reflection_methods as $reflection_method) { $method_reflection_class = $reflection_method->getDeclaringClass(); $this->registerClass($method_reflection_class); $this->extractReflectionMethodInfo($reflection_method); if ($reflection_method->class !== $class_name && ($class_name !== 'SoapFault' || $reflection_method->name !== '__construct')) { $reflection_method_name = \strtolower($reflection_method->name); $reflection_method_class = $reflection_method->class; $this->codebase->methods->setDeclaringMethodId($class_name, $reflection_method_name, $reflection_method_class, $reflection_method_name); $this->codebase->methods->setAppearingMethodId($class_name, $reflection_method_name, $reflection_method_class, $reflection_method_name); } } } public function extractReflectionMethodInfo(\ReflectionMethod $method) : void { $method_name_lc = \strtolower($method->getName()); $fq_class_name = $method->class; $fq_class_name_lc = \strtolower($fq_class_name); $class_storage = $this->storage_provider->get($fq_class_name_lc); if (isset($class_storage->methods[$method_name_lc])) { return; } $method_id = $method->class . '::' . $method_name_lc; $storage = $class_storage->methods[$method_name_lc] = new \Psalm\Storage\MethodStorage(); $storage->cased_name = $method->name; $storage->defining_fqcln = $method->class; if ($method_name_lc === $fq_class_name_lc) { $this->codebase->methods->setDeclaringMethodId($fq_class_name, '__construct', $fq_class_name, $method_name_lc); $this->codebase->methods->setAppearingMethodId($fq_class_name, '__construct', $fq_class_name, $method_name_lc); } $declaring_class = $method->getDeclaringClass(); $storage->is_static = $method->isStatic(); $storage->abstract = $method->isAbstract(); $storage->mutation_free = $storage->external_mutation_free = $method_name_lc === '__construct' && $fq_class_name_lc === 'datetimezone'; $class_storage->declaring_method_ids[$method_name_lc] = new \Psalm\Internal\MethodIdentifier($declaring_class->name, $method_name_lc); $class_storage->inheritable_method_ids[$method_name_lc] = $class_storage->declaring_method_ids[$method_name_lc]; $class_storage->appearing_method_ids[$method_name_lc] = $class_storage->declaring_method_ids[$method_name_lc]; $class_storage->overridden_method_ids[$method_name_lc] = []; $storage->visibility = $method->isPrivate() ? \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE : ($method->isProtected() ? \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED : \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC); $callables = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallablesFromCallMap($method_id); if ($callables && $callables[0]->params !== null && $callables[0]->return_type !== null) { $storage->params = []; foreach ($callables[0]->params as $param) { if ($param->type) { $param->type->queueClassLikesForScanning($this->codebase); } } $storage->params = $callables[0]->params; $storage->return_type = $callables[0]->return_type; $storage->return_type->queueClassLikesForScanning($this->codebase); } else { $params = $method->getParameters(); $storage->params = []; foreach ($params as $param) { $param_array = $this->getReflectionParamData($param); $storage->params[] = $param_array; $storage->param_lookup[$param->name] = \true; } } $storage->required_param_count = 0; foreach ($storage->params as $i => $param) { if (!$param->is_optional && !$param->is_variadic) { $storage->required_param_count = $i + 1; } } } private function getReflectionParamData(\ReflectionParameter $param) : \Psalm\Storage\FunctionLikeParameter { $param_type = self::getPsalmTypeFromReflectionType($param->getType()); $param_name = (string) $param->getName(); $is_optional = (bool) $param->isOptional(); $parameter = new \Psalm\Storage\FunctionLikeParameter($param_name, (bool) $param->isPassedByReference(), $param_type, null, null, $is_optional, $param_type->isNullable(), $param->isVariadic()); $parameter->signature_type = \Psalm\Type::getMixed(); return $parameter; } /** * @param callable-string $function_id * * @return false|null */ public function registerFunction(string $function_id) : ?bool { try { $reflection_function = new \ReflectionFunction($function_id); $callmap_callable = null; if (isset(self::$builtin_functions[$function_id])) { return null; } $storage = self::$builtin_functions[$function_id] = new \Psalm\Storage\FunctionStorage(); if (\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($function_id)) { $callmap_callable = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallableFromCallMapById($this->codebase, $function_id, [], null); } if ($callmap_callable !== null && $callmap_callable->params !== null && $callmap_callable->return_type !== null) { $storage->params = $callmap_callable->params; $storage->return_type = $callmap_callable->return_type; } else { $reflection_params = $reflection_function->getParameters(); foreach ($reflection_params as $param) { $param_obj = $this->getReflectionParamData($param); $storage->params[] = $param_obj; } if ($reflection_return_type = $reflection_function->getReturnType()) { $storage->return_type = self::getPsalmTypeFromReflectionType($reflection_return_type); } } $storage->pure = \true; $storage->required_param_count = 0; foreach ($storage->params as $i => $param) { if (!$param->is_optional && !$param->is_variadic) { $storage->required_param_count = $i + 1; } } $storage->cased_name = $reflection_function->getName(); } catch (\ReflectionException $e) { return \false; } return null; } public static function getPsalmTypeFromReflectionType(?\ReflectionType $reflection_type = null) : \Psalm\Type\Union { if (!$reflection_type) { return \Psalm\Type::getMixed(); } $suffix = ''; if ($reflection_type->allowsNull()) { $suffix = '|null'; } return \Psalm\Type::parseString($reflection_type->getName() . $suffix); } private function registerInheritedMethods(string $fq_class_name, string $parent_class) : void { $parent_storage = $this->storage_provider->get($parent_class); $storage = $this->storage_provider->get($fq_class_name); // register where they appear (can never be in a trait) foreach ($parent_storage->appearing_method_ids as $method_name => $appearing_method_id) { $storage->appearing_method_ids[$method_name] = $appearing_method_id; } // register where they're declared foreach ($parent_storage->inheritable_method_ids as $method_name => $declaring_method_id) { $storage->declaring_method_ids[$method_name] = $declaring_method_id; $storage->inheritable_method_ids[$method_name] = $declaring_method_id; $storage->overridden_method_ids[$method_name][$declaring_method_id->fq_class_name] = $declaring_method_id; } } /** * @param lowercase-string $fq_class_name * @param lowercase-string $parent_class * */ private function registerInheritedProperties(string $fq_class_name, string $parent_class) : void { $parent_storage = $this->storage_provider->get($parent_class); $storage = $this->storage_provider->get($fq_class_name); // register where they appear (can never be in a trait) foreach ($parent_storage->appearing_property_ids as $property_name => $appearing_property_id) { if (!$parent_storage->is_trait && isset($parent_storage->properties[$property_name]) && $parent_storage->properties[$property_name]->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { continue; } $storage->appearing_property_ids[$property_name] = $appearing_property_id; } // register where they're declared foreach ($parent_storage->declaring_property_ids as $property_name => $declaring_property_class) { if (!$parent_storage->is_trait && isset($parent_storage->properties[$property_name]) && $parent_storage->properties[$property_name]->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { continue; } $storage->declaring_property_ids[$property_name] = \strtolower($declaring_property_class); } // register where they're declared foreach ($parent_storage->inheritable_property_ids as $property_name => $inheritable_property_id) { if (!$parent_storage->is_trait && isset($parent_storage->properties[$property_name]) && $parent_storage->properties[$property_name]->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { continue; } $storage->inheritable_property_ids[$property_name] = $inheritable_property_id; } } public function hasFunction(string $function_id) : bool { return isset(self::$builtin_functions[$function_id]); } public function getFunctionStorage(string $function_id) : \Psalm\Storage\FunctionStorage { if (isset(self::$builtin_functions[$function_id])) { return self::$builtin_functions[$function_id]; } throw new \UnexpectedValueException('Expecting to have a function for ' . $function_id); } public static function clearCache() : void { self::$builtin_functions = []; } } id] = \true; $child_nodes = $this->getChildNodes($source, $visited_source_ids); if ($child_nodes === null) { return \true; } $new_sources = \array_merge($new_sources, $child_nodes); } $sources = $new_sources; } return \false; } /** * @param array $visited_source_ids * @return array|null */ private function getChildNodes(\Psalm\Internal\DataFlow\DataFlowNode $generated_source, array $visited_source_ids) : ?array { $new_sources = []; if (!isset($this->forward_edges[$generated_source->id])) { return []; } foreach ($this->forward_edges[$generated_source->id] as $to_id => $path) { $path_type = $path->type; if ($path->type === 'variable-use' || $path->type === 'closure-use' || $path->type === 'global-use' || $path->type === 'use-inside-instance-property' || $path->type === 'use-inside-static-property' || $path->type === 'use-inside-call' || $path->type === 'use-inside-conditional' || $path->type === 'use-inside-isset' || $path->type === 'arg') { return null; } if (isset($visited_source_ids[$to_id])) { continue; } if (self::shouldIgnoreFetch($path_type, 'array', $generated_source->path_types)) { continue; } if (self::shouldIgnoreFetch($path_type, 'property', $generated_source->path_types)) { continue; } $new_destination = new \Psalm\Internal\DataFlow\DataFlowNode($to_id, $to_id, null); $new_destination->path_types = \array_merge($generated_source->path_types, [$path_type]); $new_sources[$to_id] = $new_destination; } return $new_sources; } } classlike_storage_provider = $storage_provider; $this->file_reference_provider = $file_reference_provider; $this->property_existence_provider = new \Psalm\Internal\Provider\PropertyExistenceProvider(); $this->property_visibility_provider = new \Psalm\Internal\Provider\PropertyVisibilityProvider(); $this->property_type_provider = new \Psalm\Internal\Provider\PropertyTypeProvider(); } /** * Whether or not a given property exists * */ public function propertyExists(string $property_id, bool $read_mode, ?\Psalm\StatementsSource $source = null, ?\Psalm\Context $context = null, ?\Psalm\CodeLocation $code_location = null) : bool { // remove trailing backslash if it exists $property_id = \preg_replace('/^\\\\/', '', $property_id); [$fq_class_name, $property_name] = \explode('::$', $property_id); $fq_class_name_lc = \strtolower($fq_class_name); if ($this->property_existence_provider->has($fq_class_name)) { $property_exists = $this->property_existence_provider->doesPropertyExist($fq_class_name, $property_name, $read_mode, $source, $context, $code_location); if ($property_exists !== null) { return $property_exists; } } $class_storage = $this->classlike_storage_provider->get($fq_class_name); if ($source && $context && $context->self !== $fq_class_name && !$context->collect_initializations && !$context->collect_mutations) { if ($context->calling_method_id) { $this->file_reference_provider->addMethodReferenceToClass($context->calling_method_id, $fq_class_name_lc); } else { $this->file_reference_provider->addNonMethodReferenceToClass($source->getFilePath(), $fq_class_name_lc); } } if (isset($class_storage->declaring_property_ids[$property_name])) { $declaring_property_class = $class_storage->declaring_property_ids[$property_name]; if ($context && $context->calling_method_id) { $this->file_reference_provider->addMethodReferenceToClassMember($context->calling_method_id, \strtolower($declaring_property_class) . '::$' . $property_name); } elseif ($source) { $this->file_reference_provider->addFileReferenceToClassMember($source->getFilePath(), \strtolower($declaring_property_class) . '::$' . $property_name); } if ($this->collect_locations && $code_location) { $this->file_reference_provider->addCallingLocationForClassProperty($code_location, \strtolower($declaring_property_class) . '::$' . $property_name); } return \true; } if ($context && $context->calling_method_id) { $this->file_reference_provider->addMethodReferenceToMissingClassMember($context->calling_method_id, $fq_class_name_lc . '::$' . $property_name); } elseif ($source) { $this->file_reference_provider->addFileReferenceToMissingClassMember($source->getFilePath(), $fq_class_name_lc . '::$' . $property_name); } return \false; } public function getDeclaringClassForProperty(string $property_id, bool $read_mode, ?\Psalm\StatementsSource $source = null) : ?string { [$fq_class_name, $property_name] = \explode('::$', $property_id); if ($this->property_existence_provider->has($fq_class_name)) { if ($this->property_existence_provider->doesPropertyExist($fq_class_name, $property_name, $read_mode, $source, null)) { return $fq_class_name; } } $class_storage = $this->classlike_storage_provider->get($fq_class_name); if (isset($class_storage->declaring_property_ids[$property_name])) { return $class_storage->declaring_property_ids[$property_name]; } return null; } /** * Get the class this property appears in (vs is declared in, which could give a trait) */ public function getAppearingClassForProperty(string $property_id, bool $read_mode, ?\Psalm\StatementsSource $source = null) : ?string { [$fq_class_name, $property_name] = \explode('::$', $property_id); if ($this->property_existence_provider->has($fq_class_name)) { if ($this->property_existence_provider->doesPropertyExist($fq_class_name, $property_name, $read_mode, $source, null)) { return $fq_class_name; } } $class_storage = $this->classlike_storage_provider->get($fq_class_name); if (isset($class_storage->appearing_property_ids[$property_name])) { $appearing_property_id = $class_storage->appearing_property_ids[$property_name]; return \explode('::$', $appearing_property_id)[0]; } return null; } public function getStorage(string $property_id) : \Psalm\Storage\PropertyStorage { // remove trailing backslash if it exists $property_id = \preg_replace('/^\\\\/', '', $property_id); [$fq_class_name, $property_name] = \explode('::$', $property_id); $class_storage = $this->classlike_storage_provider->get($fq_class_name); if (isset($class_storage->declaring_property_ids[$property_name])) { $declaring_property_class = $class_storage->declaring_property_ids[$property_name]; $declaring_class_storage = $this->classlike_storage_provider->get($declaring_property_class); if (isset($declaring_class_storage->properties[$property_name])) { return $declaring_class_storage->properties[$property_name]; } } throw new \UnexpectedValueException('Property ' . $property_id . ' should exist'); } public function getPropertyType(string $property_id, bool $property_set, ?\Psalm\StatementsSource $source = null, ?\Psalm\Context $context = null) : ?\Psalm\Type\Union { // remove trailing backslash if it exists $property_id = \preg_replace('/^\\\\/', '', $property_id); [$fq_class_name, $property_name] = \explode('::$', $property_id); if ($this->property_type_provider->has($fq_class_name)) { $property_type = $this->property_type_provider->getPropertyType($fq_class_name, $property_name, !$property_set, $source, $context); if ($property_type !== null) { return $property_type; } } $class_storage = $this->classlike_storage_provider->get($fq_class_name); if (isset($class_storage->declaring_property_ids[$property_name])) { $declaring_property_class = $class_storage->declaring_property_ids[$property_name]; $declaring_class_storage = $this->classlike_storage_provider->get($declaring_property_class); if (isset($declaring_class_storage->properties[$property_name])) { $storage = $declaring_class_storage->properties[$property_name]; } else { throw new \UnexpectedValueException('Property ' . $property_id . ' should exist'); } } else { throw new \UnexpectedValueException('Property ' . $property_id . ' should exist'); } if ($storage->type) { if ($property_set) { if (isset($class_storage->pseudo_property_set_types[$property_name])) { return $class_storage->pseudo_property_set_types[$property_name]; } } else { if (isset($class_storage->pseudo_property_get_types[$property_name])) { return $class_storage->pseudo_property_get_types[$property_name]; } } return $storage->type; } if (!isset($class_storage->overridden_property_ids[$property_name])) { return null; } foreach ($class_storage->overridden_property_ids[$property_name] as $overridden_property_id) { $overridden_storage = $this->getStorage($overridden_property_id); if ($overridden_storage->type) { return $overridden_storage->type; } } return null; } } */ private $sources = []; /** @var array */ private $nodes = []; /** @var array */ private $sinks = []; /** @var array> */ private $specialized_calls = []; /** @var array> */ private $specializations = []; public function addNode(\Psalm\Internal\DataFlow\DataFlowNode $node) : void { $this->nodes[$node->id] = $node; if ($node->unspecialized_id && $node->specialization_key) { $this->specialized_calls[$node->specialization_key][$node->unspecialized_id] = \true; $this->specializations[$node->unspecialized_id][$node->specialization_key] = \true; } } public function addSource(\Psalm\Internal\DataFlow\TaintSource $node) : void { $this->sources[$node->id] = $node; } public function addSink(\Psalm\Internal\DataFlow\TaintSink $node) : void { $this->sinks[$node->id] = $node; // in the rare case the sink is the _next_ node, this is necessary $this->nodes[$node->id] = $node; } public function addGraph(self $taint) : void { $this->sources += $taint->sources; $this->sinks += $taint->sinks; $this->nodes += $taint->nodes; $this->specialized_calls += $taint->specialized_calls; foreach ($taint->forward_edges as $key => $map) { if (!isset($this->forward_edges[$key])) { $this->forward_edges[$key] = $map; } else { $this->forward_edges[$key] += $map; } } foreach ($taint->specializations as $key => $map) { if (!isset($this->specializations[$key])) { $this->specializations[$key] = $map; } else { $this->specializations[$key] += $map; } } } public function getPredecessorPath(\Psalm\Internal\DataFlow\DataFlowNode $source) : string { $location_summary = ''; if ($source->code_location) { $location_summary = $source->code_location->getShortSummary(); } $source_descriptor = $source->label . ($location_summary ? ' (' . $location_summary . ')' : ''); $previous_source = $source->previous; if ($previous_source) { if ($previous_source === $source) { return ''; } return $this->getPredecessorPath($previous_source) . ' -> ' . $source_descriptor; } return $source_descriptor; } public function getSuccessorPath(\Psalm\Internal\DataFlow\DataFlowNode $sink) : string { $location_summary = ''; if ($sink->code_location) { $location_summary = $sink->code_location->getShortSummary(); } $sink_descriptor = $sink->label . ($location_summary ? ' (' . $location_summary . ')' : ''); $next_sink = $sink->previous; if ($next_sink) { if ($next_sink === $sink) { return ''; } return $sink_descriptor . ' -> ' . $this->getSuccessorPath($next_sink); } return $sink_descriptor; } /** * @return list */ public function getIssueTrace(\Psalm\Internal\DataFlow\DataFlowNode $source) : array { $previous_source = $source->previous; $node = ['location' => $source->code_location, 'label' => $source->label, 'entry_path_type' => \end($source->path_types) ?: '']; if ($previous_source) { if ($previous_source === $source) { return []; } return \array_merge($this->getIssueTrace($previous_source), [$node]); } return [$node]; } public function connectSinksAndSources() : void { $visited_source_ids = []; $sources = $this->sources; $sinks = $this->sinks; for ($i = 0; \count($sinks) && \count($sources) && $i < 40; $i++) { $new_sources = []; foreach ($sources as $source) { $source_taints = $source->taints; \sort($source_taints); $visited_source_ids[$source->id][\implode(',', $source_taints)] = \true; $generated_sources = $this->getSpecializedSources($source); foreach ($generated_sources as $generated_source) { $new_sources = \array_merge($new_sources, $this->getChildNodes($generated_source, $source_taints, $sinks, $visited_source_ids)); } } $sources = $new_sources; } } /** * @param array $source_taints * @param array $sinks * @return array */ private function getChildNodes(\Psalm\Internal\DataFlow\DataFlowNode $generated_source, array $source_taints, array $sinks, array $visited_source_ids) : array { $new_sources = []; foreach ($this->forward_edges[$generated_source->id] as $to_id => $path) { $path_type = $path->type; $added_taints = $path->unescaped_taints ?: []; $removed_taints = $path->escaped_taints ?: []; if (!isset($this->nodes[$to_id])) { continue; } $new_taints = \array_unique(\array_diff(\array_merge($source_taints, $added_taints), $removed_taints)); \sort($new_taints); $destination_node = $this->nodes[$to_id]; if (isset($visited_source_ids[$to_id][\implode(',', $new_taints)])) { continue; } if (self::shouldIgnoreFetch($path_type, 'array', $generated_source->path_types)) { continue; } if (self::shouldIgnoreFetch($path_type, 'property', $generated_source->path_types)) { continue; } if (isset($sinks[$to_id])) { $matching_taints = \array_intersect($sinks[$to_id]->taints, $new_taints); if ($matching_taints && $generated_source->code_location) { $config = \Psalm\Config::getInstance(); if ($sinks[$to_id]->code_location && $config->reportIssueInFile('TaintedInput', $sinks[$to_id]->code_location->file_path)) { $issue_location = $sinks[$to_id]->code_location; } else { $issue_location = $generated_source->code_location; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TaintedInput('Detected tainted ' . \implode(', ', $matching_taints), $issue_location, $this->getIssueTrace($generated_source), $this->getPredecessorPath($generated_source) . ' -> ' . $this->getSuccessorPath($sinks[$to_id])))) { // fall through } continue; } } $new_destination = clone $destination_node; $new_destination->previous = $generated_source; $new_destination->taints = $new_taints; $new_destination->specialized_calls = $generated_source->specialized_calls; $new_destination->path_types = \array_merge($generated_source->path_types, [$path_type]); $new_sources[$to_id] = $new_destination; } return $new_sources; } /** @return array */ private function getSpecializedSources(\Psalm\Internal\DataFlow\DataFlowNode $source) : array { $generated_sources = []; if (isset($this->forward_edges[$source->id])) { return [$source]; } if ($source->specialization_key && isset($this->specialized_calls[$source->specialization_key])) { $generated_source = clone $source; $generated_source->specialized_calls[$source->specialization_key] = $this->specialized_calls[$source->specialization_key]; $generated_source->id = \substr($source->id, 0, -\strlen($source->specialization_key) - 1); $generated_sources[] = $generated_source; } elseif (isset($this->specializations[$source->id])) { foreach ($this->specializations[$source->id] as $specialization => $_) { if (!$source->specialized_calls || isset($source->specialized_calls[$specialization])) { $new_source = clone $source; $new_source->id = $source->id . '-' . $specialization; $generated_sources[] = $new_source; } } } else { foreach ($source->specialized_calls as $key => $map) { if (isset($map[$source->id]) && isset($this->forward_edges[$source->id . '-' . $key])) { $new_source = clone $source; $new_source->id = $source->id . '-' . $key; $generated_sources[] = $new_source; } } } return \array_filter($generated_sources, function ($new_source) : bool { return isset($this->forward_edges[$new_source->id]); }); } } >|null */ private static $property_map; /** * Gets the method/function call map * * @return array> */ public static function getPropertyMap() : array { if (self::$property_map !== null) { return self::$property_map; } /** @var array> */ $property_map = (require \dirname(__DIR__, 4) . '/dictionaries/PropertyMap.php'); self::$property_map = []; foreach ($property_map as $key => $value) { $cased_key = \strtolower($key); self::$property_map[$cased_key] = $value; } return self::$property_map; } public static function inPropertyMap(string $class_name) : bool { return isset(self::getPropertyMap()[\strtolower($class_name)]); } } */ public $params = []; /** * @var array */ public $params_out = []; /** * @var array{type:string, line_number: int}|null */ public $self_out; /** * @var array */ public $globals = []; /** * Whether or not the function is deprecated * * @var bool */ public $deprecated = \false; /** * If set, the function is internal to the given namespace. * * @var null|string */ public $psalm_internal = null; /** * Whether or not the function is internal * * @var bool */ public $internal = \false; /** * Whether or not the function uses get_args * * @var bool */ public $variadic = \false; /** * Whether or not the function is pure * * @var bool */ public $pure = \false; /** * Whether or not to specialize a given call (useful for taint analysis) * * @var bool */ public $specialize_call = \false; /** * Represents the flow from function params to return type * * @var array */ public $flows = []; /** * @var array */ public $added_taints = []; /** * @var array */ public $removed_taints = []; /** * @var array */ public $taint_sink_params = []; /** * @var array */ public $taint_source_types = []; /** * @var array */ public $assert_untainted_params = []; /** * Whether or not to ignore the nullability of this function's return type * * @var bool */ public $ignore_nullable_return = \false; /** * Whether or not to ignore the nullability of this function's return type * * @var bool */ public $ignore_falsable_return = \false; /** * @var array */ public $suppressed_issues = []; /** * @var array */ public $throws = []; /** * @var array */ public $templates = []; /** * @var array */ public $template_typeofs = []; /** * @var array */ public $assertions = []; /** * @var array */ public $if_true_assertions = []; /** * @var array */ public $if_false_assertions = []; /** * @var bool */ public $inheritdoc = \false; /** * @var bool */ public $mutation_free = \false; /** * @var bool */ public $external_mutation_free = \false; /** * @var bool */ public $no_named_args = \false; /** @var bool */ public $stub_override = \false; } file_path = $file_path; $this->file_name = $file_name; $this->will_analyze = $will_analyze; } public function scan(\Psalm\Codebase $codebase, \Psalm\Storage\FileStorage $file_storage, bool $storage_from_cache = \false, ?\Psalm\Progress\Progress $progress = null) : void { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } if ((!$this->will_analyze || $file_storage->deep_scan) && $storage_from_cache && !$codebase->register_stub_files) { return; } $stmts = $codebase->statements_provider->getStatementsForFile($file_storage->file_path, $codebase->php_major_version . '.' . $codebase->php_minor_version, $progress); foreach ($stmts as $stmt) { if (!$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike && !$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ && !($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression && $stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_)) { $file_storage->has_extra_statements = \true; break; } } if ($this->will_analyze) { $progress->debug('Deep scanning ' . $file_storage->file_path . "\n"); } else { $progress->debug('Scanning ' . $file_storage->file_path . "\n"); } $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $traverser->addVisitor(new \Psalm\Internal\PhpVisitor\ReflectorVisitor($codebase, $file_storage, $this)); $traverser->traverse($stmts); $file_storage->deep_scan = $this->will_analyze; } public function getFilePath() : string { return $this->file_path; } public function getFileName() : string { return $this->file_name; } public function getRootFilePath() : string { return $this->file_path; } public function getRootFileName() : string { return $this->file_name; } public function getAliases() : \Psalm\Aliases { return new \Psalm\Aliases(); } } > */ public $tags = []; /** @var array> */ public $combined_tags = []; /** * @var bool */ private static $shouldAddNewLineBetweenAnnotations = \true; /** @param array> $tags */ public function __construct(string $description, array $tags, string $first_line_padding = '') { $this->description = $description; $this->tags = $tags; $this->first_line_padding = $first_line_padding; } public function render(string $left_padding) : string { $doc_comment_text = '/**' . "\n"; $trimmed_description = \trim($this->description); if ($trimmed_description !== '') { $description_lines = \explode("\n", $this->description); foreach ($description_lines as $line) { $doc_comment_text .= $left_padding . ' *' . (\trim($line) ? ' ' . $line : '') . "\n"; } } if ($this->tags) { if ($trimmed_description !== '') { $doc_comment_text .= $left_padding . ' *' . "\n"; } $last_type = null; foreach ($this->tags as $type => $lines) { if ($last_type !== null && $last_type !== 'psalm-return' && static::shouldAddNewLineBetweenAnnotations()) { $doc_comment_text .= $left_padding . ' *' . "\n"; } foreach ($lines as $line) { $doc_comment_text .= $left_padding . ' * @' . $type . ($line !== '' ? ' ' . $line : '') . "\n"; } $last_type = $type; } } $doc_comment_text .= $left_padding . ' */' . "\n" . $left_padding; return $doc_comment_text; } private static function shouldAddNewLineBetweenAnnotations() : bool { return static::$shouldAddNewLineBetweenAnnotations; } /** * Sets whether a new line should be added between the annotations or not. * */ public static function addNewLineBetweenAnnotations(bool $should = \true) : void { static::$shouldAddNewLineBetweenAnnotations = $should; } public static function resetNewlineBetweenAnnotations() : void { static::$shouldAddNewLineBetweenAnnotations = \true; } } */ public $removed_taints = []; } $args */ public static function handleOverride(array $args, \Psalm\Codebase $codebase) : void { $identifier = $args[0]->value; if (!$args[1]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || !$args[1]->value->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { return; } $map = []; if ($args[1]->value->name->parts === ['map'] && $args[1]->value->args && $args[1]->value->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_) { foreach ($args[1]->value->args[0]->value->items as $array_item) { if ($array_item && $array_item->key instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if ($array_item->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $array_item->value->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified && $array_item->value->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($array_item->value->name->name)) { $map[$array_item->key->value] = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject(\implode('\\', $array_item->value->class->parts))]); } elseif ($array_item->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $map[$array_item->key->value] = $array_item->value->value; } } } } $type_offset = null; if ($args[1]->value->name->parts === ['type'] && $args[1]->value->args && $args[1]->value->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $type_offset = $args[1]->value->args[0]->value->value; } $element_type_offset = null; if ($args[1]->value->name->parts === ['elementType'] && $args[1]->value->args && $args[1]->value->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $element_type_offset = $args[1]->value->args[0]->value->value; } if ($identifier instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall && $identifier->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified && $identifier->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $identifier->args && $identifier->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $meta_fq_classlike_name = \implode('\\', $identifier->class->parts); $meta_method_name = \strtolower($identifier->name->name); if ($map) { $offset = $identifier->args[0]->value->value; $codebase->methods->return_type_provider->registerClosure( $meta_fq_classlike_name, /** * @param array $call_args */ function (\Psalm\StatementsSource $statements_analyzer, string $fq_classlike_name, string $method_name, array $call_args, \Psalm\Context $_context, \Psalm\CodeLocation $_code_location) use($map, $offset, $meta_fq_classlike_name, $meta_method_name) : ?Type\Union { if (!$statements_analyzer instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if ($meta_method_name !== $method_name || $meta_fq_classlike_name !== $fq_classlike_name) { return null; } if (isset($call_args[$offset]->value) && ($call_arg_type = $statements_analyzer->node_data->getType($call_args[$offset]->value)) && $call_arg_type->isSingleStringLiteral()) { $offset_arg_value = $call_arg_type->getSingleStringLiteral()->value; if ($mapped_type = $map[$offset_arg_value] ?? null) { if ($mapped_type instanceof \Psalm\Type\Union) { return clone $mapped_type; } } if (($mapped_type = $map[''] ?? null) && \is_string($mapped_type)) { if (\strpos($mapped_type, '@') !== \false) { $mapped_type = \str_replace('@', $offset_arg_value, $mapped_type); if (\strpos($mapped_type, '.') === \false) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($mapped_type)]); } } } } return null; } ); } elseif ($type_offset !== null) { $codebase->methods->return_type_provider->registerClosure( $meta_fq_classlike_name, /** * @param array $call_args */ function (\Psalm\StatementsSource $statements_analyzer, string $fq_classlike_name, string $method_name, array $call_args, \Psalm\Context $_context, \Psalm\CodeLocation $_code_location) use($map, $type_offset, $meta_fq_classlike_name, $meta_method_name) : ?Type\Union { if (!$statements_analyzer instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if ($meta_method_name !== $method_name || $meta_fq_classlike_name !== $fq_classlike_name) { return null; } if (isset($call_args[$type_offset]->value) && ($call_arg_type = $statements_analyzer->node_data->getType($call_args[$type_offset]->value))) { return clone $call_arg_type; } return null; } ); } elseif ($element_type_offset !== null) { $codebase->methods->return_type_provider->registerClosure( $meta_fq_classlike_name, /** * @param array $call_args */ function (\Psalm\StatementsSource $statements_analyzer, string $fq_classlike_name, string $method_name, array $call_args, \Psalm\Context $_context, \Psalm\CodeLocation $_code_location) use($map, $element_type_offset, $meta_fq_classlike_name, $meta_method_name) : ?Type\Union { if (!$statements_analyzer instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if ($meta_method_name !== $method_name || $meta_fq_classlike_name !== $fq_classlike_name) { return null; } if (isset($call_args[$element_type_offset]->value) && ($call_arg_type = $statements_analyzer->node_data->getType($call_args[$element_type_offset]->value)) && $call_arg_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var Type\Atomic\TArray|Type\Atomic\TKeyedArray|Type\Atomic\TList */ $array_atomic_type = $call_arg_type->getAtomicTypes()['array']; if ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { return $array_atomic_type->getGenericValueType(); } if ($array_atomic_type instanceof \Psalm\Type\Atomic\TList) { return $array_atomic_type->type_param; } return clone $array_atomic_type->type_params[1]; } return null; } ); } } if ($identifier instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $identifier->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified && $identifier->args && $identifier->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $function_id = \implode('\\', $identifier->name->parts); if ($map) { $offset = $identifier->args[0]->value->value; $codebase->functions->return_type_provider->registerClosure( $function_id, /** * @param non-empty-string $function_id * @param array $call_args */ function (\Psalm\StatementsSource $statements_analyzer, string $function_id, array $call_args, \Psalm\Context $_context, \Psalm\CodeLocation $_code_location) use($map, $offset) : Type\Union { if (!$statements_analyzer instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (isset($call_args[$offset]->value) && ($call_arg_type = $statements_analyzer->node_data->getType($call_args[$offset]->value)) && $call_arg_type->isSingleStringLiteral()) { $offset_arg_value = $call_arg_type->getSingleStringLiteral()->value; if ($mapped_type = $map[$offset_arg_value] ?? null) { if ($mapped_type instanceof \Psalm\Type\Union) { return clone $mapped_type; } } if (($mapped_type = $map[''] ?? null) && \is_string($mapped_type)) { if (\strpos($mapped_type, '@') !== \false) { $mapped_type = \str_replace('@', $offset_arg_value, $mapped_type); if (\strpos($mapped_type, '.') === \false) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($mapped_type)]); } } } } $storage = $statements_analyzer->getCodebase()->functions->getStorage($statements_analyzer, \strtolower($function_id)); return $storage->return_type ?: \Psalm\Type::getMixed(); } ); } elseif ($type_offset !== null) { $codebase->functions->return_type_provider->registerClosure( $function_id, /** * @param non-empty-string $function_id * @param array $call_args */ function (\Psalm\StatementsSource $statements_analyzer, string $function_id, array $call_args, \Psalm\Context $_context, \Psalm\CodeLocation $_code_location) use($map, $type_offset) : Type\Union { if (!$statements_analyzer instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (isset($call_args[$type_offset]->value) && ($call_arg_type = $statements_analyzer->node_data->getType($call_args[$type_offset]->value))) { return clone $call_arg_type; } $storage = $statements_analyzer->getCodebase()->functions->getStorage($statements_analyzer, \strtolower($function_id)); return $storage->return_type ?: \Psalm\Type::getMixed(); } ); } elseif ($element_type_offset !== null) { $codebase->functions->return_type_provider->registerClosure( $function_id, /** * @param non-empty-string $function_id * @param array $call_args */ function (\Psalm\StatementsSource $statements_analyzer, string $function_id, array $call_args, \Psalm\Context $_context, \Psalm\CodeLocation $_code_location) use($map, $element_type_offset) : Type\Union { if (!$statements_analyzer instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \Psalm\Type::getMixed(); } if (isset($call_args[$element_type_offset]->value) && ($call_arg_type = $statements_analyzer->node_data->getType($call_args[$element_type_offset]->value)) && $call_arg_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var Type\Atomic\TArray|Type\Atomic\TKeyedArray|Type\Atomic\TList */ $array_atomic_type = $call_arg_type->getAtomicTypes()['array']; if ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { return $array_atomic_type->getGenericValueType(); } if ($array_atomic_type instanceof \Psalm\Type\Atomic\TList) { return $array_atomic_type->type_param; } return clone $array_atomic_type->type_params[1]; } $storage = $statements_analyzer->getCodebase()->functions->getStorage($statements_analyzer, \strtolower($function_id)); return $storage->return_type ?: \Psalm\Type::getMixed(); } ); } } } } $line) { if (\preg_match('/^[ \\t]*\\*?\\s*@\\w/i', $line)) { $last = $k; } elseif (\preg_match('/^\\s*\\r?$/', $line)) { $last = \false; } elseif ($last !== \false) { $old_last_line = $lines[$last]; $lines[$last] = $old_last_line . "\n" . $line; unset($lines[$k]); } } $line_offset = 0; foreach ($lines as $k => $line) { $original_line_length = \strlen($line); $line = \str_replace("\r", '', $line); if ($first_line_padding === null) { $asterisk_pos = \strpos($line, '*'); if ($asterisk_pos) { $first_line_padding = \substr($line, 0, $asterisk_pos - 1); } } if (\preg_match('/^[ \\t]*\\*?\\s*@([\\w\\-\\\\:]+)[\\t ]*(.*)$/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 (empty($special[$type])) { $special[$type] = []; } $data_offset += $line_offset; $special[$type][$data_offset + 3] = $data; unset($lines[$k]); } else { // Strip the leading *, if present. $lines[$k] = \str_replace("\t", ' ', $line); $lines[$k] = \preg_replace('/^ *\\*/', '', $line); } $line_offset += $original_line_length + 1; } // Smush the whole docblock to the left edge. $min_indent = 80; foreach ($lines as $k => $line) { $indent = \strspn($line, ' '); if ($indent === \strlen($line)) { // This line consists of only spaces. Trim it completely. $lines[$k] = ''; continue; } $min_indent = \min($indent, $min_indent); } if ($min_indent > 0) { foreach ($lines as $k => $line) { if (\strlen($line) < $min_indent) { continue; } $lines[$k] = \substr($line, $min_indent); } } $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); $parsed = new \Psalm\Internal\Scanner\ParsedDocblock($docblock, $special, $first_line_padding ?: ''); self::resolveTags($parsed); return $parsed; } private static function resolveTags(\Psalm\Internal\Scanner\ParsedDocblock $docblock) : void { if (isset($docblock->tags['template']) || isset($docblock->tags['psalm-template']) || isset($docblock->tags['phpstan-template'])) { $docblock->combined_tags['template'] = ($docblock->tags['template'] ?? []) + ($docblock->tags['phpstan-template'] ?? []) + ($docblock->tags['psalm-template'] ?? []); } if (isset($docblock->tags['template-covariant']) || isset($docblock->tags['psalm-template-covariant']) || isset($docblock->tags['phpstan-template-covariant'])) { $docblock->combined_tags['template-covariant'] = ($docblock->tags['template-covariant'] ?? []) + ($docblock->tags['phpstan-template-covariant'] ?? []) + ($docblock->tags['psalm-template-covariant'] ?? []); } if (isset($docblock->tags['template-extends']) || isset($docblock->tags['inherits']) || isset($docblock->tags['extends']) || isset($docblock->tags['psalm-extends']) || isset($docblock->tags['phpstan-extends'])) { $docblock->combined_tags['extends'] = ($docblock->tags['template-extends'] ?? []) + ($docblock->tags['inherits'] ?? []) + ($docblock->tags['extends'] ?? []) + ($docblock->tags['psalm-extends'] ?? []) + ($docblock->tags['phpstan-extends'] ?? []); } if (isset($docblock->tags['template-implements']) || isset($docblock->tags['implements']) || isset($docblock->tags['phpstan-implements']) || isset($docblock->tags['psalm-implements'])) { $docblock->combined_tags['implements'] = ($docblock->tags['template-implements'] ?? []) + ($docblock->tags['implements'] ?? []) + ($docblock->tags['phpstan-implements'] ?? []) + ($docblock->tags['psalm-implements'] ?? []); } if (isset($docblock->tags['template-use']) || isset($docblock->tags['use']) || isset($docblock->tags['phpstan-use']) || isset($docblock->tags['psalm-use'])) { $docblock->combined_tags['use'] = ($docblock->tags['template-use'] ?? []) + ($docblock->tags['use'] ?? []) + ($docblock->tags['phpstan-use'] ?? []) + ($docblock->tags['psalm-use'] ?? []); } if (isset($docblock->tags['method']) || isset($docblock->tags['psalm-method'])) { $docblock->combined_tags['method'] = ($docblock->tags['method'] ?? []) + ($docblock->tags['psalm-method'] ?? []); } if (isset($docblock->tags['return']) || isset($docblock->tags['psalm-return']) || isset($docblock->tags['phpstan-return'])) { if (isset($docblock->tags['psalm-return'])) { $docblock->combined_tags['return'] = $docblock->tags['psalm-return']; } elseif (isset($docblock->tags['phpstan-return'])) { $docblock->combined_tags['return'] = $docblock->tags['phpstan-return']; } else { $docblock->combined_tags['return'] = $docblock->tags['return']; } } if (isset($docblock->tags['param']) || isset($docblock->tags['psalm-param']) || isset($docblock->tags['phpstan-param'])) { $docblock->combined_tags['param'] = ($docblock->tags['param'] ?? []) + ($docblock->tags['phpstan-param'] ?? []) + ($docblock->tags['psalm-param'] ?? []); } if (isset($docblock->tags['var']) || isset($docblock->tags['psalm-var']) || isset($docblock->tags['phpstan-var'])) { $docblock->combined_tags['var'] = ($docblock->tags['var'] ?? []) + ($docblock->tags['phpstan-var'] ?? []) + ($docblock->tags['psalm-var'] ?? []); } } } left = $left; $this->right = $right; } } */ public $entries; /** @param list $entries */ public function __construct(array $entries) { $this->entries = $entries; } } name = $name; $this->is_fully_qualified = $is_fully_qualified; } } fqcln = $fqcln; $this->name = $name; } } key = $key; $this->value = $value; } } cond = $cond; $this->if = $if; $this->else = $else; } } array = $left; $this->offset = $right; } } value = $value; } } */ public $templates = []; /** * @var array */ public $template_extends = []; /** * @var array */ public $template_implements = []; /** * @var ?string */ public $yield = null; /** * @var array */ public $properties = []; /** * @var array */ public $methods = []; /** * @var bool */ public $sealed_properties = \false; /** * @var bool */ public $sealed_methods = \false; /** * @var bool */ public $override_property_visibility = \false; /** * @var bool */ public $override_method_visibility = \false; /** * @var bool */ public $mutation_free = \false; /** * @var bool */ public $external_mutation_free = \false; /** * @var bool */ public $taint_specialize = \false; /** * @var array */ public $suppressed_issues = []; /** * @var list}> */ public $imported_types = []; /** * @var bool */ public $consistent_constructor = \false; /** @var bool */ public $stub_override = \false; /** * @var null|string */ public $extension_requirement; /** * @var array */ public $implementation_requirements = []; } declaring_fq_classlike_name = $declaring_fq_classlike_name; $this->alias_name = $alias_name; $this->line_number = $line_number; $this->start_offset = $start_offset; $this->end_offset = $end_offset; } } */ public $replacement_atomic_types; /** * @param list<\Psalm\Type\Atomic> $replacement_atomic_types */ public function __construct(array $replacement_atomic_types) { $this->replacement_atomic_types = $replacement_atomic_types; } } */ public $replacement_tokens; /** * @param list $replacement_tokens */ public function __construct(array $replacement_tokens) { $this->replacement_tokens = $replacement_tokens; } } */ private $type_tokens; /** @var int */ private $type_token_count; /** @var int */ private $t = 0; /** * @param list $type_tokens */ public function __construct(array $type_tokens) { $this->type_tokens = $type_tokens; $this->type_token_count = \count($type_tokens); $this->parse_tree = new \Psalm\Internal\Type\ParseTree\Root(); $this->current_leaf = $this->parse_tree; } public function create() : \Psalm\Internal\Type\ParseTree { while ($this->t < $this->type_token_count) { $type_token = $this->type_tokens[$this->t]; switch ($type_token[0]) { case '<': case '{': case ']': throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ' . $type_token[0]); case '[': $this->handleOpenSquareBracket(); break; case '(': $this->handleOpenRoundBracket(); break; case ')': $this->handleClosedRoundBracket(); break; case '>': do { if ($this->current_leaf->parent === null) { throw new \Psalm\Exception\TypeParseTreeException('Cannot parse generic type'); } $this->current_leaf = $this->current_leaf->parent; } while (!$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\GenericTree); $this->current_leaf->terminated = \true; break; case '}': do { if ($this->current_leaf->parent === null) { throw new \Psalm\Exception\TypeParseTreeException('Cannot parse array type'); } $this->current_leaf = $this->current_leaf->parent; } while (!$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayTree); $this->current_leaf->terminated = \true; break; case ',': $this->handleComma(); break; case '...': case '=': $this->handleEllipsisOrEquals($type_token); break; case ':': $this->handleColon(); break; case ' ': $this->handleSpace(); break; case '?': $this->handleQuestionMark(); break; case '|': $this->handleBar(); break; case '&': $this->handleAmpersand(); break; case 'is': case 'as': $this->handleIsOrAs($type_token); break; default: $this->handleValue($type_token); break; } $this->t++; } $this->parse_tree->cleanParents(); if ($this->current_leaf !== $this->parse_tree && ($this->parse_tree instanceof \Psalm\Internal\Type\ParseTree\GenericTree || $this->parse_tree instanceof \Psalm\Internal\Type\ParseTree\CallableTree || $this->parse_tree instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayTree)) { throw new \Psalm\Exception\TypeParseTreeException('Unterminated bracket'); } return $this->parse_tree; } /** * @param array{0: string, 1: int} $current_token */ private function createMethodParam(array $current_token, \Psalm\Internal\Type\ParseTree $current_parent) : void { $byref = \false; $variadic = \false; $has_default = \false; $default = ''; if ($current_token[0] === '&') { throw new \Psalm\Exception\TypeParseTreeException('Magic args cannot be passed by reference'); } if ($current_token[0] === '...') { $variadic = \true; ++$this->t; $current_token = $this->t < $this->type_token_count ? $this->type_tokens[$this->t] : null; } if (!$current_token || $current_token[0][0] !== '$') { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token after space'); } $new_parent_leaf = new \Psalm\Internal\Type\ParseTree\MethodParamTree($current_token[0], $byref, $variadic, $current_parent); for ($j = $this->t + 1; $j < $this->type_token_count; ++$j) { $ahead_type_token = $this->type_tokens[$j]; if ($ahead_type_token[0] === ',' || $ahead_type_token[0] === ')' && $this->type_tokens[$j - 1][0] !== '(') { $this->t = $j - 1; break; } if ($has_default) { $default .= $ahead_type_token[0]; } if ($ahead_type_token[0] === '=') { $has_default = \true; continue; } if ($j === $this->type_token_count - 1) { throw new \Psalm\Exception\TypeParseTreeException('Unterminated method'); } } $new_parent_leaf->default = $default; if ($this->current_leaf !== $current_parent) { $new_parent_leaf->children = [$this->current_leaf]; $this->current_leaf->parent = $new_parent_leaf; \array_pop($current_parent->children); } $current_parent->children[] = $new_parent_leaf; $this->current_leaf = $new_parent_leaf; } private function handleOpenSquareBracket() : void { if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ['); } $indexed_access = \false; $next_token = $this->t + 1 < $this->type_token_count ? $this->type_tokens[$this->t + 1] : null; if (!$next_token || $next_token[0] !== ']') { $next_next_token = $this->t + 2 < $this->type_token_count ? $this->type_tokens[$this->t + 2] : null; if ($next_next_token !== null && $next_next_token[0] === ']') { $indexed_access = \true; ++$this->t; } else { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ['); } } $current_parent = $this->current_leaf->parent; if ($indexed_access) { if ($next_token === null) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ['); } $new_parent_leaf = new \Psalm\Internal\Type\ParseTree\IndexedAccessTree($next_token[0], $current_parent); } else { if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayPropertyTree) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ['); } $new_parent_leaf = new \Psalm\Internal\Type\ParseTree\GenericTree('array', $current_parent); } $this->current_leaf->parent = $new_parent_leaf; $new_parent_leaf->children = [$this->current_leaf]; if ($current_parent) { \array_pop($current_parent->children); $current_parent->children[] = $new_parent_leaf; } else { $this->parse_tree = $new_parent_leaf; } $this->current_leaf = $new_parent_leaf; ++$this->t; } private function handleOpenRoundBracket() : void { if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Value) { throw new \Psalm\Exception\TypeParseTreeException('Unrecognised token ('); } $new_parent = !$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root ? $this->current_leaf : null; $new_leaf = new \Psalm\Internal\Type\ParseTree\EncapsulationTree($new_parent); if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { $this->current_leaf = $this->parse_tree = $new_leaf; return; } if ($new_leaf->parent) { $new_leaf->parent->children[] = $new_leaf; } $this->current_leaf = $new_leaf; } private function handleClosedRoundBracket() : void { $prev_token = $this->t > 0 ? $this->type_tokens[$this->t - 1] : null; if ($prev_token !== null && $prev_token[0] === '(' && $this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\CallableTree) { return; } do { if ($this->current_leaf->parent === null) { break; } $this->current_leaf = $this->current_leaf->parent; } while (!$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\EncapsulationTree && !$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\CallableTree && !$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\MethodTree); if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\EncapsulationTree || $this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\CallableTree) { $this->current_leaf->terminated = \true; } } private function handleComma() : void { if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ,'); } if (!$this->current_leaf->parent) { throw new \Psalm\Exception\TypeParseTreeException('Cannot parse comma without a parent node'); } $context_node = $this->current_leaf; if ($context_node instanceof \Psalm\Internal\Type\ParseTree\GenericTree || $context_node instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayTree || $context_node instanceof \Psalm\Internal\Type\ParseTree\CallableTree || $context_node instanceof \Psalm\Internal\Type\ParseTree\MethodTree) { $context_node = $context_node->parent; } while ($context_node && !$context_node instanceof \Psalm\Internal\Type\ParseTree\GenericTree && !$context_node instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayTree && !$context_node instanceof \Psalm\Internal\Type\ParseTree\CallableTree && !$context_node instanceof \Psalm\Internal\Type\ParseTree\MethodTree) { $context_node = $context_node->parent; } if (!$context_node) { throw new \Psalm\Exception\TypeParseTreeException('Cannot parse comma in non-generic/array type'); } $this->current_leaf = $context_node; } /** @param array{0: string, 1: int} $type_token */ private function handleEllipsisOrEquals(array $type_token) : void { $prev_token = $this->t > 0 ? $this->type_tokens[$this->t - 1] : null; if ($prev_token && ($prev_token[0] === '...' || $prev_token[0] === '=')) { throw new \Psalm\Exception\TypeParseTreeException('Cannot have duplicate tokens'); } $current_parent = $this->current_leaf->parent; if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\MethodTree && $type_token[0] === '...') { $this->createMethodParam($type_token, $this->current_leaf); return; } while ($current_parent && !$current_parent instanceof \Psalm\Internal\Type\ParseTree\CallableTree && !$current_parent instanceof \Psalm\Internal\Type\ParseTree\CallableParamTree) { $this->current_leaf = $current_parent; $current_parent = $current_parent->parent; } if (!$current_parent) { if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\CallableTree && $type_token[0] === '...') { $current_parent = $this->current_leaf; } else { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ' . $type_token[0]); } } if ($current_parent instanceof \Psalm\Internal\Type\ParseTree\CallableParamTree) { throw new \Psalm\Exception\TypeParseTreeException('Cannot have variadic param with a default'); } $new_leaf = new \Psalm\Internal\Type\ParseTree\CallableParamTree($current_parent); $new_leaf->has_default = $type_token[0] === '='; $new_leaf->variadic = $type_token[0] === '...'; if ($current_parent !== $this->current_leaf) { $new_leaf->children = [$this->current_leaf]; $this->current_leaf->parent = $new_leaf; \array_pop($current_parent->children); $current_parent->children[] = $new_leaf; } else { $current_parent->children[] = $new_leaf; } $this->current_leaf = $new_leaf; } private function handleColon() : void { if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token :'); } $current_parent = $this->current_leaf->parent; if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\CallableTree) { $new_parent_leaf = new \Psalm\Internal\Type\ParseTree\CallableWithReturnTypeTree($current_parent); $this->current_leaf->parent = $new_parent_leaf; $new_parent_leaf->children = [$this->current_leaf]; if ($current_parent) { \array_pop($current_parent->children); $current_parent->children[] = $new_parent_leaf; } else { $this->parse_tree = $new_parent_leaf; } $this->current_leaf = $new_parent_leaf; return; } if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\MethodTree) { $new_parent_leaf = new \Psalm\Internal\Type\ParseTree\MethodWithReturnTypeTree($current_parent); $this->current_leaf->parent = $new_parent_leaf; $new_parent_leaf->children = [$this->current_leaf]; if ($current_parent) { \array_pop($current_parent->children); $current_parent->children[] = $new_parent_leaf; } else { $this->parse_tree = $new_parent_leaf; } $this->current_leaf = $new_parent_leaf; return; } if ($current_parent && $current_parent instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayPropertyTree) { return; } while (($current_parent instanceof \Psalm\Internal\Type\ParseTree\UnionTree || $current_parent instanceof \Psalm\Internal\Type\ParseTree\CallableWithReturnTypeTree) && $this->current_leaf->parent) { $this->current_leaf = $this->current_leaf->parent; $current_parent = $this->current_leaf->parent; } if ($current_parent && $current_parent instanceof \Psalm\Internal\Type\ParseTree\ConditionalTree) { if (\count($current_parent->children) > 1) { throw new \Psalm\Exception\TypeParseTreeException('Cannot process colon in conditional twice'); } $this->current_leaf = $current_parent; return; } if (!$current_parent) { throw new \Psalm\Exception\TypeParseTreeException('Cannot process colon without parent'); } if (!$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Value) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected LHS of property'); } if (!$current_parent instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayTree) { throw new \Psalm\Exception\TypeParseTreeException('Saw : outside of object-like array'); } $prev_token = $this->t > 0 ? $this->type_tokens[$this->t - 1] : null; $new_parent_leaf = new \Psalm\Internal\Type\ParseTree\KeyedArrayPropertyTree($this->current_leaf->value, $current_parent); $new_parent_leaf->possibly_undefined = $prev_token !== null && $prev_token[0] === '?'; $this->current_leaf->parent = $new_parent_leaf; \array_pop($current_parent->children); $current_parent->children[] = $new_parent_leaf; $this->current_leaf = $new_parent_leaf; } private function handleSpace() : void { if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected space'); } if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayTree) { return; } $current_parent = $this->current_leaf->parent; if ($current_parent instanceof \Psalm\Internal\Type\ParseTree\CallableTree) { return; } while ($current_parent && !$current_parent instanceof \Psalm\Internal\Type\ParseTree\MethodTree) { $this->current_leaf = $current_parent; $current_parent = $current_parent->parent; } $next_token = $this->t + 1 < $this->type_token_count ? $this->type_tokens[$this->t + 1] : null; if (!$current_parent instanceof \Psalm\Internal\Type\ParseTree\MethodTree || !$next_token) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected space'); } ++$this->t; $this->createMethodParam($next_token, $current_parent); } private function handleQuestionMark() : void { $next_token = $this->t + 1 < $this->type_token_count ? $this->type_tokens[$this->t + 1] : null; if ($next_token === null || $next_token[0] !== ':') { while (($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Value || $this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\UnionTree || $this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayTree && $this->current_leaf->terminated || $this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\GenericTree && $this->current_leaf->terminated || $this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\EncapsulationTree && $this->current_leaf->terminated || $this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\CallableTree && $this->current_leaf->terminated || $this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\IntersectionTree) && $this->current_leaf->parent) { $this->current_leaf = $this->current_leaf->parent; } if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\TemplateIsTree && $this->current_leaf->parent) { $current_parent = $this->current_leaf->parent; $new_leaf = new \Psalm\Internal\Type\ParseTree\ConditionalTree($this->current_leaf, $this->current_leaf->parent); $this->current_leaf->parent = $new_leaf; \array_pop($current_parent->children); $current_parent->children[] = $new_leaf; $this->current_leaf = $new_leaf; } else { $new_parent = !$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root ? $this->current_leaf : null; if (!$next_token) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ?'); } $new_leaf = new \Psalm\Internal\Type\ParseTree\NullableTree($new_parent); if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { $this->current_leaf = $this->parse_tree = $new_leaf; return; } if ($new_leaf->parent) { $new_leaf->parent->children[] = $new_leaf; } $this->current_leaf = $new_leaf; } } } private function handleBar() : void { if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token |'); } $current_parent = $this->current_leaf->parent; if ($current_parent instanceof \Psalm\Internal\Type\ParseTree\CallableWithReturnTypeTree) { $this->current_leaf = $current_parent; $current_parent = $current_parent->parent; } if ($current_parent instanceof \Psalm\Internal\Type\ParseTree\NullableTree) { $this->current_leaf = $current_parent; $current_parent = $current_parent->parent; } if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\UnionTree) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token |'); } if ($current_parent && $current_parent instanceof \Psalm\Internal\Type\ParseTree\UnionTree) { $this->current_leaf = $current_parent; return; } if ($current_parent && $current_parent instanceof \Psalm\Internal\Type\ParseTree\IntersectionTree) { $this->current_leaf = $current_parent; $current_parent = $this->current_leaf->parent; } if ($current_parent instanceof \Psalm\Internal\Type\ParseTree\TemplateIsTree) { $new_parent_leaf = new \Psalm\Internal\Type\ParseTree\UnionTree($this->current_leaf); $new_parent_leaf->children = [$this->current_leaf]; $new_parent_leaf->parent = $current_parent; $this->current_leaf->parent = $new_parent_leaf; } else { $new_parent_leaf = new \Psalm\Internal\Type\ParseTree\UnionTree($current_parent); $new_parent_leaf->children = [$this->current_leaf]; $this->current_leaf->parent = $new_parent_leaf; } if ($current_parent) { \array_pop($current_parent->children); $current_parent->children[] = $new_parent_leaf; } else { $this->parse_tree = $new_parent_leaf; } $this->current_leaf = $new_parent_leaf; } private function handleAmpersand() : void { if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected &'); } $current_parent = $this->current_leaf->parent; if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\MethodTree && $current_parent) { $this->createMethodParam($this->type_tokens[$this->t], $current_parent); return; } if ($current_parent && $current_parent instanceof \Psalm\Internal\Type\ParseTree\IntersectionTree) { $this->current_leaf = $current_parent; return; } $new_parent_leaf = new \Psalm\Internal\Type\ParseTree\IntersectionTree($current_parent); $new_parent_leaf->children = [$this->current_leaf]; $this->current_leaf->parent = $new_parent_leaf; if ($current_parent) { \array_pop($current_parent->children); $current_parent->children[] = $new_parent_leaf; } else { $this->parse_tree = $new_parent_leaf; } $this->current_leaf = $new_parent_leaf; } /** @param array{0: string, 1: int} $type_token */ private function handleIsOrAs(array $type_token) : void { if ($this->t === 0) { $this->handleValue($type_token); } else { $current_parent = $this->current_leaf->parent; if ($current_parent) { \array_pop($current_parent->children); } if ($type_token[0] === 'as') { $next_token = $this->t + 1 < $this->type_token_count ? $this->type_tokens[$this->t + 1] : null; if (!$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Value || !$current_parent instanceof \Psalm\Internal\Type\ParseTree\GenericTree || !$next_token) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ' . $type_token[0]); } $this->current_leaf = new \Psalm\Internal\Type\ParseTree\TemplateAsTree($this->current_leaf->value, $next_token[0], $current_parent); $current_parent->children[] = $this->current_leaf; ++$this->t; } elseif ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Value) { $this->current_leaf = new \Psalm\Internal\Type\ParseTree\TemplateIsTree($this->current_leaf->value, $current_parent); if ($current_parent) { $current_parent->children[] = $this->current_leaf; } } } } /** @param array{0: string, 1: int} $type_token */ private function handleValue(array $type_token) : void { $new_parent = !$this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root ? $this->current_leaf : null; if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\MethodTree && $type_token[0][0] === '$') { $this->createMethodParam($type_token, $this->current_leaf); return; } $next_token = $this->t + 1 < $this->type_token_count ? $this->type_tokens[$this->t + 1] : null; switch ($next_token[0] ?? null) { case '<': $new_leaf = new \Psalm\Internal\Type\ParseTree\GenericTree($type_token[0], $new_parent); ++$this->t; break; case '{': $new_leaf = new \Psalm\Internal\Type\ParseTree\KeyedArrayTree($type_token[0], $new_parent); ++$this->t; break; case '(': if (\in_array($type_token[0], ['callable', 'pure-callable', 'Closure', '\\Closure', 'pure-Closure'], \true)) { $new_leaf = new \Psalm\Internal\Type\ParseTree\CallableTree($type_token[0], $new_parent); } elseif ($type_token[0] !== 'array' && $type_token[0][0] !== '\\' && $this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { $new_leaf = new \Psalm\Internal\Type\ParseTree\MethodTree($type_token[0], $new_parent); } else { throw new \Psalm\Exception\TypeParseTreeException('Bracket must be preceded by “Closure”, “callable”, "pure-callable" or a valid @method name'); } ++$this->t; break; case '::': $nexter_token = $this->t + 2 < $this->type_token_count ? $this->type_tokens[$this->t + 2] : null; if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayTree) { throw new \Psalm\Exception\TypeParseTreeException('Unexpected :: in array key'); } if (!$nexter_token || !\preg_match('/^([a-zA-Z_][a-zA-Z_0-9]*\\*?|\\*)$/', $nexter_token[0]) && \strtolower($nexter_token[0]) !== 'class') { throw new \Psalm\Exception\TypeParseTreeException('Invalid class constant ' . ($nexter_token[0] ?? '')); } $new_leaf = new \Psalm\Internal\Type\ParseTree\Value($type_token[0] . '::' . $nexter_token[0], $type_token[1], $type_token[1] + 2 + \strlen($nexter_token[0]), $new_parent); $this->t += 2; break; default: if ($type_token[0] === '$this') { $type_token[0] = 'static'; } $new_leaf = new \Psalm\Internal\Type\ParseTree\Value($type_token[0], $type_token[1], $type_token[1] + \strlen($type_token[0]), $new_parent); break; } if ($this->current_leaf instanceof \Psalm\Internal\Type\ParseTree\Root) { $this->current_leaf = $this->parse_tree = $new_leaf; return; } if ($new_leaf->parent) { $new_leaf->parent->children[] = $new_leaf; } $this->current_leaf = $new_leaf; } } key = $key; $this->value = $value; $this->is_list = $is_list; } /** * @return self|null */ public static function infer(\Psalm\Type\Atomic $type) : ?self { if ($type instanceof \Psalm\Type\Atomic\TKeyedArray) { return new self($type->getGenericKeyType(), $type->getGenericValueType(), $type->is_list); } if ($type instanceof \Psalm\Type\Atomic\TList) { return new self(\Psalm\Type::getInt(), $type->type_param, \true); } if ($type instanceof \Psalm\Type\Atomic\TArray) { return new self($type->type_params[0], $type->type_params[1], \false); } return null; } } > */ public $template_types; /** * @var array> */ public $upper_bounds; /** * @var array> */ public $lower_bounds = []; /** * @var list */ public $lower_bounds_unintersectable_types = []; /** * @param array> $template_types * @param array> $upper_bounds */ public function __construct(array $template_types, array $upper_bounds) { $this->template_types = $template_types; $this->upper_bounds = $upper_bounds; } } null, * - empty(bool) => false, * - notEmpty(Object|null) => Object, * - notEmpty(Object|false) => Object * * @param string[] $suppressed_issues * @param array> $template_type_map * @param-out 0|1|2 $failed_reconciliation */ public static function reconcile(string $assertion, ?\Psalm\Type\Union $existing_var_type, ?string $key, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, bool $inside_loop, array $template_type_map, ?\Psalm\CodeLocation $code_location = null, array $suppressed_issues = [], ?int &$failed_reconciliation = 0, bool $negated = \false) : \Psalm\Type\Union { $codebase = $statements_analyzer->getCodebase(); $is_strict_equality = \false; $is_loose_equality = \false; $is_equality = \false; $is_negation = \false; $failed_reconciliation = 0; if ($assertion[0] === '!') { $assertion = \substr($assertion, 1); $is_negation = \true; } if ($assertion[0] === '=') { $assertion = \substr($assertion, 1); $is_strict_equality = \true; $is_equality = \true; } if ($assertion[0] === '~') { $assertion = \substr($assertion, 1); $is_loose_equality = \true; $is_equality = \true; } if ($assertion[0] === '>') { $assertion = 'falsy'; $is_negation = \true; } if ($existing_var_type === null && \is_string($key) && \Psalm\Internal\Analyzer\Statements\Expression\Fetch\VariableFetchAnalyzer::isSuperGlobal($key)) { $existing_var_type = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\VariableFetchAnalyzer::getGlobalType($key); } if ($existing_var_type === null) { if ($assertion === 'isset' && !$is_negation || $assertion === 'empty' && $is_negation) { return \Psalm\Type::getMixed($inside_loop); } if ($assertion === 'array-key-exists' || $assertion === 'non-empty-countable' || \strpos($assertion, 'has-at-least-') === 0 || \strpos($assertion, 'has-exactly-') === 0) { return \Psalm\Type::getMixed(); } if (!$is_negation && $assertion !== 'falsy' && $assertion !== 'empty') { if ($is_equality) { $bracket_pos = \strpos($assertion, '('); if ($bracket_pos) { $assertion = \substr($assertion, 0, $bracket_pos); } } try { return \Psalm\Type::parseString($assertion, null, $template_type_map); } catch (\Exception $e) { return \Psalm\Type::getMixed(); } } return \Psalm\Type::getMixed(); } $old_var_type_string = $existing_var_type->getId(); if ($is_negation) { return \Psalm\Internal\Type\NegatedAssertionReconciler::reconcile($statements_analyzer, $assertion, $is_strict_equality, $is_loose_equality, $existing_var_type, $template_type_map, $old_var_type_string, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation); } $simply_reconciled_type = \Psalm\Internal\Type\SimpleAssertionReconciler::reconcile($assertion, $codebase, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, $is_strict_equality, $inside_loop); if ($simply_reconciled_type) { return $simply_reconciled_type; } if (\substr($assertion, 0, 4) === 'isa-') { $assertion = \substr($assertion, 4); $allow_string_comparison = \false; if (\substr($assertion, 0, 7) === 'string-') { $assertion = \substr($assertion, 7); $allow_string_comparison = \true; } if ($existing_var_type->hasMixed()) { $type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($assertion)]); if ($allow_string_comparison) { $type->addType(new \Psalm\Type\Atomic\TClassString($assertion, new \Psalm\Type\Atomic\TNamedObject($assertion))); } return $type; } $existing_has_object = $existing_var_type->hasObjectType(); $existing_has_string = $existing_var_type->hasString(); if ($existing_has_object && !$existing_has_string) { $new_type = \Psalm\Type::parseString($assertion, null, $template_type_map); } elseif ($existing_has_string && !$existing_has_object) { if (!$allow_string_comparison && $code_location) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType('Cannot allow string comparison to object for ' . $key, $code_location, null), $suppressed_issues)) { // fall through } $new_type = \Psalm\Type::getMixed(); } else { $new_type_has_interface_string = $codebase->interfaceExists($assertion); $old_type_has_interface_string = \false; foreach ($existing_var_type->getAtomicTypes() as $existing_type_part) { if ($existing_type_part instanceof \Psalm\Type\Atomic\TClassString && $existing_type_part->as_type && $codebase->interfaceExists($existing_type_part->as_type->value)) { $old_type_has_interface_string = \true; break; } } if (isset($template_type_map[$assertion])) { $new_type = \Psalm\Type::parseString('class-string<' . $assertion . '>', null, $template_type_map); } else { $new_type = \Psalm\Type::getClassString($assertion); } if ($new_type_has_interface_string && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $existing_var_type, $new_type) || $old_type_has_interface_string && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $new_type, $existing_var_type)) { $new_type_part = \Psalm\Type\Atomic::create($assertion, null, $template_type_map); $acceptable_atomic_types = []; foreach ($existing_var_type->getAtomicTypes() as $existing_var_type_part) { if (!$new_type_part instanceof \Psalm\Type\Atomic\TNamedObject || !$existing_var_type_part instanceof \Psalm\Type\Atomic\TClassString) { $acceptable_atomic_types = []; break; } if (!$existing_var_type_part->as_type instanceof \Psalm\Type\Atomic\TNamedObject) { $acceptable_atomic_types = []; break; } $existing_var_type_part = $existing_var_type_part->as_type; if (\Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $existing_var_type_part, $new_type_part)) { $acceptable_atomic_types[] = clone $existing_var_type_part; continue; } if ($codebase->classExists($existing_var_type_part->value) || $codebase->interfaceExists($existing_var_type_part->value)) { $existing_var_type_part = clone $existing_var_type_part; $existing_var_type_part->addIntersectionType($new_type_part); $acceptable_atomic_types[] = $existing_var_type_part; } } if (\count($acceptable_atomic_types) === 1) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClassString('object', $acceptable_atomic_types[0])]); } } } } else { $new_type = \Psalm\Type::getMixed(); } } elseif (\substr($assertion, 0, 9) === 'getclass-') { $assertion = \substr($assertion, 9); $new_type = \Psalm\Type::parseString($assertion, null, $template_type_map); } else { $bracket_pos = \strpos($assertion, '('); if ($bracket_pos) { return self::handleLiteralEquality($assertion, $bracket_pos, $is_loose_equality, $existing_var_type, $old_var_type_string, $key, $negated, $code_location, $suppressed_issues); } $new_type = \Psalm\Type::parseString($assertion, null, $template_type_map); } if ($existing_var_type->hasMixed()) { if ($is_loose_equality && $new_type->hasScalarType()) { return $existing_var_type; } return $new_type; } return self::refine($statements_analyzer, $assertion, $new_type, $existing_var_type, $template_type_map, $key, $negated, $code_location, $is_equality, $is_loose_equality, $suppressed_issues, $failed_reconciliation); } /** * @param 0|1|2 $failed_reconciliation * @param string[] $suppressed_issues * @param array> $template_type_map * @param-out 0|1|2 $failed_reconciliation */ private static function refine(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $assertion, \Psalm\Type\Union $new_type, \Psalm\Type\Union $existing_var_type, array $template_type_map, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, bool $is_equality, bool $is_loose_equality, array $suppressed_issues, int &$failed_reconciliation) : \Psalm\Type\Union { $codebase = $statements_analyzer->getCodebase(); $old_var_type_string = $existing_var_type->getId(); $new_type_has_interface = \false; if ($new_type->hasObjectType()) { foreach ($new_type->getAtomicTypes() as $new_type_part) { if ($new_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->interfaceExists($new_type_part->value)) { $new_type_has_interface = \true; break; } } } $old_type_has_interface = \false; if ($existing_var_type->hasObjectType()) { foreach ($existing_var_type->getAtomicTypes() as $existing_type_part) { if ($existing_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->interfaceExists($existing_type_part->value)) { $old_type_has_interface = \true; break; } } } try { if (\strpos($assertion, '<') || \strpos($assertion, '[') || \strpos($assertion, '{')) { $new_type_union = \Psalm\Type::parseString($assertion); $new_type_part = \array_values($new_type_union->getAtomicTypes())[0]; } else { $new_type_part = \Psalm\Type\Atomic::create($assertion, null, $template_type_map); } } catch (\Psalm\Exception\TypeParseTreeException $e) { $new_type_part = new \Psalm\Type\Atomic\TMixed(); if ($code_location) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock($assertion . ' cannot be used in an assertion', $code_location), $suppressed_issues)) { // fall through } } } if ($new_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $new_type_part->as->isSingle()) { $new_as_atomic = \array_values($new_type_part->as->getAtomicTypes())[0]; $acceptable_atomic_types = []; foreach ($existing_var_type->getAtomicTypes() as $existing_var_type_part) { if ($existing_var_type_part instanceof \Psalm\Type\Atomic\TNamedObject || $existing_var_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $new_type_part->addIntersectionType($existing_var_type_part); $acceptable_atomic_types[] = clone $existing_var_type_part; } else { if (\Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $existing_var_type_part, $new_as_atomic)) { $acceptable_atomic_types[] = clone $existing_var_type_part; } } } if ($acceptable_atomic_types) { $new_type_part->as = new \Psalm\Type\Union($acceptable_atomic_types); return new \Psalm\Type\Union([$new_type_part]); } } if ($new_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $acceptable_atomic_types = []; foreach ($existing_var_type->getAtomicTypes() as $existing_var_type_part) { if ($existing_var_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { if (!\array_intersect_key($existing_var_type_part->properties, $new_type_part->properties)) { $existing_var_type_part = clone $existing_var_type_part; $existing_var_type_part->properties = \array_merge($existing_var_type_part->properties, $new_type_part->properties); $acceptable_atomic_types[] = $existing_var_type_part; } } } if ($acceptable_atomic_types) { return new \Psalm\Type\Union($acceptable_atomic_types); } } if ($new_type_part instanceof \Psalm\Type\Atomic\TNamedObject && ($new_type_has_interface && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $existing_var_type, $new_type) || $old_type_has_interface && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $new_type, $existing_var_type))) { $acceptable_atomic_types = []; foreach ($existing_var_type->getAtomicTypes() as $existing_var_type_part) { if (\Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $existing_var_type_part, $new_type_part)) { $acceptable_atomic_types[] = clone $existing_var_type_part; continue; } if ($existing_var_type_part instanceof \Psalm\Type\Atomic\TNamedObject && ($codebase->classExists($existing_var_type_part->value) || $codebase->interfaceExists($existing_var_type_part->value))) { $existing_var_type_part = clone $existing_var_type_part; $existing_var_type_part->addIntersectionType($new_type_part); $acceptable_atomic_types[] = $existing_var_type_part; } if ($existing_var_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $existing_var_type_part = clone $existing_var_type_part; $existing_var_type_part->addIntersectionType($new_type_part); $acceptable_atomic_types[] = $existing_var_type_part; } } if ($acceptable_atomic_types) { return new \Psalm\Type\Union($acceptable_atomic_types); } } elseif (!$new_type->hasMixed()) { $has_match = \true; if ($key && $code_location && $new_type->getId() === $existing_var_type->getId() && !$is_equality && (!$statements_analyzer->getSource()->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer || $key !== '$this' && !($existing_var_type->hasLiteralClassString() && $new_type->hasLiteralClassString()))) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, $assertion, \true, $negated, $code_location, $suppressed_issues); } $any_scalar_type_match_found = \false; if ($code_location && $key && !$is_equality && $new_type_part instanceof \Psalm\Type\Atomic\TNamedObject && !$new_type_has_interface && (!$statements_analyzer->getSource()->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer || $key !== '$this' && !($existing_var_type->hasLiteralClassString() && $new_type->hasLiteralClassString())) && \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $existing_var_type, $new_type)) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, $assertion, \true, $negated, $code_location, $suppressed_issues); } $new_type = self::filterTypeWithAnother($codebase, $existing_var_type, $new_type, $template_type_map, $has_match, $any_scalar_type_match_found); if ($code_location && !$has_match && (!$is_loose_equality || !$any_scalar_type_match_found)) { if ($assertion === 'null') { if ($existing_var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction('Cannot resolve types for ' . $key . ' - docblock-defined type ' . $existing_var_type . ' does not contain null', $code_location, $existing_var_type->getId() . ' null'), $suppressed_issues)) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainNull('Cannot resolve types for ' . $key . ' - ' . $existing_var_type . ' does not contain null', $code_location, $existing_var_type->getId()), $suppressed_issues)) { // fall through } } } elseif (!$statements_analyzer->getSource()->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer || $key !== '$this' && !($existing_var_type->hasLiteralClassString() && $new_type->hasLiteralClassString())) { if ($existing_var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction('Cannot resolve types for ' . $key . ' - docblock-defined type ' . $existing_var_type->getId() . ' does not contain ' . $new_type->getId(), $code_location, $existing_var_type->getId() . ' ' . $new_type->getId()), $suppressed_issues)) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType('Cannot resolve types for ' . $key . ' - ' . $existing_var_type->getId() . ' does not contain ' . $new_type->getId(), $code_location, $existing_var_type->getId() . ' ' . $new_type->getId()), $suppressed_issues)) { // fall through } } } $failed_reconciliation = 2; } } return $new_type; } /** * @param array> $template_type_map */ private static function filterTypeWithAnother(\Psalm\Codebase $codebase, \Psalm\Type\Union $existing_type, \Psalm\Type\Union $new_type, array $template_type_map, bool &$has_match = \false, bool &$any_scalar_type_match_found = \false) : \Psalm\Type\Union { $matching_atomic_types = []; $has_cloned_type = \false; foreach ($new_type->getAtomicTypes() as $new_type_part) { $has_local_match = \false; foreach ($existing_type->getAtomicTypes() as $key => $existing_type_part) { // special workaround because PHP allows floats to contain ints, but we don’t want this // behaviour here if ($existing_type_part instanceof \Psalm\Type\Atomic\TFloat && $new_type_part instanceof \Psalm\Type\Atomic\TInt) { $any_scalar_type_match_found = \true; continue; } $atomic_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if ($existing_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $existing_type_part->was_static = \false; } $atomic_contained_by = \Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $new_type_part, $existing_type_part, \true, \false, $atomic_comparison_results); if ($atomic_contained_by) { $has_local_match = \true; if ($atomic_comparison_results->type_coerced && \get_class($new_type_part) === \Psalm\Type\Atomic\TNamedObject::class && $existing_type_part instanceof \Psalm\Type\Atomic\TGenericObject) { // this is a hack - it's not actually rigorous, as the params may be different $matching_atomic_types[] = new \Psalm\Type\Atomic\TGenericObject($new_type_part->value, $existing_type_part->type_params); } } elseif (\Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $existing_type_part, $new_type_part, \true, \false, null)) { $has_local_match = \true; $matching_atomic_types[] = $existing_type_part; } if ($new_type_part instanceof \Psalm\Type\Atomic\TKeyedArray && $existing_type_part instanceof \Psalm\Type\Atomic\TList) { $new_type_key = $new_type_part->getGenericKeyType(); $new_type_value = $new_type_part->getGenericValueType(); if (!$new_type_key->hasString()) { $has_param_match = \false; $new_type_value = self::filterTypeWithAnother($codebase, $existing_type_part->type_param, $new_type_value, $template_type_map, $has_param_match, $any_scalar_type_match_found); $hybrid_type_part = new \Psalm\Type\Atomic\TKeyedArray($new_type_part->properties); $hybrid_type_part->previous_key_type = \Psalm\Type::getInt(); $hybrid_type_part->previous_value_type = $new_type_value; $hybrid_type_part->is_list = \true; if (!$has_cloned_type) { $new_type = clone $new_type; $has_cloned_type = \true; } $has_local_match = \true; $new_type->removeType($key); $new_type->addType($hybrid_type_part); continue; } } if ($new_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $existing_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $new_type_part->param_name !== $existing_type_part->param_name && $new_type_part->as->hasObject() && $existing_type_part->as->hasObject()) { $new_type_part->extra_types[$existing_type_part->getKey()] = $existing_type_part; $matching_atomic_types[] = $new_type_part; $has_local_match = \true; continue; } if ($has_local_match && $new_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $existing_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $existing_type_part->as->hasObjectType()) { $existing_type_part = clone $existing_type_part; $existing_type_part->as = self::filterTypeWithAnother($codebase, $existing_type_part->as, new \Psalm\Type\Union([$new_type_part]), $template_type_map); $matching_atomic_types[] = $existing_type_part; $has_local_match = \true; continue; } if (($new_type_part instanceof \Psalm\Type\Atomic\TGenericObject || $new_type_part instanceof \Psalm\Type\Atomic\TArray || $new_type_part instanceof \Psalm\Type\Atomic\TIterable) && ($existing_type_part instanceof \Psalm\Type\Atomic\TGenericObject || $existing_type_part instanceof \Psalm\Type\Atomic\TArray || $existing_type_part instanceof \Psalm\Type\Atomic\TIterable) && \count($new_type_part->type_params) === \count($existing_type_part->type_params)) { $has_any_param_match = \false; foreach ($new_type_part->type_params as $i => $new_param) { $existing_param = $existing_type_part->type_params[$i]; $has_param_match = \true; $new_param = self::filterTypeWithAnother($codebase, $existing_param, $new_param, $template_type_map, $has_param_match, $any_scalar_type_match_found); if ($template_type_map) { $new_param->replaceTemplateTypesWithArgTypes(new \Psalm\Internal\Type\TemplateResult([], $template_type_map), $codebase); } $existing_type->bustCache(); if ($has_param_match && $existing_type_part->type_params[$i]->getId() !== $new_param->getId()) { $existing_type_part->type_params[$i] = $new_param; if (!$has_local_match) { $has_any_param_match = \true; } } } if ($has_any_param_match) { $has_local_match = \true; $matching_atomic_types[] = $existing_type_part; $atomic_comparison_results->type_coerced = \true; } } if (($new_type_part instanceof \Psalm\Type\Atomic\TArray || $new_type_part instanceof \Psalm\Type\Atomic\TIterable) && $existing_type_part instanceof \Psalm\Type\Atomic\TList) { $has_any_param_match = \false; $new_param = $new_type_part->type_params[1]; $existing_param = $existing_type_part->type_param; $has_param_match = \true; $new_param = self::filterTypeWithAnother($codebase, $existing_param, $new_param, $template_type_map, $has_param_match, $any_scalar_type_match_found); if ($template_type_map) { $new_param->replaceTemplateTypesWithArgTypes(new \Psalm\Internal\Type\TemplateResult([], $template_type_map), $codebase); } $existing_type->bustCache(); if ($has_param_match && $existing_type_part->type_param->getId() !== $new_param->getId()) { $existing_type_part->type_param = $new_param; if (!$has_local_match) { $has_any_param_match = \true; } } if ($has_any_param_match) { $has_local_match = \true; $matching_atomic_types[] = $existing_type_part; $atomic_comparison_results->type_coerced = \true; } } if ($atomic_contained_by || $atomic_comparison_results->type_coerced) { if ($atomic_contained_by && $existing_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $new_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $existing_type_part->extra_types && !$codebase->classExists($existing_type_part->value) && !$codebase->classExists($new_type_part->value) && !\array_filter($existing_type_part->extra_types, function ($extra_type) use($codebase) : bool { return $extra_type instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classExists($extra_type->value); })) { if (!$has_cloned_type) { $new_type = clone $new_type; $has_cloned_type = \true; } $new_type->removeType($key); $new_type->addType($existing_type_part); $new_type->from_docblock = $existing_type_part->from_docblock; } continue; } if ($atomic_comparison_results->scalar_type_match_found) { $any_scalar_type_match_found = \true; } } if (!$has_local_match) { $has_match = \false; break; } } if ($matching_atomic_types) { return new \Psalm\Type\Union($matching_atomic_types); } return $new_type; } /** * @param string[] $suppressed_issues */ private static function handleLiteralEquality(string $assertion, int $bracket_pos, bool $is_loose_equality, \Psalm\Type\Union $existing_var_type, string $old_var_type_string, ?string $var_id, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues) : \Psalm\Type\Union { $value = \substr($assertion, $bracket_pos + 1, -1); $scalar_type = \substr($assertion, 0, $bracket_pos); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($scalar_type === 'int') { $value = (int) $value; if ($existing_var_type->hasMixed() || $existing_var_type->hasScalar() || $existing_var_type->hasNumeric() || $existing_var_type->hasArrayKey()) { if ($is_loose_equality) { return $existing_var_type; } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralInt($value)]); } $has_int = \false; foreach ($existing_var_atomic_types as $existing_var_atomic_type) { if ($existing_var_atomic_type instanceof \Psalm\Type\Atomic\TInt) { $has_int = \true; } elseif ($existing_var_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($existing_var_atomic_type->as->hasMixed() || $existing_var_atomic_type->as->hasScalar() || $existing_var_atomic_type->as->hasNumeric() || $existing_var_atomic_type->as->hasArrayKey()) { if ($is_loose_equality) { return $existing_var_type; } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralInt($value)]); } if ($existing_var_atomic_type->as->hasInt()) { $has_int = \true; } } } if ($has_int) { $existing_int_types = $existing_var_type->getLiteralInts(); if ($existing_int_types) { $can_be_equal = \false; $did_remove_type = \false; foreach ($existing_var_atomic_types as $atomic_key => $atomic_type) { if ($atomic_key !== $assertion && !($atomic_type instanceof \Psalm\Type\Atomic\TPositiveInt && $value > 0)) { $existing_var_type->removeType($atomic_key); $did_remove_type = \true; } else { $can_be_equal = \true; } } if ($var_id && $code_location && (!$can_be_equal || !$did_remove_type && \count($existing_var_atomic_types) === 1)) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $var_id, $assertion, $can_be_equal, $negated, $code_location, $suppressed_issues); } } else { $existing_var_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralInt($value)]); } } elseif ($var_id && $code_location && !$is_loose_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $var_id, $assertion, \false, $negated, $code_location, $suppressed_issues); } elseif ($is_loose_equality && $existing_var_type->hasFloat()) { // convert floats to ints $existing_float_types = $existing_var_type->getLiteralFloats(); if ($existing_float_types) { $can_be_equal = \false; $did_remove_type = \false; foreach ($existing_var_atomic_types as $atomic_key => $_) { if (\substr($atomic_key, 0, 6) === 'float(') { $atomic_key = 'int(' . \substr($atomic_key, 6); } if ($atomic_key !== $assertion) { $existing_var_type->removeType($atomic_key); $did_remove_type = \true; } else { $can_be_equal = \true; } } if ($var_id && $code_location && (!$can_be_equal || !$did_remove_type && \count($existing_var_atomic_types) === 1)) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $var_id, $assertion, $can_be_equal, $negated, $code_location, $suppressed_issues); } } } } elseif ($scalar_type === 'string' || $scalar_type === 'class-string' || $scalar_type === 'interface-string' || $scalar_type === 'callable-string' || $scalar_type === 'trait-string') { if ($existing_var_type->hasMixed() || $existing_var_type->hasScalar() || $existing_var_type->hasArrayKey()) { if ($is_loose_equality) { return $existing_var_type; } if ($scalar_type === 'class-string' || $scalar_type === 'interface-string' || $scalar_type === 'trait-string') { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralClassString($value)]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralString($value)]); } $has_string = \false; foreach ($existing_var_atomic_types as $existing_var_atomic_type) { if ($existing_var_atomic_type instanceof \Psalm\Type\Atomic\TString) { $has_string = \true; } elseif ($existing_var_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($existing_var_atomic_type->as->hasMixed() || $existing_var_atomic_type->as->hasString() || $existing_var_atomic_type->as->hasScalar() || $existing_var_atomic_type->as->hasArrayKey()) { if ($is_loose_equality) { return $existing_var_type; } $existing_var_atomic_type = clone $existing_var_atomic_type; $existing_var_atomic_type->as = self::handleLiteralEquality($assertion, $bracket_pos, $is_loose_equality, $existing_var_atomic_type->as, $old_var_type_string, $var_id, $negated, $code_location, $suppressed_issues); return new \Psalm\Type\Union([$existing_var_atomic_type]); } if ($existing_var_atomic_type->as->hasString()) { $has_string = \true; } } } if ($has_string) { $existing_string_types = $existing_var_type->getLiteralStrings(); if ($existing_string_types) { $can_be_equal = \false; $did_remove_type = \false; foreach ($existing_var_atomic_types as $atomic_key => $_) { if ($atomic_key !== $assertion) { $existing_var_type->removeType($atomic_key); $did_remove_type = \true; } else { $can_be_equal = \true; } } if ($var_id && $code_location && (!$can_be_equal || !$did_remove_type && \count($existing_var_atomic_types) === 1)) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $var_id, $assertion, $can_be_equal, $negated, $code_location, $suppressed_issues); } } else { if ($scalar_type === 'class-string' || $scalar_type === 'interface-string' || $scalar_type === 'trait-string') { $existing_var_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralClassString($value)]); } else { $existing_var_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralString($value)]); } } } elseif ($var_id && $code_location && !$is_loose_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $var_id, $assertion, \false, $negated, $code_location, $suppressed_issues); } } elseif ($scalar_type === 'float') { $value = (float) $value; if ($existing_var_type->hasMixed() || $existing_var_type->hasScalar() || $existing_var_type->hasNumeric()) { if ($is_loose_equality) { return $existing_var_type; } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralFloat($value)]); } if ($existing_var_type->hasFloat()) { $existing_float_types = $existing_var_type->getLiteralFloats(); if ($existing_float_types) { $can_be_equal = \false; $did_remove_type = \false; foreach ($existing_var_atomic_types as $atomic_key => $_) { if ($atomic_key !== $assertion) { $existing_var_type->removeType($atomic_key); $did_remove_type = \true; } else { $can_be_equal = \true; } } if ($var_id && $code_location && (!$can_be_equal || !$did_remove_type && \count($existing_var_atomic_types) === 1)) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $var_id, $assertion, $can_be_equal, $negated, $code_location, $suppressed_issues); } } else { $existing_var_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralFloat($value)]); } } elseif ($var_id && $code_location && !$is_loose_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $var_id, $assertion, \false, $negated, $code_location, $suppressed_issues); } elseif ($is_loose_equality && $existing_var_type->hasInt()) { // convert ints to floats $existing_float_types = $existing_var_type->getLiteralInts(); if ($existing_float_types) { $can_be_equal = \false; $did_remove_type = \false; foreach ($existing_var_atomic_types as $atomic_key => $_) { if (\substr($atomic_key, 0, 4) === 'int(') { $atomic_key = 'float(' . \substr($atomic_key, 4); } if ($atomic_key !== $assertion) { $existing_var_type->removeType($atomic_key); $did_remove_type = \true; } else { $can_be_equal = \true; } } if ($var_id && $code_location && (!$can_be_equal || !$did_remove_type && \count($existing_var_atomic_types) === 1)) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $var_id, $assertion, $can_be_equal, $negated, $code_location, $suppressed_issues); } } } } return $existing_var_type; } } param_name = $param_name; $this->parent = $parent; } } value = $value; $this->parent = $parent; } } value = $value; $this->parent = $parent; } } offset_start = $offset_start; $this->offset_end = $offset_end; $this->value = $value; $this->parent = $parent; } } condition = $condition; $this->parent = $parent; } } value = $value; $this->parent = $parent; } } name = $name; $this->byref = $byref; $this->variadic = $variadic; $this->parent = $parent; } } value = $value; $this->parent = $parent; } } value = $value; $this->parent = $parent; } } param_name = $param_name; $this->as = $as; $this->parent = $parent; } } value = $value; $this->parent = $parent; } } */ private $value_types = []; /** @var array|null */ private $named_object_types = []; /** @var list */ private $array_type_params = []; /** @var array> */ private $builtin_type_params = []; /** @var array> */ private $object_type_params = []; /** @var array|null */ private $array_counts = []; /** @var bool */ private $array_sometimes_filled = \false; /** @var bool */ private $array_always_filled = \true; /** @var array */ private $objectlike_entries = []; /** @var array */ private $objectlike_class_strings = []; /** @var bool */ private $objectlike_sealed = \true; /** @var ?Union */ private $objectlike_key_type = null; /** @var ?Union */ private $objectlike_value_type = null; /** @var bool */ private $has_mixed = \false; /** @var bool */ private $empty_mixed = \false; /** @var bool */ private $non_empty_mixed = \false; /** @var ?bool */ private $mixed_from_loop_isset = null; /** @var array|null */ private $strings = []; /** @var array|null */ private $ints = []; /** @var array|null */ private $floats = []; /** @var array|null */ private $class_string_types = []; /** * @var array|null */ private $extra_types; /** @var ?bool */ private $all_arrays_lists; /** @var ?bool */ private $all_arrays_callable; /** @var ?bool */ private $all_arrays_class_string_maps; /** @var array */ private $class_string_map_names = []; /** @var array */ private $class_string_map_as_types = []; /** * Combines types together * - so `int + string = int|string` * - so `array + array = array` * - and `array + string = array|string` * - and `array + array = array` * - and `array + array = array` * - and `array + array = array` * * @param non-empty-list $types * @param int $literal_limit any greater number of literal types than this * will be merged to a scalar * */ public static function combineTypes(array $types, ?\Psalm\Codebase $codebase = null, bool $overwrite_empty_array = \false, bool $allow_mixed_union = \true, int $literal_limit = 500) : \Psalm\Type\Union { if (\in_array(null, $types, \true)) { return \Psalm\Type::getMixed(); } if (\count($types) === 1) { $union_type = new \Psalm\Type\Union([$types[0]]); if ($types[0]->from_docblock) { $union_type->from_docblock = \true; } return $union_type; } $combination = new \Psalm\Internal\Type\TypeCombination(); $from_docblock = \false; foreach ($types as $type) { $from_docblock = $from_docblock || $type->from_docblock; $result = self::scrapeTypeProperties($type, $combination, $codebase, $overwrite_empty_array, $allow_mixed_union, $literal_limit); if ($result) { if ($from_docblock) { $result->from_docblock = \true; } return $result; } } if (\count($combination->value_types) === 1 && !\count($combination->objectlike_entries) && !$combination->array_type_params && !$combination->builtin_type_params && !$combination->object_type_params && !$combination->named_object_types && !$combination->strings && !$combination->class_string_types && !$combination->ints && !$combination->floats) { if (isset($combination->value_types['false'])) { $union_type = \Psalm\Type::getFalse(); if ($from_docblock) { $union_type->from_docblock = \true; } return $union_type; } if (isset($combination->value_types['true'])) { $union_type = \Psalm\Type::getTrue(); if ($from_docblock) { $union_type->from_docblock = \true; } return $union_type; } } elseif (isset($combination->value_types['void'])) { unset($combination->value_types['void']); // if we're merging with another type, we cannot represent it in PHP $from_docblock = \true; if (!isset($combination->value_types['null'])) { $combination->value_types['null'] = new \Psalm\Type\Atomic\TNull(); } } if (isset($combination->value_types['true']) && isset($combination->value_types['false'])) { unset($combination->value_types['true'], $combination->value_types['false']); $combination->value_types['bool'] = new \Psalm\Type\Atomic\TBool(); } if ($combination->array_type_params && (isset($combination->named_object_types['Traversable']) || isset($combination->builtin_type_params['Traversable'])) && ($codebase && !$codebase->config->allow_phpstorm_generics || isset($combination->builtin_type_params['Traversable']) || isset($combination->named_object_types['Traversable']) && $combination->named_object_types['Traversable']->from_docblock) && !$combination->extra_types) { $array_param_types = $combination->array_type_params; $traversable_param_types = $combination->builtin_type_params['Traversable'] ?? [\Psalm\Type::getMixed(), \Psalm\Type::getMixed()]; $combined_param_types = []; foreach ($array_param_types as $i => $array_param_type) { $combined_param_types[] = \Psalm\Type::combineUnionTypes($array_param_type, $traversable_param_types[$i]); } $combination->value_types['iterable'] = new \Psalm\Type\Atomic\TIterable($combined_param_types); $combination->array_type_params = []; /** * @psalm-suppress PossiblyNullArrayAccess */ unset($combination->value_types['array'], $combination->named_object_types['Traversable'], $combination->builtin_type_params['Traversable']); } if ($combination->empty_mixed && $combination->non_empty_mixed) { $combination->value_types['mixed'] = new \Psalm\Type\Atomic\TMixed((bool) $combination->mixed_from_loop_isset); } $new_types = []; if (\count($combination->objectlike_entries)) { if ($combination->array_type_params && $combination->array_type_params[0]->allStringLiterals() && $combination->array_always_filled) { foreach ($combination->array_type_params[0]->getAtomicTypes() as $atomic_key_type) { if ($atomic_key_type instanceof \Psalm\Type\Atomic\TLiteralString) { $combination->objectlike_entries[$atomic_key_type->value] = $combination->array_type_params[1]; } } $combination->array_type_params = []; $combination->objectlike_sealed = \false; } if (!$combination->array_type_params || $combination->array_type_params[1]->isEmpty()) { if (!$overwrite_empty_array && ($combination->array_type_params && ($combination->array_type_params[1]->isEmpty() || $combination->array_type_params[1]->isMixed()))) { foreach ($combination->objectlike_entries as $objectlike_entry) { $objectlike_entry->possibly_undefined = \true; } } if ($combination->objectlike_value_type && $combination->objectlike_value_type->isMixed()) { $combination->objectlike_entries = \array_filter($combination->objectlike_entries, function (\Psalm\Type\Union $type) : bool { return !$type->possibly_undefined; }); } if ($combination->objectlike_entries) { if ($combination->all_arrays_callable) { $objectlike = new \Psalm\Type\Atomic\TCallableKeyedArray($combination->objectlike_entries); } else { $objectlike = new \Psalm\Type\Atomic\TKeyedArray($combination->objectlike_entries); } if ($combination->objectlike_sealed && !$combination->array_type_params) { $objectlike->sealed = \true; } if ($combination->objectlike_key_type) { $objectlike->previous_key_type = $combination->objectlike_key_type; } elseif ($combination->array_type_params && $combination->array_type_params[0]->isArrayKey()) { $objectlike->previous_key_type = $combination->array_type_params[0]; } if ($combination->objectlike_value_type) { $objectlike->previous_value_type = $combination->objectlike_value_type; } elseif ($combination->array_type_params && $combination->array_type_params[1]->isMixed()) { $objectlike->previous_value_type = $combination->array_type_params[1]; } if ($combination->all_arrays_lists) { $objectlike->is_list = \true; } $new_types[] = $objectlike; } else { $new_types[] = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getMixed()]); } // if we're merging an empty array with an object-like, clobber empty array $combination->array_type_params = []; } } if ($generic_type_params = $combination->array_type_params) { if ($combination->objectlike_entries) { $objectlike_generic_type = null; $objectlike_keys = []; foreach ($combination->objectlike_entries as $property_name => $property_type) { if ($objectlike_generic_type) { $objectlike_generic_type = \Psalm\Type::combineUnionTypes($property_type, $objectlike_generic_type, $codebase, $overwrite_empty_array); } else { $objectlike_generic_type = clone $property_type; } if (\is_int($property_name)) { $objectlike_keys[$property_name] = new \Psalm\Type\Atomic\TLiteralInt($property_name); } elseif (isset($type->class_strings[$property_name])) { $objectlike_keys[$property_name] = new \Psalm\Type\Atomic\TLiteralClassString($property_name); } else { $objectlike_keys[$property_name] = new \Psalm\Type\Atomic\TLiteralString($property_name); } } if ($combination->objectlike_value_type) { $objectlike_generic_type = \Psalm\Type::combineUnionTypes($combination->objectlike_value_type, $objectlike_generic_type, $codebase, $overwrite_empty_array); } $objectlike_generic_type->possibly_undefined = \false; $objectlike_key_type = new \Psalm\Type\Union(\array_values($objectlike_keys)); if ($combination->objectlike_key_type) { $objectlike_key_type = \Psalm\Type::combineUnionTypes($combination->objectlike_key_type, $objectlike_key_type, $codebase, $overwrite_empty_array); } $generic_type_params[0] = \Psalm\Type::combineUnionTypes($generic_type_params[0], $objectlike_key_type, $codebase, $overwrite_empty_array, $allow_mixed_union); if (!$generic_type_params[1]->isMixed()) { $generic_type_params[1] = \Psalm\Type::combineUnionTypes($generic_type_params[1], $objectlike_generic_type, $codebase, $overwrite_empty_array, $allow_mixed_union); } } if ($combination->all_arrays_callable) { $array_type = new \Psalm\Type\Atomic\TCallableArray($generic_type_params); } elseif ($combination->array_always_filled || $combination->array_sometimes_filled && $overwrite_empty_array || $combination->objectlike_entries && $combination->objectlike_sealed && $overwrite_empty_array) { if ($combination->all_arrays_lists) { if ($combination->objectlike_entries && $combination->objectlike_sealed) { $array_type = new \Psalm\Type\Atomic\TKeyedArray([$generic_type_params[1]]); $array_type->previous_key_type = \Psalm\Type::getInt(); $array_type->previous_value_type = $combination->array_type_params[1]; $array_type->is_list = \true; } else { $array_type = new \Psalm\Type\Atomic\TNonEmptyList($generic_type_params[1]); if ($combination->array_counts && \count($combination->array_counts) === 1) { $array_type->count = \array_keys($combination->array_counts)[0]; } } } else { $array_type = new \Psalm\Type\Atomic\TNonEmptyArray($generic_type_params); if ($combination->array_counts && \count($combination->array_counts) === 1) { $array_type->count = \array_keys($combination->array_counts)[0]; } } } else { if ($combination->all_arrays_class_string_maps && \count($combination->class_string_map_as_types) === 1 && \count($combination->class_string_map_names) === 1) { $array_type = new \Psalm\Type\Atomic\TClassStringMap(\array_keys($combination->class_string_map_names)[0], \array_values($combination->class_string_map_as_types)[0], $generic_type_params[1]); } elseif ($combination->all_arrays_lists) { $array_type = new \Psalm\Type\Atomic\TList($generic_type_params[1]); } else { $array_type = new \Psalm\Type\Atomic\TArray($generic_type_params); } } $new_types[] = $array_type; } if ($combination->extra_types) { /** @psalm-suppress PropertyTypeCoercion */ $combination->extra_types = self::combineTypes(\array_values($combination->extra_types), $codebase)->getAtomicTypes(); } foreach ($combination->builtin_type_params as $generic_type => $generic_type_params) { if ($generic_type === 'iterable') { $new_types[] = new \Psalm\Type\Atomic\TIterable($generic_type_params); } else { $generic_object = new \Psalm\Type\Atomic\TGenericObject($generic_type, $generic_type_params); /** @psalm-suppress PropertyTypeCoercion */ $generic_object->extra_types = $combination->extra_types; $new_types[] = $generic_object; if ($combination->named_object_types) { unset($combination->named_object_types[$generic_type]); } } } foreach ($combination->object_type_params as $generic_type => $generic_type_params) { $generic_type = \substr($generic_type, 0, (int) \strpos($generic_type, '<')); $generic_object = new \Psalm\Type\Atomic\TGenericObject($generic_type, $generic_type_params); /** @psalm-suppress PropertyTypeCoercion */ $generic_object->extra_types = $combination->extra_types; $new_types[] = $generic_object; } if ($combination->class_string_types) { if ($combination->strings) { foreach ($combination->strings as $k => $string) { if ($string instanceof \Psalm\Type\Atomic\TLiteralClassString) { $combination->class_string_types[$string->value] = new \Psalm\Type\Atomic\TNamedObject($string->value); unset($combination->strings[$k]); } } } if (!isset($combination->value_types['string'])) { $object_type = self::combineTypes(\array_values($combination->class_string_types), $codebase); foreach ($object_type->getAtomicTypes() as $object_atomic_type) { if ($object_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $new_types[] = new \Psalm\Type\Atomic\TClassString($object_atomic_type->value, $object_atomic_type); } elseif ($object_atomic_type instanceof \Psalm\Type\Atomic\TObject) { $new_types[] = new \Psalm\Type\Atomic\TClassString(); } } } } if ($combination->strings) { $new_types = \array_merge($new_types, \array_values($combination->strings)); } if ($combination->ints) { $new_types = \array_merge($new_types, \array_values($combination->ints)); } if ($combination->floats) { $new_types = \array_merge($new_types, \array_values($combination->floats)); } if (isset($combination->value_types['string']) && isset($combination->value_types['int']) && isset($combination->value_types['bool']) && isset($combination->value_types['float'])) { unset($combination->value_types['string'], $combination->value_types['int'], $combination->value_types['bool'], $combination->value_types['float']); $combination->value_types['scalar'] = new \Psalm\Type\Atomic\TScalar(); } if ($combination->named_object_types !== null) { $combination->value_types += $combination->named_object_types; } $has_empty = (int) isset($combination->value_types['empty']); foreach ($combination->value_types as $type) { if ($type instanceof \Psalm\Type\Atomic\TMixed && $combination->mixed_from_loop_isset && (\count($combination->value_types) > 1 + $has_empty || \count($new_types) > $has_empty)) { continue; } if ($type instanceof \Psalm\Type\Atomic\TEmpty && (\count($combination->value_types) > 1 || \count($new_types))) { continue; } $new_types[] = $type; } if (!$new_types) { throw new \UnexpectedValueException('There should be types here'); } $union_type = new \Psalm\Type\Union($new_types); if ($from_docblock) { $union_type->from_docblock = \true; } return $union_type; } private static function scrapeTypeProperties(\Psalm\Type\Atomic $type, \Psalm\Internal\Type\TypeCombination $combination, ?\Psalm\Codebase $codebase, bool $overwrite_empty_array, bool $allow_mixed_union, int $literal_limit) : ?\Psalm\Type\Union { if ($type instanceof \Psalm\Type\Atomic\TMixed) { $combination->has_mixed = \true; if ($type->from_loop_isset) { if ($combination->mixed_from_loop_isset === null) { $combination->mixed_from_loop_isset = \true; } else { return null; } } else { $combination->mixed_from_loop_isset = \false; } if ($type instanceof \Psalm\Type\Atomic\TNonEmptyMixed) { $combination->non_empty_mixed = \true; if ($combination->empty_mixed) { return null; } } elseif ($type instanceof \Psalm\Type\Atomic\TEmptyMixed) { $combination->empty_mixed = \true; if ($combination->non_empty_mixed) { return null; } } else { $combination->empty_mixed = \true; $combination->non_empty_mixed = \true; } if (!$allow_mixed_union) { return \Psalm\Type::getMixed((bool) $combination->mixed_from_loop_isset); } } // deal with false|bool => bool if (($type instanceof \Psalm\Type\Atomic\TFalse || $type instanceof \Psalm\Type\Atomic\TTrue) && isset($combination->value_types['bool'])) { return null; } if (\get_class($type) === \Psalm\Type\Atomic\TBool::class && isset($combination->value_types['false'])) { unset($combination->value_types['false']); } if (\get_class($type) === \Psalm\Type\Atomic\TBool::class && isset($combination->value_types['true'])) { unset($combination->value_types['true']); } if ($type instanceof \Psalm\Type\Atomic\TArray && isset($combination->builtin_type_params['iterable'])) { $type_key = 'iterable'; } elseif ($type instanceof \Psalm\Type\Atomic\TArray && $type->type_params[1]->isMixed() && isset($combination->value_types['iterable'])) { $type_key = 'iterable'; $combination->builtin_type_params['iterable'] = [\Psalm\Type::getMixed(), \Psalm\Type::getMixed()]; } elseif ($type instanceof \Psalm\Type\Atomic\TNamedObject && $type->value === 'Traversable' && (isset($combination->builtin_type_params['iterable']) || isset($combination->value_types['iterable']))) { $type_key = 'iterable'; if (!isset($combination->builtin_type_params['iterable'])) { $combination->builtin_type_params['iterable'] = [\Psalm\Type::getMixed(), \Psalm\Type::getMixed()]; } if (!$type instanceof \Psalm\Type\Atomic\TGenericObject) { $type = new \Psalm\Type\Atomic\TGenericObject($type->value, [\Psalm\Type::getMixed(), \Psalm\Type::getMixed()]); } } elseif ($type instanceof \Psalm\Type\Atomic\TNamedObject && ($type->value === 'Traversable' || $type->value === 'Generator')) { $type_key = $type->value; } else { $type_key = $type->getKey(); } if ($type instanceof \Psalm\Type\Atomic\TIterable && $combination->array_type_params && ($type->has_docblock_params || $combination->array_type_params[1]->isMixed())) { if (!isset($combination->builtin_type_params['iterable'])) { $combination->builtin_type_params['iterable'] = $combination->array_type_params; } else { foreach ($combination->array_type_params as $i => $array_type_param) { $iterable_type_param = $combination->builtin_type_params['iterable'][$i]; /** @psalm-suppress PropertyTypeCoercion */ $combination->builtin_type_params['iterable'][$i] = \Psalm\Type::combineUnionTypes($iterable_type_param, $array_type_param); } } $combination->array_type_params = []; } if ($type instanceof \Psalm\Type\Atomic\TIterable && (isset($combination->named_object_types['Traversable']) || isset($combination->builtin_type_params['Traversable']))) { if (!isset($combination->builtin_type_params['iterable'])) { $combination->builtin_type_params['iterable'] = $combination->builtin_type_params['Traversable'] ?? [\Psalm\Type::getMixed(), \Psalm\Type::getMixed()]; } elseif (isset($combination->builtin_type_params['Traversable'])) { foreach ($combination->builtin_type_params['Traversable'] as $i => $array_type_param) { $iterable_type_param = $combination->builtin_type_params['iterable'][$i]; /** @psalm-suppress PropertyTypeCoercion */ $combination->builtin_type_params['iterable'][$i] = \Psalm\Type::combineUnionTypes($iterable_type_param, $array_type_param); } } else { $combination->builtin_type_params['iterable'] = [\Psalm\Type::getMixed(), \Psalm\Type::getMixed()]; } /** @psalm-suppress PossiblyNullArrayAccess */ unset($combination->named_object_types['Traversable'], $combination->builtin_type_params['Traversable']); } if ($type instanceof \Psalm\Type\Atomic\TNamedObject || $type instanceof \Psalm\Type\Atomic\TTemplateParam || $type instanceof \Psalm\Type\Atomic\TIterable || $type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { if ($type->extra_types) { $combination->extra_types = \array_merge($combination->extra_types ?: [], $type->extra_types); } } if ($type instanceof \Psalm\Type\Atomic\TArray && $type_key === 'array') { if ($type instanceof \Psalm\Type\Atomic\TCallableArray && isset($combination->value_types['callable'])) { return null; } foreach ($type->type_params as $i => $type_param) { if (isset($combination->array_type_params[$i])) { $combination->array_type_params[$i] = \Psalm\Type::combineUnionTypes($combination->array_type_params[$i], $type_param, $codebase, $overwrite_empty_array); } else { /** @psalm-suppress PropertyTypeCoercion */ $combination->array_type_params[$i] = $type_param; } } if ($type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { if ($combination->array_counts !== null) { if ($type->count === null) { $combination->array_counts = null; } else { $combination->array_counts[$type->count] = \true; } } $combination->array_sometimes_filled = \true; } else { $combination->array_always_filled = \false; } if (!$type->type_params[1]->isEmpty()) { $combination->all_arrays_lists = \false; $combination->all_arrays_class_string_maps = \false; } if ($type instanceof \Psalm\Type\Atomic\TCallableArray) { if ($combination->all_arrays_callable !== \false) { $combination->all_arrays_callable = \true; } } else { $combination->all_arrays_callable = \false; } return null; } if ($type instanceof \Psalm\Type\Atomic\TList) { foreach ([\Psalm\Type::getInt(), $type->type_param] as $i => $type_param) { if (isset($combination->array_type_params[$i])) { /** @psalm-suppress PropertyTypeCoercion */ $combination->array_type_params[$i] = \Psalm\Type::combineUnionTypes($combination->array_type_params[$i], $type_param, $codebase, $overwrite_empty_array); } else { /** @psalm-suppress PropertyTypeCoercion */ $combination->array_type_params[$i] = $type_param; } } if ($type instanceof \Psalm\Type\Atomic\TNonEmptyList) { if ($combination->array_counts !== null) { if ($type->count === null) { $combination->array_counts = null; } else { $combination->array_counts[$type->count] = \true; } } $combination->array_sometimes_filled = \true; } else { $combination->array_always_filled = \false; } if ($combination->all_arrays_lists !== \false) { $combination->all_arrays_lists = \true; } $combination->all_arrays_callable = \false; $combination->all_arrays_class_string_maps = \false; return null; } if ($type instanceof \Psalm\Type\Atomic\TClassStringMap) { foreach ([$type->getStandinKeyParam(), $type->value_param] as $i => $type_param) { if (isset($combination->array_type_params[$i])) { /** @psalm-suppress PropertyTypeCoercion */ $combination->array_type_params[$i] = \Psalm\Type::combineUnionTypes($combination->array_type_params[$i], $type_param, $codebase, $overwrite_empty_array); } else { /** @psalm-suppress PropertyTypeCoercion */ $combination->array_type_params[$i] = $type_param; } } $combination->array_always_filled = \false; if ($combination->all_arrays_class_string_maps !== \false) { $combination->all_arrays_class_string_maps = \true; $combination->class_string_map_names[$type->param_name] = \true; $combination->class_string_map_as_types[(string) $type->as_type] = $type->as_type; } return null; } if ($type instanceof \Psalm\Type\Atomic\TGenericObject && ($type->value === 'Traversable' || $type->value === 'Generator') || $type instanceof \Psalm\Type\Atomic\TIterable && $type->has_docblock_params || $type instanceof \Psalm\Type\Atomic\TArray && $type_key === 'iterable') { foreach ($type->type_params as $i => $type_param) { if (isset($combination->builtin_type_params[$type_key][$i])) { /** @psalm-suppress PropertyTypeCoercion */ $combination->builtin_type_params[$type_key][$i] = \Psalm\Type::combineUnionTypes($combination->builtin_type_params[$type_key][$i], $type_param, $codebase, $overwrite_empty_array); } else { /** @psalm-suppress PropertyTypeCoercion */ $combination->builtin_type_params[$type_key][$i] = $type_param; } } return null; } if ($type instanceof \Psalm\Type\Atomic\TGenericObject) { foreach ($type->type_params as $i => $type_param) { if (isset($combination->object_type_params[$type_key][$i])) { /** @psalm-suppress PropertyTypeCoercion */ $combination->object_type_params[$type_key][$i] = \Psalm\Type::combineUnionTypes($combination->object_type_params[$type_key][$i], $type_param, $codebase, $overwrite_empty_array); } else { /** @psalm-suppress PropertyTypeCoercion */ $combination->object_type_params[$type_key][$i] = $type_param; } } return null; } if ($type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($type instanceof \Psalm\Type\Atomic\TCallableKeyedArray && isset($combination->value_types['callable'])) { return null; } $existing_objectlike_entries = (bool) $combination->objectlike_entries; $possibly_undefined_entries = $combination->objectlike_entries; $combination->objectlike_sealed = $combination->objectlike_sealed && $type->sealed; if ($type->previous_value_type) { if (!$combination->objectlike_value_type) { $combination->objectlike_value_type = $type->previous_value_type; } else { $combination->objectlike_value_type = \Psalm\Type::combineUnionTypes($type->previous_value_type, $combination->objectlike_value_type, $codebase, $overwrite_empty_array); } } if ($type->previous_key_type) { if (!$combination->objectlike_key_type) { $combination->objectlike_key_type = $type->previous_key_type; } else { $combination->objectlike_key_type = \Psalm\Type::combineUnionTypes($type->previous_key_type, $combination->objectlike_key_type, $codebase, $overwrite_empty_array); } } $has_defined_keys = \false; foreach ($type->properties as $candidate_property_name => $candidate_property_type) { $value_type = isset($combination->objectlike_entries[$candidate_property_name]) ? $combination->objectlike_entries[$candidate_property_name] : null; if (!$value_type) { $combination->objectlike_entries[$candidate_property_name] = clone $candidate_property_type; // it's possibly undefined if there are existing objectlike entries and $combination->objectlike_entries[$candidate_property_name]->possibly_undefined = $existing_objectlike_entries || $candidate_property_type->possibly_undefined; } else { $combination->objectlike_entries[$candidate_property_name] = \Psalm\Type::combineUnionTypes($value_type, $candidate_property_type, $codebase, $overwrite_empty_array); } if (\is_string($candidate_property_name) && isset($type->class_strings[$candidate_property_name])) { $combination->objectlike_class_strings[$candidate_property_name] = \true; } if (!$type->previous_value_type) { unset($possibly_undefined_entries[$candidate_property_name]); } if (!$candidate_property_type->possibly_undefined) { $has_defined_keys = \true; } } if (!$has_defined_keys) { $combination->array_always_filled = \false; } if ($combination->array_counts !== null) { $combination->array_counts[\count($type->properties)] = \true; } foreach ($possibly_undefined_entries as $possibly_undefined_type) { $possibly_undefined_type->possibly_undefined = \true; } if (!$type->is_list) { $combination->all_arrays_lists = \false; } elseif ($combination->all_arrays_lists !== \false) { $combination->all_arrays_lists = \true; } if ($type instanceof \Psalm\Type\Atomic\TCallableKeyedArray) { if ($combination->all_arrays_callable !== \false) { $combination->all_arrays_callable = \true; } } else { $combination->all_arrays_callable = \false; } $combination->all_arrays_class_string_maps = \false; return null; } if ($type instanceof \Psalm\Type\Atomic\TObject) { if ($type instanceof \Psalm\Type\Atomic\TCallableObject && isset($combination->value_types['callable'])) { return null; } $combination->named_object_types = null; $combination->value_types[$type_key] = $type; return null; } if ($type instanceof \Psalm\Type\Atomic\TIterable) { $combination->value_types[$type_key] = $type; return null; } if ($type instanceof \Psalm\Type\Atomic\TNamedObject) { if ($combination->named_object_types === null) { return null; } if (isset($combination->named_object_types[$type_key])) { return null; } if (!$codebase) { $combination->named_object_types[$type_key] = $type; return null; } if (!$codebase->classlikes->classOrInterfaceExists($type_key)) { // write this to the main list $combination->value_types[$type_key] = $type; return null; } $is_class = $codebase->classExists($type_key); foreach ($combination->named_object_types as $key => $_) { if ($codebase->classExists($key)) { if ($codebase->classExtendsOrImplements($key, $type_key)) { unset($combination->named_object_types[$key]); continue; } if ($is_class) { if ($codebase->classExtends($type_key, $key)) { return null; } } } else { if ($codebase->interfaceExtends($key, $type_key)) { unset($combination->named_object_types[$key]); continue; } if ($is_class) { if ($codebase->classImplements($type_key, $key)) { return null; } } else { if ($codebase->interfaceExtends($type_key, $key)) { return null; } } } } $combination->named_object_types[$type_key] = $type; return null; } if ($type instanceof \Psalm\Type\Atomic\TScalar) { $combination->strings = null; $combination->ints = null; $combination->floats = null; unset($combination->value_types['string'], $combination->value_types['int'], $combination->value_types['bool'], $combination->value_types['true'], $combination->value_types['false'], $combination->value_types['float']); $combination->value_types[$type_key] = $type; return null; } if ($type instanceof \Psalm\Type\Atomic\Scalar && isset($combination->value_types['scalar'])) { return null; } if ($type instanceof \Psalm\Type\Atomic\TArrayKey) { $combination->strings = null; $combination->ints = null; unset($combination->value_types['string'], $combination->value_types['int']); $combination->value_types[$type_key] = $type; return null; } if ($type instanceof \Psalm\Type\Atomic\TString) { if ($type instanceof \Psalm\Type\Atomic\TCallableString && isset($combination->value_types['callable'])) { return null; } if (isset($combination->value_types['array-key'])) { return null; } if ($type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $combination->value_types[$type_key] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TClassString) { if (!$type->as_type) { $combination->class_string_types['object'] = new \Psalm\Type\Atomic\TObject(); } else { $combination->class_string_types[$type->as] = $type->as_type; } } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralString) { if ($combination->strings !== null && \count($combination->strings) < $literal_limit) { $combination->strings[$type_key] = $type; } else { $shared_classlikes = $codebase ? $combination->getSharedTypes($codebase) : []; $combination->strings = null; if (isset($combination->value_types['string']) && $combination->value_types['string'] instanceof \Psalm\Type\Atomic\TNumericString && \is_numeric($type->value)) { // do nothing } elseif (isset($combination->value_types['class-string']) && $type instanceof \Psalm\Type\Atomic\TLiteralClassString) { // do nothing } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralClassString) { $type_classlikes = $codebase ? self::getClassLikes($codebase, $type->value) : []; $mutual = \array_intersect_key($type_classlikes, $shared_classlikes); if ($mutual) { $first_class = \array_keys($mutual)[0]; $combination->class_string_types[$first_class] = new \Psalm\Type\Atomic\TNamedObject($first_class); } else { $combination->class_string_types['object'] = new \Psalm\Type\Atomic\TObject(); } } else { if (isset($combination->value_types['string']) && $combination->value_types['string'] instanceof \Psalm\Type\Atomic\TLowercaseString && \strtolower($type->value) === $type->value) { // do nothing } else { $combination->value_types['string'] = new \Psalm\Type\Atomic\TString(); } } } } else { $type_key = 'string'; if (!isset($combination->value_types['string'])) { if ($combination->strings) { if ($type instanceof \Psalm\Type\Atomic\TNumericString) { $has_non_numeric_string = \false; foreach ($combination->strings as $string_type) { if (!\is_numeric($string_type->value)) { $has_non_numeric_string = \true; break; } } if ($has_non_numeric_string) { $combination->value_types['string'] = new \Psalm\Type\Atomic\TString(); } else { $combination->value_types['string'] = $type; } $combination->strings = null; } elseif ($type instanceof \Psalm\Type\Atomic\TLowercaseString) { $has_non_lowercase_string = \false; foreach ($combination->strings as $string_type) { if (\strtolower($string_type->value) !== $string_type->value) { $has_non_lowercase_string = \true; break; } } if ($has_non_lowercase_string) { $combination->value_types['string'] = new \Psalm\Type\Atomic\TString(); } else { $combination->value_types['string'] = $type; } $combination->strings = null; } else { $has_non_literal_class_string = \false; $shared_classlikes = $codebase ? $combination->getSharedTypes($codebase) : []; foreach ($combination->strings as $string_type) { if (!$string_type instanceof \Psalm\Type\Atomic\TLiteralClassString) { $has_non_literal_class_string = \true; break; } } if ($has_non_literal_class_string || !$type instanceof \Psalm\Type\Atomic\TClassString) { $combination->value_types[$type_key] = new \Psalm\Type\Atomic\TString(); } else { if (isset($shared_classlikes[$type->as]) && $type->as_type) { $combination->class_string_types[$type->as] = $type->as_type; } else { $combination->class_string_types['object'] = new \Psalm\Type\Atomic\TObject(); } } } } else { $combination->value_types[$type_key] = $type; } } elseif (\get_class($combination->value_types['string']) !== \Psalm\Type\Atomic\TString::class) { if (\get_class($type) === \Psalm\Type\Atomic\TString::class) { $combination->value_types['string'] = $type; } elseif ($combination->value_types['string'] instanceof \Psalm\Type\Atomic\TTraitString && $type instanceof \Psalm\Type\Atomic\TClassString) { $combination->value_types['trait-string'] = $combination->value_types['string']; $combination->value_types['class-string'] = $type; unset($combination->value_types['string']); } elseif (\get_class($combination->value_types['string']) !== \get_class($type)) { if (\get_class($type) === \Psalm\Type\Atomic\TNonEmptyString::class && \get_class($combination->value_types['string']) === \Psalm\Type\Atomic\TNonEmptyLowercaseString::class) { $combination->value_types['string'] = $type; } elseif (\get_class($combination->value_types['string']) === \Psalm\Type\Atomic\TNonEmptyString::class && \get_class($type) === \Psalm\Type\Atomic\TNonEmptyLowercaseString::class) { //no-change } elseif (\get_class($type) === \Psalm\Type\Atomic\TLowercaseString::class && \get_class($combination->value_types['string']) === \Psalm\Type\Atomic\TNonEmptyLowercaseString::class) { $combination->value_types['string'] = $type; } elseif (\get_class($combination->value_types['string']) === \Psalm\Type\Atomic\TLowercaseString::class && \get_class($type) === \Psalm\Type\Atomic\TNonEmptyLowercaseString::class) { //no-change } else { $combination->value_types['string'] = new \Psalm\Type\Atomic\TString(); } } } $combination->strings = null; } return null; } if ($type instanceof \Psalm\Type\Atomic\TInt) { if (isset($combination->value_types['array-key'])) { return null; } $had_zero = isset($combination->ints['int(0)']); if ($type instanceof \Psalm\Type\Atomic\TLiteralInt) { if ($type->value === 0) { $had_zero = \true; } if ($combination->ints !== null && \count($combination->ints) < $literal_limit) { $combination->ints[$type_key] = $type; } else { $combination->ints[$type_key] = $type; $all_nonnegative = !\array_filter($combination->ints, function ($int) : bool { return $int->value < 0; }); $combination->ints = null; if (!isset($combination->value_types['int'])) { $combination->value_types['int'] = $all_nonnegative ? new \Psalm\Type\Atomic\TPositiveInt() : new \Psalm\Type\Atomic\TInt(); } elseif ($combination->value_types['int'] instanceof \Psalm\Type\Atomic\TPositiveInt && !$all_nonnegative) { $combination->value_types['int'] = new \Psalm\Type\Atomic\TInt(); } } } else { if ($type instanceof \Psalm\Type\Atomic\TPositiveInt) { if ($combination->ints) { $all_nonnegative = !\array_filter($combination->ints, function ($int) : bool { return $int->value < 0; }); if ($all_nonnegative) { $combination->value_types['int'] = $type; } else { $combination->value_types['int'] = new \Psalm\Type\Atomic\TInt(); } } elseif (!isset($combination->value_types['int'])) { $combination->value_types['int'] = $type; } } else { $combination->value_types['int'] = $type; } $combination->ints = null; } if ($had_zero && isset($combination->value_types['int']) && $combination->value_types['int'] instanceof \Psalm\Type\Atomic\TPositiveInt) { $combination->ints = ['int(0)' => new \Psalm\Type\Atomic\TLiteralInt(0)]; } return null; } if ($type instanceof \Psalm\Type\Atomic\TFloat) { if ($type instanceof \Psalm\Type\Atomic\TLiteralFloat) { if ($combination->floats !== null && \count($combination->floats) < $literal_limit) { $combination->floats[$type_key] = $type; } else { $combination->floats = null; $combination->value_types['float'] = new \Psalm\Type\Atomic\TFloat(); } } else { $combination->floats = null; $combination->value_types['float'] = $type; } return null; } if ($type instanceof \Psalm\Type\Atomic\TCallable && $type_key === 'callable') { if (($combination->value_types['string'] ?? null) instanceof \Psalm\Type\Atomic\TCallableString) { unset($combination->value_types['string']); } elseif (!empty($combination->array_type_params) && $combination->all_arrays_callable) { $combination->array_type_params = []; } elseif (isset($combination->value_types['callable-object'])) { unset($combination->value_types['callable-object']); } } $combination->value_types[$type_key] = $type; return null; } /** * @return array */ private function getSharedTypes(\Psalm\Codebase $codebase) : array { /** @var array|null */ $shared_classlikes = null; if ($this->strings) { foreach ($this->strings as $string_type) { $classlikes = self::getClassLikes($codebase, $string_type->value); if ($shared_classlikes === null) { $shared_classlikes = $classlikes; } elseif ($shared_classlikes) { $shared_classlikes = \array_intersect_key($shared_classlikes, $classlikes); } } } if ($this->class_string_types) { foreach ($this->class_string_types as $value_type) { if ($value_type instanceof \Psalm\Type\Atomic\TNamedObject) { $classlikes = self::getClassLikes($codebase, $value_type->value); if ($shared_classlikes === null) { $shared_classlikes = $classlikes; } elseif ($shared_classlikes) { $shared_classlikes = \array_intersect_key($shared_classlikes, $classlikes); } } } } return $shared_classlikes ?: []; } /** * @return array */ private static function getClassLikes(\Psalm\Codebase $codebase, string $fq_classlike_name) : array { try { $class_storage = $codebase->classlike_storage_provider->get($fq_classlike_name); } catch (\InvalidArgumentException $e) { return []; } $classlikes = []; $classlikes[$fq_classlike_name] = \true; foreach ($class_storage->parent_classes as $parent_class) { $classlikes[$parent_class] = \true; } foreach ($class_storage->parent_interfaces as $parent_interface) { $classlikes[$parent_interface] = \true; } foreach ($class_storage->class_implements as $interface) { $classlikes[$interface] = \true; } return $classlikes; } } */ public $children = []; /** * @var null|ParseTree */ public $parent; /** * @var bool */ public $possibly_undefined = \false; public function __construct(?\Psalm\Internal\Type\ParseTree $parent = null) { $this->parent = $parent; } public function __destruct() { $this->parent = null; } public function cleanParents() : void { foreach ($this->children as $child) { $child->cleanParents(); } $this->parent = null; } } */ public const PSALM_RESERVED_WORDS = ['int' => \true, 'string' => \true, 'float' => \true, 'bool' => \true, 'false' => \true, 'true' => \true, 'object' => \true, 'empty' => \true, 'callable' => \true, 'array' => \true, 'non-empty-array' => \true, 'non-empty-string' => \true, 'iterable' => \true, 'null' => \true, 'mixed' => \true, 'numeric-string' => \true, 'class-string' => \true, 'callable-string' => \true, 'callable-array' => \true, 'pure-callable' => \true, 'pure-Closure' => \true, 'trait-string' => \true, 'mysql-escaped-string' => \true, 'html-escaped-string' => \true, 'lowercase-string' => \true, 'non-empty-lowercase-string' => \true, 'positive-int' => \true, 'boolean' => \true, 'integer' => \true, 'double' => \true, 'real' => \true, 'resource' => \true, 'void' => \true, 'self' => \true, 'static' => \true, 'scalar' => \true, 'numeric' => \true, 'no-return' => \true, 'never-return' => \true, 'never-returns' => \true, 'array-key' => \true, 'key-of' => \true, 'value-of' => \true, 'non-empty-countable' => \true, 'list' => \true, 'non-empty-list' => \true, 'class-string-map' => \true, 'open-resource' => \true, 'closed-resource' => \true, 'associative-array' => \true, 'arraylike-object' => \true]; /** * @var array> */ private static $memoized_tokens = []; /** * @return list */ public static function tokenize(string $string_type, bool $ignore_space = \true) : array { $type_tokens = [['', 0]]; $was_char = \false; $quote_char = null; $escaped = \false; if (isset(self::$memoized_tokens[$string_type])) { return self::$memoized_tokens[$string_type]; } // index of last type token $rtc = 0; $chars = \str_split($string_type); $was_space = \false; for ($i = 0, $c = \count($chars); $i < $c; ++$i) { $char = $chars[$i]; if (!$quote_char && $char === ' ' && $ignore_space) { $was_space = \true; continue; } if ($was_space && ($char === '$' || $char === '.' && ($chars[$i + 1] ?? null) === '.' && ($chars[$i + 2] ?? null) === '.' && ($chars[$i + 3] ?? null) === '$')) { $type_tokens[++$rtc] = [' ', $i - 1]; $type_tokens[++$rtc] = ['', $i]; } elseif ($was_space && ($char === 'a' || $char === 'i') && ($chars[$i + 1] ?? null) === 's' && ($chars[$i + 2] ?? null) === ' ') { $type_tokens[++$rtc] = [$char . 's', $i - 1]; $type_tokens[++$rtc] = ['', ++$i]; continue; } elseif ($was_char) { $type_tokens[++$rtc] = ['', $i]; } if ($quote_char) { if ($char === $quote_char && $i > 0 && !$escaped) { $quote_char = null; $type_tokens[$rtc][0] .= $char; $was_char = \true; continue; } $was_char = \false; if ($char === '\\' && !$escaped && $i < $c - 1 && ($chars[$i + 1] === $quote_char || $chars[$i + 1] === '\\')) { $escaped = \true; continue; } $escaped = \false; $type_tokens[$rtc][0] .= $char; continue; } if ($char === '"' || $char === '\'') { if ($type_tokens[$rtc][0] === '') { $type_tokens[$rtc] = [$char, $i]; } else { $type_tokens[++$rtc] = [$char, $i]; } $quote_char = $char; $was_char = \false; $was_space = \false; continue; } if ($char === '<' || $char === '>' || $char === '|' || $char === '?' || $char === ',' || $char === '{' || $char === '}' || $char === '[' || $char === ']' || $char === '(' || $char === ')' || $char === ' ' || $char === '&' || $char === '=') { if ($char === '(' && $type_tokens[$rtc][0] === 'func_num_args' && isset($chars[$i + 1]) && $chars[$i + 1] === ')') { $type_tokens[$rtc][0] = 'func_num_args()'; ++$i; continue; } if ($type_tokens[$rtc][0] === '') { $type_tokens[$rtc] = [$char, $i]; } else { $type_tokens[++$rtc] = [$char, $i]; } $was_char = \true; $was_space = \false; continue; } if ($char === ':') { if ($i + 1 < $c && $chars[$i + 1] === ':') { if ($type_tokens[$rtc][0] === '') { $type_tokens[$rtc] = ['::', $i]; } else { $type_tokens[++$rtc] = ['::', $i]; } $was_char = \true; $was_space = \false; ++$i; continue; } if ($type_tokens[$rtc][0] === '') { $type_tokens[$rtc] = [':', $i]; } else { $type_tokens[++$rtc] = [':', $i]; } $was_char = \true; $was_space = \false; continue; } if ($char === '.') { if ($i + 1 < $c && \is_numeric($chars[$i + 1]) && $i > 0 && \is_numeric($chars[$i - 1])) { $type_tokens[$rtc][0] .= $char; $was_char = \false; $was_space = \false; continue; } if ($i + 2 > $c || $chars[$i + 1] !== '.' || $chars[$i + 2] !== '.') { throw new \Psalm\Exception\TypeParseTreeException('Unexpected token ' . $char); } if ($type_tokens[$rtc][0] === '') { $type_tokens[$rtc] = ['...', $i]; } else { $type_tokens[++$rtc] = ['...', $i]; } $was_char = \true; $was_space = \false; $i += 2; continue; } $type_tokens[$rtc][0] .= $char; $was_char = \false; $was_space = \false; } /** @var list $type_tokens */ self::$memoized_tokens[$string_type] = $type_tokens; return $type_tokens; } /** * @param array{int,int}|null $php_version * * * @psalm-pure */ public static function fixScalarTerms(string $type_string, ?array $php_version = null) : string { $type_string_lc = \strtolower($type_string); switch ($type_string_lc) { case 'int': case 'void': case 'float': case 'string': case 'bool': case 'callable': case 'iterable': case 'array': case 'object': case 'true': case 'false': case 'null': case 'mixed': return $type_string_lc; } switch ($type_string) { case 'boolean': return $php_version !== null ? $type_string : 'bool'; case 'integer': return $php_version !== null ? $type_string : 'int'; case 'double': case 'real': return $php_version !== null ? $type_string : 'float'; } return $type_string; } /** * @param array|null $template_type_map * @param array|null $type_aliases * * @return list */ public static function getFullyQualifiedTokens(string $string_type, \Psalm\Aliases $aliases, ?array $template_type_map = null, ?array $type_aliases = null, ?string $self_fqcln = null, ?string $parent_fqcln = null, bool $allow_assertions = \false) : array { $type_tokens = self::tokenize($string_type); for ($i = 0, $l = \count($type_tokens); $i < $l; ++$i) { $string_type_token = $type_tokens[$i]; if (\in_array($string_type_token[0], ['<', '>', '|', '?', ',', '{', '}', ':', '::', '[', ']', '(', ')', '&', '=', '...', 'as', 'is'], \true)) { continue; } if ($string_type_token[0][0] === '\\' && \strlen($string_type_token[0]) === 1) { throw new \Psalm\Exception\TypeParseTreeException("Backslash \"\\\" has to be part of class name."); } if ($string_type_token[0][0] === '"' || $string_type_token[0][0] === '\'' || \preg_match('/[0-9]/', $string_type_token[0][0])) { continue; } if (isset($type_tokens[$i + 1]) && $type_tokens[$i + 1][0] === ':' && isset($type_tokens[$i - 1]) && ($type_tokens[$i - 1][0] === '{' || $type_tokens[$i - 1][0] === ',')) { continue; } if ($i > 0 && $type_tokens[$i - 1][0] === '::') { continue; } if (\strpos($string_type_token[0], '$')) { $string_type_token[0] = \preg_replace('/(.+)\\$.*/', '$1', $string_type_token[0]); } $fixed_token = !isset($type_tokens[$i + 1]) || $type_tokens[$i + 1][0] !== '(' ? self::fixScalarTerms($string_type_token[0]) : $string_type_token[0]; $type_tokens[$i][0] = $fixed_token; $string_type_token[0] = $fixed_token; if ($string_type_token[0] === 'self' && $self_fqcln) { $type_tokens[$i][0] = $self_fqcln; continue; } if ($string_type_token[0] === 'parent' && $parent_fqcln) { $type_tokens[$i][0] = $parent_fqcln; continue; } if (isset(self::PSALM_RESERVED_WORDS[$string_type_token[0]])) { continue; } if (isset($template_type_map[$string_type_token[0]])) { continue; } if ($i > 1 && $type_tokens[$i - 2][0] === 'class-string-map' && $type_tokens[$i - 1][0] === '<') { $template_type_map[$string_type_token[0]] = \true; continue; } if (isset($type_tokens[$i + 1]) && isset($type_tokens[$i - 1]) && ($type_tokens[$i - 1][0] === '{' || $type_tokens[$i - 1][0] === ',')) { $next_char = $type_tokens[$i + 1][0]; if ($next_char === ':') { continue; } if ($next_char === '?' && isset($type_tokens[$i + 2]) && $type_tokens[$i + 2][0] === ':') { continue; } } if ($string_type_token[0][0] === '$' || $string_type_token[0][0] === ' ') { continue; } if (isset($type_tokens[$i + 1]) && $type_tokens[$i + 1][0] === '(') { continue; } if ($allow_assertions && $string_type_token[0] === 'falsy') { $type_tokens[$i][0] = 'false-y'; continue; } if ($string_type_token[0] === 'func_num_args()') { continue; } if (isset($type_aliases[$string_type_token[0]])) { $type_alias = $type_aliases[$string_type_token[0]]; if ($type_alias instanceof \Psalm\Internal\Type\TypeAlias\InlineTypeAlias) { $replacement_tokens = $type_alias->replacement_tokens; \array_unshift($replacement_tokens, ['(', $i]); \array_push($replacement_tokens, [')', $i]); $diff = \count($replacement_tokens) - 1; \array_splice($type_tokens, $i, 1, $replacement_tokens); $i += $diff; $l += $diff; } } else { $type_tokens[$i][0] = \Psalm\Type::getFQCLNFromString($string_type_token[0], $aliases); } } /** @var list */ return $type_tokens; } public static function clearCache() : void { self::$memoized_tokens = []; } } > $template_type_map * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation * * @return Type\Union */ public static function reconcile(string $assertion, \Psalm\Type\Union $existing_var_type, ?string $key = null, bool $negated = \false, ?\Psalm\CodeLocation $code_location = null, array $suppressed_issues = [], int &$failed_reconciliation = 0, bool $is_equality = \false, bool $is_strict_equality = \false) : ?\Psalm\Type\Union { if ($assertion === 'object' && !$existing_var_type->hasMixed()) { return self::reconcileObject($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'scalar' && !$existing_var_type->hasMixed()) { return self::reconcileScalar($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'resource' && !$existing_var_type->hasMixed()) { return self::reconcileResource($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'bool' && !$existing_var_type->hasMixed()) { return self::reconcileBool($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'numeric' && !$existing_var_type->hasMixed()) { return self::reconcileNumeric($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'float' && !$existing_var_type->hasMixed()) { return self::reconcileFloat($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'int' && !$existing_var_type->hasMixed()) { return self::reconcileInt($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'string' && !$existing_var_type->hasMixed()) { return self::reconcileString($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'array' && !$existing_var_type->hasMixed()) { return self::reconcileArray($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'falsy' || $assertion === 'empty') { return self::reconcileFalsyOrEmpty($assertion, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, $is_strict_equality); } if ($assertion === 'null' && !$existing_var_type->hasMixed()) { return self::reconcileNull($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'false' && !$existing_var_type->hasMixed()) { return self::reconcileFalse($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'non-empty-countable') { return self::reconcileNonEmptyCountable($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, null); } if ($assertion === 'callable') { return self::reconcileCallable($existing_var_type); } if (\substr($assertion, 0, 13) === 'has-at-least-') { return self::reconcileNonEmptyCountable($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, (int) \substr($assertion, 13)); } if (\substr($assertion, 0, 12) === 'has-exactly-') { return $existing_var_type; } return null; } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileCallable(\Psalm\Type\Union $existing_var_type) : \Psalm\Type\Union { foreach ($existing_var_type->getAtomicTypes() as $atomic_key => $type) { if ($type instanceof \Psalm\Type\Atomic\TLiteralString && \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($type->value)) { $existing_var_type->removeType($atomic_key); } if ($type->isCallableType()) { $existing_var_type->removeType($atomic_key); } } return $existing_var_type; } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileBool(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $non_bool_types = []; $did_remove_type = \false; foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$type->as->hasBool()) { $non_bool_types[] = $type; } $did_remove_type = \true; } elseif (!$type instanceof \Psalm\Type\Atomic\TBool || $is_equality && \get_class($type) === \Psalm\Type\Atomic\TBool::class) { if ($type instanceof \Psalm\Type\Atomic\TScalar) { $did_remove_type = \true; $non_bool_types[] = new \Psalm\Type\Atomic\TString(); $non_bool_types[] = new \Psalm\Type\Atomic\TInt(); $non_bool_types[] = new \Psalm\Type\Atomic\TFloat(); } else { $non_bool_types[] = $type; } } else { $did_remove_type = \true; } } if (!$did_remove_type || !$non_bool_types) { if ($key && $code_location && !$is_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!bool', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($non_bool_types) { return new \Psalm\Type\Union($non_bool_types); } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileNonEmptyCountable(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality, ?int $min_count) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if (isset($existing_var_atomic_types['array'])) { $array_atomic_type = $existing_var_atomic_types['array']; $did_remove_type = \false; if (($array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyList) && ($min_count === null || $array_atomic_type->count >= $min_count)) { $did_remove_type = \true; $existing_var_type->removeType('array'); } elseif ($array_atomic_type->getId() !== 'array') { $did_remove_type = \true; if (!$min_count) { $existing_var_type->addType(new \Psalm\Type\Atomic\TArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()])])); } } elseif ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $did_remove_type = \true; foreach ($array_atomic_type->properties as $property_type) { if (!$property_type->possibly_undefined) { $did_remove_type = \false; break; } } } if (!$is_equality && !$existing_var_type->hasMixed() && (!$did_remove_type || empty($existing_var_type->getAtomicTypes()))) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!non-empty-countable', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } } return $existing_var_type; } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileNull(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $did_remove_type = \false; if ($existing_var_type->hasType('null')) { $did_remove_type = \true; $existing_var_type->removeType('null'); } foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { $type->as = self::reconcileNull($type->as, null, \false, null, $suppressed_issues, $failed_reconciliation, $is_equality); $did_remove_type = \true; $existing_var_type->bustCache(); } } if (!$did_remove_type || empty($existing_var_type->getAtomicTypes())) { if ($key && $code_location && !$is_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!null', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($existing_var_type->getAtomicTypes()) { return $existing_var_type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileFalse(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $did_remove_type = $existing_var_type->hasScalar(); if ($existing_var_type->hasType('false')) { $did_remove_type = \true; $existing_var_type->removeType('false'); } foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { $type->as = self::reconcileFalse($type->as, null, \false, null, $suppressed_issues, $failed_reconciliation, $is_equality); $did_remove_type = \true; $existing_var_type->bustCache(); } } if (!$did_remove_type || empty($existing_var_type->getAtomicTypes())) { if ($key && $code_location && !$is_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!false', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($existing_var_type->getAtomicTypes()) { return $existing_var_type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileFalsyOrEmpty(string $assertion, \Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality, bool $is_strict_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $did_remove_type = $existing_var_type->hasDefinitelyNumericType(\false) || $existing_var_type->isEmpty() || $existing_var_type->hasType('bool') || $existing_var_type->possibly_undefined || $existing_var_type->possibly_undefined_from_try || $existing_var_type->hasType('iterable'); if ($is_strict_equality && $assertion === 'empty') { $existing_var_type->removeType('null'); $existing_var_type->removeType('false'); if ($existing_var_type->hasType('array') && $existing_var_type->getAtomicTypes()['array']->getId() === 'array') { $existing_var_type->removeType('array'); } if ($existing_var_type->hasMixed()) { $existing_var_type->removeType('mixed'); if (!$existing_var_atomic_types['mixed'] instanceof \Psalm\Type\Atomic\TEmptyMixed) { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyMixed()); } } if ($existing_var_type->hasScalar()) { $existing_var_type->removeType('scalar'); if (!$existing_var_atomic_types['scalar'] instanceof \Psalm\Type\Atomic\TEmptyScalar) { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyScalar()); } } if (isset($existing_var_atomic_types['string'])) { $existing_var_type->removeType('string'); if ($existing_var_atomic_types['string'] instanceof \Psalm\Type\Atomic\TLowercaseString) { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyLowercaseString()); } else { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyString()); } } self::removeFalsyNegatedLiteralTypes($existing_var_type, $did_remove_type); $existing_var_type->possibly_undefined = \false; $existing_var_type->possibly_undefined_from_try = \false; if ($existing_var_type->getAtomicTypes()) { return $existing_var_type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } if ($existing_var_type->hasMixed()) { if ($existing_var_type->isMixed() && $existing_var_atomic_types['mixed'] instanceof \Psalm\Type\Atomic\TEmptyMixed) { if ($code_location && $key && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParadoxicalCondition('Found a paradox when evaluating ' . $key . ' of type ' . $existing_var_type->getId() . ' and trying to reconcile it with a non-' . $assertion . ' assertion', $code_location), $suppressed_issues)) { // fall through } return \Psalm\Type::getMixed(); } if (!$existing_var_atomic_types['mixed'] instanceof \Psalm\Type\Atomic\TNonEmptyMixed) { $did_remove_type = \true; $existing_var_type->removeType('mixed'); if (!$existing_var_atomic_types['mixed'] instanceof \Psalm\Type\Atomic\TEmptyMixed) { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyMixed()); } } elseif ($existing_var_type->isMixed() && !$is_equality) { if ($code_location && $key && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition('Found a redundant condition when evaluating ' . $key . ' of type ' . $existing_var_type->getId() . ' and trying to reconcile it with a non-' . $assertion . ' assertion', $code_location, $existing_var_type->getId() . ' ' . $assertion), $suppressed_issues)) { // fall through } } if ($existing_var_type->isMixed()) { return $existing_var_type; } } if ($existing_var_type->hasScalar()) { if (!$existing_var_atomic_types['scalar'] instanceof \Psalm\Type\Atomic\TNonEmptyScalar) { $did_remove_type = \true; $existing_var_type->removeType('scalar'); if (!$existing_var_atomic_types['scalar'] instanceof \Psalm\Type\Atomic\TEmptyScalar) { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyScalar()); } } elseif ($existing_var_type->isSingle() && !$is_equality) { if ($code_location && $key && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition('Found a redundant condition when evaluating ' . $key . ' of type ' . $existing_var_type->getId() . ' and trying to reconcile it with a non-' . $assertion . ' assertion', $code_location, $existing_var_type->getId() . ' ' . $assertion), $suppressed_issues)) { // fall through } } if ($existing_var_type->isSingle()) { return $existing_var_type; } } if (isset($existing_var_atomic_types['string'])) { if (!$existing_var_atomic_types['string'] instanceof \Psalm\Type\Atomic\TNonEmptyString && !$existing_var_atomic_types['string'] instanceof \Psalm\Type\Atomic\TClassString && !$existing_var_atomic_types['string'] instanceof \Psalm\Type\Atomic\TDependentGetClass) { $did_remove_type = \true; $existing_var_type->removeType('string'); if ($existing_var_atomic_types['string'] instanceof \Psalm\Type\Atomic\TLowercaseString) { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyLowercaseString()); } else { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyString()); } } elseif ($existing_var_type->isSingle() && !$is_equality) { if ($code_location && $key && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition('Found a redundant condition when evaluating ' . $key . ' of type ' . $existing_var_type->getId() . ' and trying to reconcile it with a non-' . $assertion . ' assertion', $code_location, $existing_var_type->getId() . ' ' . $assertion), $suppressed_issues)) { // fall through } } if ($existing_var_type->isSingle()) { return $existing_var_type; } } if ($existing_var_type->hasType('null')) { $did_remove_type = \true; $existing_var_type->removeType('null'); } if ($existing_var_type->hasType('false')) { $did_remove_type = \true; $existing_var_type->removeType('false'); } if ($existing_var_type->hasType('bool')) { $did_remove_type = \true; $existing_var_type->removeType('bool'); $existing_var_type->addType(new \Psalm\Type\Atomic\TTrue()); } foreach ($existing_var_atomic_types as $existing_var_atomic_type) { if ($existing_var_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$is_equality && !$existing_var_atomic_type->as->isMixed()) { $template_did_fail = 0; $existing_var_atomic_type = clone $existing_var_atomic_type; $existing_var_atomic_type->as = self::reconcileFalsyOrEmpty($assertion, $existing_var_atomic_type->as, $key, $negated, $code_location, $suppressed_issues, $template_did_fail, $is_equality, $is_strict_equality); $did_remove_type = \true; if (!$template_did_fail) { $existing_var_type->addType($existing_var_atomic_type); } } } } self::removeFalsyNegatedLiteralTypes($existing_var_type, $did_remove_type); $existing_var_type->possibly_undefined = \false; $existing_var_type->possibly_undefined_from_try = \false; if ((!$did_remove_type || empty($existing_var_type->getAtomicTypes())) && !$existing_var_type->hasTemplate()) { if ($key && $code_location && !$is_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!' . $assertion, !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($existing_var_type->getAtomicTypes()) { return $existing_var_type; } $failed_reconciliation = 2; return \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileScalar(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $non_scalar_types = []; $did_remove_type = \false; foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$is_equality && !$type->as->isMixed()) { $template_did_fail = 0; $type = clone $type; $type->as = self::reconcileScalar($type->as, null, \false, null, $suppressed_issues, $template_did_fail, $is_equality); $did_remove_type = \true; if (!$template_did_fail) { $non_scalar_types[] = $type; } } else { $did_remove_type = \true; $non_scalar_types[] = $type; } } elseif (!$type instanceof \Psalm\Type\Atomic\Scalar) { $non_scalar_types[] = $type; } else { $did_remove_type = \true; if ($is_equality) { $non_scalar_types[] = $type; } } } if (!$did_remove_type || !$non_scalar_types) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!scalar', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($non_scalar_types) { $type = new \Psalm\Type\Union($non_scalar_types); $type->ignore_falsable_issues = $existing_var_type->ignore_falsable_issues; $type->ignore_nullable_issues = $existing_var_type->ignore_nullable_issues; $type->from_docblock = $existing_var_type->from_docblock; return $type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileObject(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $non_object_types = []; $did_remove_type = \false; foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$is_equality && !$type->as->isMixed()) { $template_did_fail = 0; $type = clone $type; $type->as = self::reconcileObject($type->as, null, \false, null, $suppressed_issues, $template_did_fail, $is_equality); $did_remove_type = \true; if (!$template_did_fail) { $non_object_types[] = $type; } } else { $did_remove_type = \true; $non_object_types[] = $type; } } elseif ($type instanceof \Psalm\Type\Atomic\TCallable) { $non_object_types[] = new \Psalm\Type\Atomic\TCallableArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getMixed()]); $non_object_types[] = new \Psalm\Type\Atomic\TCallableString(); $did_remove_type = \true; } elseif (!$type->isObjectType()) { $non_object_types[] = $type; } else { $did_remove_type = \true; if ($is_equality) { $non_object_types[] = $type; } } } if (!$non_object_types || !$did_remove_type) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!object', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($non_object_types) { $type = new \Psalm\Type\Union($non_object_types); $type->ignore_falsable_issues = $existing_var_type->ignore_falsable_issues; $type->ignore_nullable_issues = $existing_var_type->ignore_nullable_issues; $type->from_docblock = $existing_var_type->from_docblock; return $type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileNumeric(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $non_numeric_types = []; $did_remove_type = $existing_var_type->hasString() || $existing_var_type->hasScalar(); foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$is_equality && !$type->as->isMixed()) { $template_did_fail = 0; $type = clone $type; $type->as = self::reconcileNumeric($type->as, null, \false, null, $suppressed_issues, $template_did_fail, $is_equality); $did_remove_type = \true; if (!$template_did_fail) { $non_numeric_types[] = $type; } } else { $did_remove_type = \true; $non_numeric_types[] = $type; } } elseif ($type instanceof \Psalm\Type\Atomic\TArrayKey) { $did_remove_type = \true; $non_numeric_types[] = new \Psalm\Type\Atomic\TString(); } elseif (!$type->isNumericType()) { $non_numeric_types[] = $type; } else { $did_remove_type = \true; if ($is_equality) { $non_numeric_types[] = $type; } } } if (!$non_numeric_types || !$did_remove_type) { if ($key && $code_location && !$is_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!numeric', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($non_numeric_types) { $type = new \Psalm\Type\Union($non_numeric_types); $type->ignore_falsable_issues = $existing_var_type->ignore_falsable_issues; $type->ignore_nullable_issues = $existing_var_type->ignore_nullable_issues; $type->from_docblock = $existing_var_type->from_docblock; return $type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileInt(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $non_int_types = []; $did_remove_type = \false; foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$is_equality && !$type->as->isMixed()) { $template_did_fail = 0; $type = clone $type; $type->as = self::reconcileInt($type->as, null, \false, null, $suppressed_issues, $template_did_fail, $is_equality); $did_remove_type = \true; if (!$template_did_fail) { $non_int_types[] = $type; } } else { $did_remove_type = \true; $non_int_types[] = $type; } } elseif ($type instanceof \Psalm\Type\Atomic\TArrayKey) { $did_remove_type = \true; $non_int_types[] = new \Psalm\Type\Atomic\TString(); } elseif ($type instanceof \Psalm\Type\Atomic\TScalar) { $did_remove_type = \true; $non_int_types[] = new \Psalm\Type\Atomic\TString(); $non_int_types[] = new \Psalm\Type\Atomic\TFloat(); $non_int_types[] = new \Psalm\Type\Atomic\TBool(); } elseif ($type instanceof \Psalm\Type\Atomic\TInt) { $did_remove_type = \true; if ($is_equality) { $non_int_types[] = $type; } elseif ($existing_var_type->from_calculation) { $non_int_types[] = new \Psalm\Type\Atomic\TFloat(); } } else { $non_int_types[] = $type; } } if (!$non_int_types || !$did_remove_type) { if ($key && $code_location && !$is_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!int', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($non_int_types) { $type = new \Psalm\Type\Union($non_int_types); $type->ignore_falsable_issues = $existing_var_type->ignore_falsable_issues; $type->ignore_nullable_issues = $existing_var_type->ignore_nullable_issues; $type->from_docblock = $existing_var_type->from_docblock; return $type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileFloat(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $non_float_types = []; $did_remove_type = \false; foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$is_equality && !$type->as->isMixed()) { $template_did_fail = 0; $type = clone $type; $type->as = self::reconcileFloat($type->as, null, \false, null, $suppressed_issues, $template_did_fail, $is_equality); $did_remove_type = \true; if (!$template_did_fail) { $non_float_types[] = $type; } } else { $did_remove_type = \true; $non_float_types[] = $type; } } elseif ($type instanceof \Psalm\Type\Atomic\TScalar) { $did_remove_type = \true; $non_float_types[] = new \Psalm\Type\Atomic\TString(); $non_float_types[] = new \Psalm\Type\Atomic\TInt(); $non_float_types[] = new \Psalm\Type\Atomic\TBool(); } elseif ($type instanceof \Psalm\Type\Atomic\TFloat) { $did_remove_type = \true; if ($is_equality) { $non_float_types[] = $type; } } else { $non_float_types[] = $type; } } if (!$non_float_types || !$did_remove_type) { if ($key && $code_location && !$is_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!float', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($non_float_types) { $type = new \Psalm\Type\Union($non_float_types); $type->ignore_falsable_issues = $existing_var_type->ignore_falsable_issues; $type->ignore_nullable_issues = $existing_var_type->ignore_nullable_issues; $type->from_docblock = $existing_var_type->from_docblock; return $type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileString(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $non_string_types = []; $did_remove_type = $existing_var_type->hasScalar(); foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$is_equality && !$type->as->isMixed()) { $template_did_fail = 0; $type = clone $type; $type->as = self::reconcileString($type->as, null, \false, null, $suppressed_issues, $template_did_fail, $is_equality); $did_remove_type = \true; if (!$template_did_fail) { $non_string_types[] = $type; } } else { $did_remove_type = \true; $non_string_types[] = $type; } } elseif ($type instanceof \Psalm\Type\Atomic\TArrayKey) { $non_string_types[] = new \Psalm\Type\Atomic\TInt(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TCallable) { $non_string_types[] = new \Psalm\Type\Atomic\TCallableArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getMixed()]); $non_string_types[] = new \Psalm\Type\Atomic\TCallableObject(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TNumeric) { $non_string_types[] = $type; $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TScalar) { $did_remove_type = \true; $non_string_types[] = new \Psalm\Type\Atomic\TFloat(); $non_string_types[] = new \Psalm\Type\Atomic\TInt(); $non_string_types[] = new \Psalm\Type\Atomic\TBool(); } elseif (!$type instanceof \Psalm\Type\Atomic\TString) { $non_string_types[] = $type; } else { $did_remove_type = \true; if ($is_equality) { $non_string_types[] = $type; } } } if (!$non_string_types || !$did_remove_type) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!string', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($non_string_types) { $type = new \Psalm\Type\Union($non_string_types); $type->ignore_falsable_issues = $existing_var_type->ignore_falsable_issues; $type->ignore_nullable_issues = $existing_var_type->ignore_nullable_issues; $type->from_docblock = $existing_var_type->from_docblock; return $type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileArray(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $non_array_types = []; $did_remove_type = $existing_var_type->hasScalar(); foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$is_equality && !$type->as->isMixed()) { $template_did_fail = 0; $type = clone $type; $type->as = self::reconcileArray($type->as, null, \false, null, $suppressed_issues, $template_did_fail, $is_equality); $did_remove_type = \true; if (!$template_did_fail) { $non_array_types[] = $type; } } else { $did_remove_type = \true; $non_array_types[] = $type; } } elseif ($type instanceof \Psalm\Type\Atomic\TCallable) { $non_array_types[] = new \Psalm\Type\Atomic\TCallableString(); $non_array_types[] = new \Psalm\Type\Atomic\TCallableObject(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TIterable) { if (!$type->type_params[0]->isMixed() || !$type->type_params[1]->isMixed()) { $non_array_types[] = new \Psalm\Type\Atomic\TGenericObject('Traversable', $type->type_params); } else { $non_array_types[] = new \Psalm\Type\Atomic\TNamedObject('Traversable'); } $did_remove_type = \true; } elseif (!$type instanceof \Psalm\Type\Atomic\TArray && !$type instanceof \Psalm\Type\Atomic\TKeyedArray && !$type instanceof \Psalm\Type\Atomic\TList) { $non_array_types[] = $type; } else { $did_remove_type = \true; if ($is_equality) { $non_array_types[] = $type; } } } if (!$non_array_types || !$did_remove_type) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!array', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($non_array_types) { $type = new \Psalm\Type\Union($non_array_types); $type->ignore_falsable_issues = $existing_var_type->ignore_falsable_issues; $type->ignore_nullable_issues = $existing_var_type->ignore_nullable_issues; $type->from_docblock = $existing_var_type->from_docblock; return $type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileResource(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $did_remove_type = \false; if ($existing_var_type->hasType('resource')) { $did_remove_type = \true; $existing_var_type->removeType('resource'); } foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { $type->as = self::reconcileResource($type->as, null, \false, null, $suppressed_issues, $failed_reconciliation, $is_equality); $did_remove_type = \true; $existing_var_type->bustCache(); } } if (!$did_remove_type || empty($existing_var_type->getAtomicTypes())) { if ($key && $code_location && !$is_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!resource', !$did_remove_type, $negated, $code_location, $suppressed_issues); } if (!$did_remove_type) { $failed_reconciliation = 1; } } if ($existing_var_type->getAtomicTypes()) { return $existing_var_type; } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } private static function removeFalsyNegatedLiteralTypes(\Psalm\Type\Union $existing_var_type, bool &$did_remove_type) : void { if ($existing_var_type->hasString()) { $existing_string_types = $existing_var_type->getLiteralStrings(); if ($existing_string_types) { foreach ($existing_string_types as $string_key => $literal_type) { if (!$literal_type->value) { $existing_var_type->removeType($string_key); $did_remove_type = \true; } } } else { $did_remove_type = \true; } } if ($existing_var_type->hasInt()) { $existing_int_types = $existing_var_type->getLiteralInts(); if ($existing_int_types) { foreach ($existing_int_types as $int_key => $literal_type) { if (!$literal_type->value) { $existing_var_type->removeType($int_key); $did_remove_type = \true; } } } else { $did_remove_type = \true; } } if ($existing_var_type->hasType('array')) { $array_atomic_type = $existing_var_type->getAtomicTypes()['array']; if ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray && !$array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $did_remove_type = \true; if ($array_atomic_type->getId() === 'array') { $existing_var_type->removeType('array'); } else { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyArray($array_atomic_type->type_params)); } } elseif ($array_atomic_type instanceof \Psalm\Type\Atomic\TList && !$array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyList) { $did_remove_type = \true; $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyList($array_atomic_type->type_param)); } elseif ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray && !$array_atomic_type->sealed) { $did_remove_type = \true; } } } } hasMixed()) { return $existing_var_type; } if ($assertion === 'isset') { $existing_var_type->removeType('null'); if (empty($existing_var_type->getAtomicTypes())) { $failed_reconciliation = 2; if ($code_location) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType('Cannot resolve types for ' . $key . ' on null var', $code_location, null), $suppressed_issues)) { // fall through } } return \Psalm\Type::getEmpty(); } if ($existing_var_type->hasType('empty')) { $existing_var_type->removeType('empty'); $existing_var_type->addType(new \Psalm\Type\Atomic\TMixed($inside_loop)); } $existing_var_type->possibly_undefined = \false; $existing_var_type->possibly_undefined_from_try = \false; return $existing_var_type; } if ($assertion === 'array-key-exists') { $existing_var_type->possibly_undefined = \false; return $existing_var_type; } if (\substr($assertion, 0, 9) === 'in-array-') { return self::reconcileInArray($codebase, $existing_var_type, \substr($assertion, 9)); } if (\substr($assertion, 0, 14) === 'has-array-key-') { return self::reconcileHasArrayKey($existing_var_type, \substr($assertion, 14)); } if ($assertion === 'falsy' || $assertion === 'empty') { return self::reconcileFalsyOrEmpty($assertion, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation); } if ($assertion === 'object') { return self::reconcileObject($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'resource') { return self::reconcileResource($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'callable') { return self::reconcileCallable($codebase, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'iterable') { return self::reconcileIterable($codebase, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'array') { return self::reconcileArray($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'list') { return self::reconcileList($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, \false); } if ($assertion === 'non-empty-list') { return self::reconcileList($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, \true); } if ($assertion === 'Traversable') { return self::reconcileTraversable($codebase, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'countable') { return self::reconcileCountable($codebase, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'string-array-access') { return self::reconcileStringArrayAccess($codebase, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $inside_loop); } if ($assertion === 'int-or-string-array-access') { return self::reconcileIntArrayAccess($codebase, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $inside_loop); } if ($assertion === 'numeric') { return self::reconcileNumeric($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'scalar') { return self::reconcileScalar($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'bool') { return self::reconcileBool($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'string') { return self::reconcileString($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, $is_strict_equality); } if ($assertion === 'int') { return self::reconcileInt($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, $is_strict_equality); } if ($assertion === 'positive-numeric') { return self::reconcilePositiveNumeric($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality); } if ($assertion === 'float' && $existing_var_type->from_calculation && $existing_var_type->hasInt()) { return \Psalm\Type::getFloat(); } if ($assertion === 'non-empty-countable') { return self::reconcileNonEmptyCountable($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, null); } if (\substr($assertion, 0, 13) === 'has-at-least-') { return self::reconcileNonEmptyCountable($existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, (int) \substr($assertion, 13)); } if (\substr($assertion, 0, 12) === 'has-exactly-') { /** @psalm-suppress ArgumentTypeCoercion */ return self::reconcileExactlyCountable($existing_var_type, (int) \substr($assertion, 12)); } if (\substr($assertion, 0, 10) === 'hasmethod-') { return self::reconcileHasMethod($codebase, \substr($assertion, 10), $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation); } if ($existing_var_type->isSingle() && $existing_var_type->hasTemplate() && \strpos($assertion, '-') === \false && \strpos($assertion, '(') === \false) { foreach ($existing_var_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($atomic_type->as->hasMixed() || $atomic_type->as->hasObject()) { $atomic_type->as = \Psalm\Type::parseString($assertion); return $existing_var_type; } } } } return null; } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileNonEmptyCountable(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality, ?int $min_count) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); if ($existing_var_type->hasType('array')) { $array_atomic_type = $existing_var_type->getAtomicTypes()['array']; $did_remove_type = \false; if ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray) { if (!$array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyArray || $array_atomic_type->count < $min_count) { if ($array_atomic_type->getId() === 'array') { $existing_var_type->removeType('array'); } else { $non_empty_array = new \Psalm\Type\Atomic\TNonEmptyArray($array_atomic_type->type_params); if ($min_count) { $non_empty_array->count = $min_count; } $existing_var_type->addType($non_empty_array); } $did_remove_type = \true; } } elseif ($array_atomic_type instanceof \Psalm\Type\Atomic\TList) { if (!$array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyList || $array_atomic_type->count < $min_count) { $non_empty_list = new \Psalm\Type\Atomic\TNonEmptyList($array_atomic_type->type_param); if ($min_count) { $non_empty_list->count = $min_count; } $did_remove_type = \true; $existing_var_type->addType($non_empty_list); } } elseif ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { foreach ($array_atomic_type->properties as $property_type) { if ($property_type->possibly_undefined) { $did_remove_type = \true; break; } } } if (!$is_equality && !$existing_var_type->hasMixed() && (!$did_remove_type || empty($existing_var_type->getAtomicTypes()))) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'non-empty-countable', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } } return $existing_var_type; } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation * @param positive-int $count */ private static function reconcileExactlyCountable(\Psalm\Type\Union $existing_var_type, int $count) : \Psalm\Type\Union { if ($existing_var_type->hasType('array')) { $array_atomic_type = $existing_var_type->getAtomicTypes()['array']; if ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray) { $non_empty_array = new \Psalm\Type\Atomic\TNonEmptyArray($array_atomic_type->type_params); $non_empty_array->count = $count; $existing_var_type->addType($non_empty_array); } elseif ($array_atomic_type instanceof \Psalm\Type\Atomic\TList) { $non_empty_list = new \Psalm\Type\Atomic\TNonEmptyList($array_atomic_type->type_param); $non_empty_list->count = $count; $existing_var_type->addType($non_empty_list); } } return $existing_var_type; } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcilePositiveNumeric(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $did_remove_type = \false; $positive_types = []; foreach ($existing_var_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TLiteralInt) { if ($atomic_type->value < 1) { $did_remove_type = \true; } else { $positive_types[] = $atomic_type; } } elseif ($atomic_type instanceof \Psalm\Type\Atomic\TPositiveInt) { $positive_types[] = $atomic_type; } elseif (\get_class($atomic_type) === \Psalm\Type\Atomic\TInt::class) { $positive_types[] = new \Psalm\Type\Atomic\TPositiveInt(); $did_remove_type = \true; } else { // for now allow this check everywhere else if (!$atomic_type instanceof \Psalm\Type\Atomic\TNull && !$atomic_type instanceof \Psalm\Type\Atomic\TFalse) { $positive_types[] = $atomic_type; } $did_remove_type = \true; } } if (!$is_equality && !$existing_var_type->hasMixed() && (!$did_remove_type || !$positive_types)) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'positive-numeric', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($positive_types) { return new \Psalm\Type\Union($positive_types); } $failed_reconciliation = 2; return \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileHasMethod(\Psalm\Codebase $codebase, string $method_name, \Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $object_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classOrInterfaceExists($type->value)) { $object_types[] = $type; if (!$codebase->methodExists($type->value . '::' . $method_name)) { $match_found = \false; if ($type->extra_types) { foreach ($type->extra_types as $extra_type) { if ($extra_type instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classOrInterfaceExists($extra_type->value) && $codebase->methodExists($extra_type->value . '::' . $method_name)) { $match_found = \true; } elseif ($extra_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { $match_found = \true; if (!isset($extra_type->methods[$method_name])) { $extra_type->methods[$method_name] = 'object::' . $method_name; $did_remove_type = \true; } } } } if (!$match_found) { $obj = new \Psalm\Type\Atomic\TObjectWithProperties([], [$method_name => $type->value . '::' . $method_name]); $type->extra_types[$obj->getKey()] = $obj; $did_remove_type = \true; } } } elseif ($type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { $object_types[] = $type; if (!isset($type->methods[$method_name])) { $type->methods[$method_name] = 'object::' . $method_name; $did_remove_type = \true; } } elseif ($type instanceof \Psalm\Type\Atomic\TObject || $type instanceof \Psalm\Type\Atomic\TMixed) { $object_types[] = new \Psalm\Type\Atomic\TObjectWithProperties([], [$method_name => 'object::' . $method_name]); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TString) { // we don’t know $object_types[] = $type; $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { $object_types[] = $type; $did_remove_type = \true; } else { $did_remove_type = \true; } } if (!$object_types || !$did_remove_type) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'object with method ' . $method_name, !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($object_types) { return new \Psalm\Type\Union($object_types); } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileString(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality, bool $is_strict_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($existing_var_type->hasMixed()) { if ($is_equality && !$is_strict_equality) { return $existing_var_type; } return \Psalm\Type::getString(); } $string_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type instanceof \Psalm\Type\Atomic\TString) { $string_types[] = $type; if (\get_class($type) === \Psalm\Type\Atomic\TString::class) { $type->from_docblock = \false; } } elseif ($type instanceof \Psalm\Type\Atomic\TCallable) { $string_types[] = new \Psalm\Type\Atomic\TCallableString(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TNumeric) { $string_types[] = new \Psalm\Type\Atomic\TNumericString(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TScalar || $type instanceof \Psalm\Type\Atomic\TArrayKey) { $string_types[] = new \Psalm\Type\Atomic\TString(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($type->as->hasString() || $type->as->hasMixed()) { $type = clone $type; $type->as = self::reconcileString($type->as, null, \false, null, $suppressed_issues, $failed_reconciliation, $is_equality, $is_strict_equality); $string_types[] = $type; } $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$did_remove_type || !$string_types) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'string', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($string_types) { return new \Psalm\Type\Union($string_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileInt(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality, bool $is_strict_equality) : \Psalm\Type\Union { if ($existing_var_type->hasMixed()) { if ($is_equality && !$is_strict_equality) { return $existing_var_type; } return \Psalm\Type::getInt(); } $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $int_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type instanceof \Psalm\Type\Atomic\TInt) { $int_types[] = $type; if (\get_class($type) === \Psalm\Type\Atomic\TInt::class) { $type->from_docblock = \false; } if ($existing_var_type->from_calculation) { $did_remove_type = \true; } } elseif ($type instanceof \Psalm\Type\Atomic\TNumeric) { $int_types[] = new \Psalm\Type\Atomic\TInt(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TScalar || $type instanceof \Psalm\Type\Atomic\TArrayKey) { $int_types[] = new \Psalm\Type\Atomic\TInt(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($type->as->hasInt() || $type->as->hasMixed()) { $type = clone $type; $type->as = self::reconcileInt($type->as, null, \false, null, $suppressed_issues, $failed_reconciliation, $is_equality, $is_strict_equality); $int_types[] = $type; } $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$did_remove_type || !$int_types) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'int', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($int_types) { return new \Psalm\Type\Union($int_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileBool(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { if ($existing_var_type->hasMixed()) { return \Psalm\Type::getBool(); } $bool_types = []; $did_remove_type = \false; $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); foreach ($existing_var_atomic_types as $type) { if ($type instanceof \Psalm\Type\Atomic\TBool) { $bool_types[] = $type; $type->from_docblock = \false; } elseif ($type instanceof \Psalm\Type\Atomic\TScalar) { $bool_types[] = new \Psalm\Type\Atomic\TBool(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($type->as->hasBool() || $type->as->hasMixed()) { $type = clone $type; $type->as = self::reconcileBool($type->as, null, \false, null, $suppressed_issues, $failed_reconciliation, $is_equality); $bool_types[] = $type; } $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$did_remove_type || !$bool_types) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'bool', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($bool_types) { return new \Psalm\Type\Union($bool_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileScalar(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { if ($existing_var_type->hasMixed()) { return \Psalm\Type::getScalar(); } $scalar_types = []; $did_remove_type = \false; $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); foreach ($existing_var_atomic_types as $type) { if ($type instanceof \Psalm\Type\Atomic\Scalar) { $scalar_types[] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($type->as->hasScalar() || $type->as->hasMixed()) { $type = clone $type; $type->as = self::reconcileScalar($type->as, null, \false, null, $suppressed_issues, $failed_reconciliation, $is_equality); $scalar_types[] = $type; } $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$did_remove_type || !$scalar_types) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'scalar', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($scalar_types) { return new \Psalm\Type\Union($scalar_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileNumeric(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { if ($existing_var_type->hasMixed()) { return \Psalm\Type::getNumeric(); } $old_var_type_string = $existing_var_type->getId(); $numeric_types = []; $did_remove_type = \false; if ($existing_var_type->hasString()) { $did_remove_type = \true; $existing_var_type->removeType('string'); $existing_var_type->addType(new \Psalm\Type\Atomic\TNumericString()); } foreach ($existing_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TNumeric || $type instanceof \Psalm\Type\Atomic\TNumericString) { // this is a workaround for a possible issue running // is_numeric($a) && is_string($a) $did_remove_type = \true; $numeric_types[] = $type; } elseif ($type->isNumericType()) { $numeric_types[] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TScalar) { $did_remove_type = \true; $numeric_types[] = new \Psalm\Type\Atomic\TNumeric(); } elseif ($type instanceof \Psalm\Type\Atomic\TArrayKey) { $did_remove_type = \true; $numeric_types[] = new \Psalm\Type\Atomic\TInt(); $numeric_types[] = new \Psalm\Type\Atomic\TNumericString(); } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($type->as->hasNumeric() || $type->as->hasMixed()) { $type = clone $type; $type->as = self::reconcileNumeric($type->as, null, \false, null, $suppressed_issues, $failed_reconciliation, $is_equality); $numeric_types[] = $type; } $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$did_remove_type || !$numeric_types) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'numeric', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($numeric_types) { return new \Psalm\Type\Union($numeric_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileObject(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { if ($existing_var_type->hasMixed()) { return \Psalm\Type::getObject(); } $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $object_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type->isObjectType()) { $object_types[] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TCallable) { $object_types[] = new \Psalm\Type\Atomic\TCallableObject(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam && $type->as->isMixed()) { $type = clone $type; $type->as = \Psalm\Type::getObject(); $object_types[] = $type; $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($type->as->hasObject() || $type->as->hasMixed()) { $type = clone $type; $type->as = self::reconcileObject($type->as, null, \false, null, $suppressed_issues, $failed_reconciliation, $is_equality); $object_types[] = $type; } $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$object_types || !$did_remove_type) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'object', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($object_types) { return new \Psalm\Type\Union($object_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileResource(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { if ($existing_var_type->hasMixed()) { return \Psalm\Type::getResource(); } $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $resource_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type instanceof \Psalm\Type\Atomic\TResource) { $resource_types[] = $type; } else { $did_remove_type = \true; } } if ((!$resource_types || !$did_remove_type) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'resource', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($resource_types) { return new \Psalm\Type\Union($resource_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileCountable(\Psalm\Codebase $codebase, \Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($existing_var_type->hasMixed() || $existing_var_type->hasTemplate()) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getMixed()]), new \Psalm\Type\Atomic\TNamedObject('Countable')]); } $iterable_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type->isCountable($codebase)) { $iterable_types[] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TObject) { $iterable_types[] = new \Psalm\Type\Atomic\TNamedObject('Countable'); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TNamedObject || $type instanceof \Psalm\Type\Atomic\TIterable) { $countable = new \Psalm\Type\Atomic\TNamedObject('Countable'); $type->extra_types[$countable->getKey()] = $countable; $iterable_types[] = $type; $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$iterable_types || !$did_remove_type) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'countable', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($iterable_types) { return new \Psalm\Type\Union($iterable_types); } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileIterable(\Psalm\Codebase $codebase, \Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($existing_var_type->hasMixed() || $existing_var_type->hasTemplate()) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TIterable()]); } $iterable_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type->isIterable($codebase)) { $iterable_types[] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TObject) { $iterable_types[] = new \Psalm\Type\Atomic\TNamedObject('Traversable'); $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$iterable_types || !$did_remove_type) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'iterable', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($iterable_types) { return new \Psalm\Type\Union($iterable_types); } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileInArray(\Psalm\Codebase $codebase, \Psalm\Type\Union $existing_var_type, string $assertion) : \Psalm\Type\Union { if (\strpos($assertion, '::')) { [$fq_classlike_name, $const_name] = \explode('::', $assertion); $class_constant_type = $codebase->classlikes->getClassConstantType($fq_classlike_name, $const_name, \ReflectionProperty::IS_PRIVATE); if ($class_constant_type) { foreach ($class_constant_type->getAtomicTypes() as $const_type_atomic) { if ($const_type_atomic instanceof \Psalm\Type\Atomic\TKeyedArray || $const_type_atomic instanceof \Psalm\Type\Atomic\TArray) { if ($const_type_atomic instanceof \Psalm\Type\Atomic\TKeyedArray) { $const_type_atomic = $const_type_atomic->getGenericArrayType(); } if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $const_type_atomic->type_params[0], $existing_var_type)) { return clone $const_type_atomic->type_params[0]; } } } } } $existing_var_type->removeType('null'); return $existing_var_type; } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileHasArrayKey(\Psalm\Type\Union $existing_var_type, string $assertion) : \Psalm\Type\Union { foreach ($existing_var_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $is_class_string = \false; if (\strpos($assertion, '::class')) { [$assertion] = \explode('::', $assertion); $is_class_string = \true; } if (isset($atomic_type->properties[$assertion])) { $atomic_type->properties[$assertion]->possibly_undefined = \false; } else { $atomic_type->properties[$assertion] = \Psalm\Type::getMixed(); if ($is_class_string) { $atomic_type->class_strings[$assertion] = \true; } } } } return $existing_var_type; } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileTraversable(\Psalm\Codebase $codebase, \Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($existing_var_type->hasMixed() || $existing_var_type->hasTemplate()) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject('Traversable')]); } $traversable_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type->hasTraversableInterface($codebase)) { $traversable_types[] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TIterable) { $clone_type = clone $type; $traversable_types[] = new \Psalm\Type\Atomic\TGenericObject('Traversable', $clone_type->type_params); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TObject) { $traversable_types[] = new \Psalm\Type\Atomic\TNamedObject('Traversable'); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TNamedObject) { $traversable = new \Psalm\Type\Atomic\TNamedObject('Traversable'); $type->extra_types[$traversable->getKey()] = $traversable; $traversable_types[] = $type; $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$traversable_types || !$did_remove_type) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'Traversable', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($traversable_types) { return new \Psalm\Type\Union($traversable_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileArray(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($existing_var_type->hasMixed() || $existing_var_type->hasTemplate()) { return \Psalm\Type::getArray(); } $array_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type instanceof \Psalm\Type\Atomic\TArray || $type instanceof \Psalm\Type\Atomic\TKeyedArray || $type instanceof \Psalm\Type\Atomic\TList) { $array_types[] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TCallable) { $array_types[] = new \Psalm\Type\Atomic\TCallableKeyedArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClassString(), new \Psalm\Type\Atomic\TObject()]), \Psalm\Type::getString()]); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TIterable) { $clone_type = clone $type; self::refineArrayKey($clone_type->type_params[0]); $array_types[] = new \Psalm\Type\Atomic\TArray($clone_type->type_params); $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$array_types || !$did_remove_type) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'array', !$did_remove_type, $negated, $code_location, $suppressed_issues); if (!$did_remove_type) { $failed_reconciliation = 1; } } } if ($array_types) { return \Psalm\Internal\Type\TypeCombination::combineTypes($array_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } private static function refineArrayKey(\Psalm\Type\Union $key_type) : void { foreach ($key_type->getAtomicTypes() as $key => $cat) { if ($cat instanceof \Psalm\Type\Atomic\TTemplateParam) { self::refineArrayKey($cat->as); $key_type->bustCache(); } elseif ($cat instanceof \Psalm\Type\Atomic\TScalar || $cat instanceof \Psalm\Type\Atomic\TMixed) { $key_type->removeType($key); $key_type->addType(new \Psalm\Type\Atomic\TArrayKey()); } elseif (!$cat instanceof \Psalm\Type\Atomic\TString && !$cat instanceof \Psalm\Type\Atomic\TInt) { $key_type->removeType($key); $key_type->addType(new \Psalm\Type\Atomic\TArrayKey()); } } if (!$key_type->getAtomicTypes()) { // this should ideally prompt some sort of error $key_type->addType(new \Psalm\Type\Atomic\TArrayKey()); } } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileList(\Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality, bool $is_non_empty) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($existing_var_type->hasMixed() || $existing_var_type->hasTemplate()) { return $is_non_empty ? \Psalm\Type::getNonEmptyList() : \Psalm\Type::getList(); } $array_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type instanceof \Psalm\Type\Atomic\TList || $type instanceof \Psalm\Type\Atomic\TKeyedArray && $type->is_list) { if ($is_non_empty && $type instanceof \Psalm\Type\Atomic\TList && !$type instanceof \Psalm\Type\Atomic\TNonEmptyList) { $array_types[] = new \Psalm\Type\Atomic\TNonEmptyList($type->type_param); $did_remove_type = \true; } else { $array_types[] = $type; } } elseif ($type instanceof \Psalm\Type\Atomic\TArray || $type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($type instanceof \Psalm\Type\Atomic\TKeyedArray) { $type = $type->getGenericArrayType(); } if ($type->type_params[0]->hasArrayKey() || $type->type_params[0]->hasInt()) { if ($type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $array_types[] = new \Psalm\Type\Atomic\TNonEmptyList($type->type_params[1]); } else { $array_types[] = new \Psalm\Type\Atomic\TList($type->type_params[1]); } } $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TCallable) { $array_types[] = new \Psalm\Type\Atomic\TCallableKeyedArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClassString(), new \Psalm\Type\Atomic\TObject()]), \Psalm\Type::getString()]); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TIterable) { $clone_type = clone $type; $array_types[] = new \Psalm\Type\Atomic\TList($clone_type->type_params[1]); $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$array_types || !$did_remove_type) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'array', !$did_remove_type, $negated, $code_location, $suppressed_issues); if (!$did_remove_type) { $failed_reconciliation = 1; } } } if ($array_types) { return \Psalm\Internal\Type\TypeCombination::combineTypes($array_types); } $failed_reconciliation = 2; return $existing_var_type->from_docblock ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileStringArrayAccess(\Psalm\Codebase $codebase, \Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $inside_loop) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($existing_var_type->hasMixed() || $existing_var_type->hasTemplate()) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getMixed()]), new \Psalm\Type\Atomic\TNamedObject('ArrayAccess')]); } $array_types = []; foreach ($existing_var_atomic_types as $type) { if ($type->isArrayAccessibleWithStringKey($codebase)) { if (\get_class($type) === \Psalm\Type\Atomic\TArray::class) { $array_types[] = new \Psalm\Type\Atomic\TNonEmptyArray($type->type_params); } elseif (\get_class($type) === \Psalm\Type\Atomic\TList::class) { $array_types[] = new \Psalm\Type\Atomic\TNonEmptyList($type->type_param); } else { $array_types[] = $type; } } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { $array_types[] = $type; } } if (!$array_types) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'string-array-access', \true, $negated, $code_location, $suppressed_issues); } } if ($array_types) { return new \Psalm\Type\Union($array_types); } $failed_reconciliation = 2; return \Psalm\Type::getMixed($inside_loop); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileIntArrayAccess(\Psalm\Codebase $codebase, \Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $inside_loop) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($existing_var_type->hasMixed()) { return \Psalm\Type::getMixed(); } $array_types = []; foreach ($existing_var_atomic_types as $type) { if ($type->isArrayAccessibleWithIntOrStringKey($codebase)) { if (\get_class($type) === \Psalm\Type\Atomic\TArray::class) { $array_types[] = new \Psalm\Type\Atomic\TNonEmptyArray($type->type_params); } else { $array_types[] = $type; } } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { $array_types[] = $type; } } if (!$array_types) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'int-or-string-array-access', \true, $negated, $code_location, $suppressed_issues); } } if ($array_types) { return \Psalm\Internal\Type\TypeCombination::combineTypes($array_types); } $failed_reconciliation = 2; return \Psalm\Type::getMixed($inside_loop); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileCallable(\Psalm\Codebase $codebase, \Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation, bool $is_equality) : \Psalm\Type\Union { if ($existing_var_type->hasMixed()) { return \Psalm\Type::parseString('callable'); } $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $callable_types = []; $did_remove_type = \false; foreach ($existing_var_atomic_types as $type) { if ($type->isCallableType()) { $callable_types[] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TObject) { $callable_types[] = new \Psalm\Type\Atomic\TCallableObject(); $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classExists($type->value) && $codebase->methodExists($type->value . '::__invoke')) { $callable_types[] = $type; } elseif (\get_class($type) === \Psalm\Type\Atomic\TString::class || \get_class($type) === \Psalm\Type\Atomic\TNonEmptyString::class) { $callable_types[] = new \Psalm\Type\Atomic\TCallableString(); $did_remove_type = \true; } elseif (\get_class($type) === \Psalm\Type\Atomic\TLiteralString::class && \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($type->value)) { $callable_types[] = $type; $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TArray) { $type = clone $type; $type = new \Psalm\Type\Atomic\TCallableArray($type->type_params); $callable_types[] = $type; $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TList) { $type = clone $type; $type = new \Psalm\Type\Atomic\TCallableList($type->type_param); $callable_types[] = $type; $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TKeyedArray) { $type = clone $type; $type = new \Psalm\Type\Atomic\TCallableKeyedArray($type->properties); $callable_types[] = $type; $did_remove_type = \true; } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($type->as->isMixed()) { $type = clone $type; $type->as = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TCallable()]); } $callable_types[] = $type; $did_remove_type = \true; } else { $did_remove_type = \true; } } if ((!$callable_types || !$did_remove_type) && !$is_equality) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, 'callable', !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($callable_types) { return \Psalm\Internal\Type\TypeCombination::combineTypes($callable_types); } $failed_reconciliation = 2; return \Psalm\Type::getMixed(); } /** * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation */ private static function reconcileFalsyOrEmpty(string $assertion, \Psalm\Type\Union $existing_var_type, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation) : \Psalm\Type\Union { $old_var_type_string = $existing_var_type->getId(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $did_remove_type = $existing_var_type->hasDefinitelyNumericType(\false) || $existing_var_type->hasType('iterable'); if ($existing_var_type->hasMixed()) { if ($existing_var_type->isMixed() && $existing_var_atomic_types['mixed'] instanceof \Psalm\Type\Atomic\TNonEmptyMixed) { if ($code_location && $key && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParadoxicalCondition('Found a paradox when evaluating ' . $key . ' of type ' . $existing_var_type->getId() . ' and trying to reconcile it with a ' . $assertion . ' assertion', $code_location), $suppressed_issues)) { // fall through } return \Psalm\Type::getMixed(); } if (!$existing_var_atomic_types['mixed'] instanceof \Psalm\Type\Atomic\TEmptyMixed) { $did_remove_type = \true; $existing_var_type->removeType('mixed'); if (!$existing_var_atomic_types['mixed'] instanceof \Psalm\Type\Atomic\TNonEmptyMixed) { $existing_var_type->addType(new \Psalm\Type\Atomic\TEmptyMixed()); } } elseif ($existing_var_type->isMixed()) { if ($code_location && $key && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition('Found a redundant condition when evaluating ' . $key . ' of type ' . $existing_var_type->getId() . ' and trying to reconcile it with a ' . $assertion . ' assertion', $code_location, $existing_var_type->getId() . ' ' . $assertion), $suppressed_issues)) { // fall through } } if ($existing_var_type->isMixed()) { return $existing_var_type; } } if ($existing_var_type->hasScalar()) { if ($existing_var_type->isSingle() && $existing_var_atomic_types['scalar'] instanceof \Psalm\Type\Atomic\TNonEmptyScalar) { if ($code_location && $key && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParadoxicalCondition('Found a paradox when evaluating ' . $key . ' of type ' . $existing_var_type->getId() . ' and trying to reconcile it with a ' . $assertion . ' assertion', $code_location), $suppressed_issues)) { // fall through } return \Psalm\Type::getScalar(); } if (!$existing_var_atomic_types['scalar'] instanceof \Psalm\Type\Atomic\TEmptyScalar) { $did_remove_type = \true; $existing_var_type->removeType('scalar'); if (!$existing_var_atomic_types['scalar'] instanceof \Psalm\Type\Atomic\TNonEmptyScalar) { $existing_var_type->addType(new \Psalm\Type\Atomic\TEmptyScalar()); } } elseif ($existing_var_type->isSingle()) { if ($code_location && $key && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition('Found a redundant condition when evaluating ' . $key . ' of type ' . $existing_var_type->getId() . ' and trying to reconcile it with a ' . $assertion . ' assertion', $code_location, $existing_var_type->getId() . ' ' . $assertion), $suppressed_issues)) { // fall through } } if ($existing_var_type->isSingle()) { return $existing_var_type; } } if ($existing_var_type->hasType('bool')) { $did_remove_type = \true; $existing_var_type->removeType('bool'); $existing_var_type->addType(new \Psalm\Type\Atomic\TFalse()); } if ($existing_var_type->hasType('true')) { $did_remove_type = \true; $existing_var_type->removeType('true'); } if ($existing_var_type->hasString()) { $existing_string_types = $existing_var_type->getLiteralStrings(); if ($existing_string_types) { foreach ($existing_string_types as $string_key => $literal_type) { if ($literal_type->value) { $existing_var_type->removeType($string_key); $did_remove_type = \true; } } } else { $did_remove_type = \true; if ($existing_var_type->hasType('class-string')) { $existing_var_type->removeType('class-string'); } if ($existing_var_type->hasType('callable-string')) { $existing_var_type->removeType('callable-string'); } if ($existing_var_type->hasType('string')) { $existing_var_type->removeType('string'); if (!$existing_var_atomic_types['string'] instanceof \Psalm\Type\Atomic\TNonEmptyString) { $existing_var_type->addType(new \Psalm\Type\Atomic\TLiteralString('')); $existing_var_type->addType(new \Psalm\Type\Atomic\TLiteralString('0')); } } } } if ($existing_var_type->hasInt()) { $existing_int_types = $existing_var_type->getLiteralInts(); if ($existing_int_types) { foreach ($existing_int_types as $int_key => $literal_type) { if ($literal_type->value) { $existing_var_type->removeType($int_key); $did_remove_type = \true; } } } else { $did_remove_type = \true; $existing_var_type->removeType('int'); $existing_var_type->addType(new \Psalm\Type\Atomic\TLiteralInt(0)); } } if ($existing_var_type->hasFloat()) { $existing_float_types = $existing_var_type->getLiteralFloats(); if ($existing_float_types) { foreach ($existing_float_types as $float_key => $literal_type) { if ($literal_type->value) { $existing_var_type->removeType($float_key); $did_remove_type = \true; } } } else { $did_remove_type = \true; $existing_var_type->removeType('float'); $existing_var_type->addType(new \Psalm\Type\Atomic\TLiteralFloat(0)); } } if ($existing_var_type->hasNumeric()) { $existing_int_types = $existing_var_type->getLiteralInts(); if ($existing_int_types) { foreach ($existing_int_types as $int_key => $literal_type) { if ($literal_type->value) { $existing_var_type->removeType($int_key); } } } $existing_string_types = $existing_var_type->getLiteralStrings(); if ($existing_string_types) { foreach ($existing_string_types as $string_key => $literal_type) { if ($literal_type->value) { $existing_var_type->removeType($string_key); } } } $existing_float_types = $existing_var_type->getLiteralFloats(); if ($existing_float_types) { foreach ($existing_float_types as $float_key => $literal_type) { if ($literal_type->value) { $existing_var_type->removeType($float_key); } } } $did_remove_type = \true; $existing_var_type->removeType('numeric'); $existing_var_type->addType(new \Psalm\Type\Atomic\TEmptyNumeric()); } if (isset($existing_var_atomic_types['array'])) { $array_atomic_type = $existing_var_atomic_types['array']; if ($array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyList || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray && \array_filter($array_atomic_type->properties, function (\Psalm\Type\Union $t) : bool { return !$t->possibly_undefined; })) { $did_remove_type = \true; $existing_var_type->removeType('array'); } elseif ($array_atomic_type->getId() !== 'array') { $did_remove_type = \true; $existing_var_type->addType(new \Psalm\Type\Atomic\TArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()])])); } } if (isset($existing_var_atomic_types['scalar']) && $existing_var_atomic_types['scalar']->getId() !== 'empty-scalar') { $did_remove_type = \true; $existing_var_type->addType(new \Psalm\Type\Atomic\TEmptyScalar()); } foreach ($existing_var_atomic_types as $type_key => $type) { if ($type instanceof \Psalm\Type\Atomic\TNamedObject || $type instanceof \Psalm\Type\Atomic\TObject || $type instanceof \Psalm\Type\Atomic\TResource || $type instanceof \Psalm\Type\Atomic\TCallable || $type instanceof \Psalm\Type\Atomic\TClassString) { $did_remove_type = \true; $existing_var_type->removeType($type_key); } if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { $did_remove_type = \true; } } if ((!$did_remove_type || empty($existing_var_type->getAtomicTypes())) && ($assertion !== 'empty' || !$existing_var_type->possibly_undefined)) { if ($key && $code_location) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, $assertion, !$did_remove_type, $negated, $code_location, $suppressed_issues); } } if ($existing_var_type->getAtomicTypes()) { return $existing_var_type; } $failed_reconciliation = 2; return $assertion === 'empty' && $existing_var_type->possibly_undefined ? \Psalm\Type::getEmpty() : \Psalm\Type::getMixed(); } } > $template_type_map * @param string[] $suppressed_issues * @param 0|1|2 $failed_reconciliation * */ public static function reconcile(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $assertion, bool $is_strict_equality, bool $is_loose_equality, \Psalm\Type\Union $existing_var_type, array $template_type_map, string $old_var_type_string, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, int &$failed_reconciliation) : \Psalm\Type\Union { $is_equality = $is_strict_equality || $is_loose_equality; // this is a specific value comparison type that cannot be negated if ($is_equality && ($bracket_pos = \strpos($assertion, '('))) { if ($existing_var_type->hasMixed()) { return $existing_var_type; } return self::handleLiteralNegatedEquality($statements_analyzer, $assertion, $bracket_pos, $existing_var_type, $old_var_type_string, $key, $negated, $code_location, $suppressed_issues, $is_strict_equality); } if ($is_equality && $assertion === 'positive-numeric') { return $existing_var_type; } if (!$is_equality) { if ($assertion === 'isset') { if ($existing_var_type->possibly_undefined) { return \Psalm\Type::getEmpty(); } if (!$existing_var_type->isNullable() && $key && \strpos($key, '[') === \false && $key !== '$_SESSION') { foreach ($existing_var_type->getAtomicTypes() as $atomic) { if (!$existing_var_type->hasMixed() || $atomic instanceof \Psalm\Type\Atomic\TNonEmptyMixed) { $failed_reconciliation = 2; if ($code_location) { if ($existing_var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction('Cannot resolve types for ' . $key . ' with docblock-defined type ' . $existing_var_type . ' and !isset assertion', $code_location, null), $suppressed_issues)) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType('Cannot resolve types for ' . $key . ' with type ' . $existing_var_type . ' and !isset assertion', $code_location, null), $suppressed_issues)) { // fall through } } } return $existing_var_type->from_docblock ? \Psalm\Type::getNull() : \Psalm\Type::getEmpty(); } } } return \Psalm\Type::getNull(); } elseif ($assertion === 'array-key-exists') { return \Psalm\Type::getEmpty(); } elseif (\substr($assertion, 0, 9) === 'in-array-') { return $existing_var_type; } elseif (\substr($assertion, 0, 14) === 'has-array-key-') { return $existing_var_type; } } $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); if ($assertion === 'false' && isset($existing_var_atomic_types['bool'])) { $existing_var_type->removeType('bool'); $existing_var_type->addType(new \Psalm\Type\Atomic\TTrue()); } elseif ($assertion === 'true' && isset($existing_var_atomic_types['bool'])) { $existing_var_type->removeType('bool'); $existing_var_type->addType(new \Psalm\Type\Atomic\TFalse()); } else { $simple_negated_type = \Psalm\Internal\Type\SimpleNegatedAssertionReconciler::reconcile($assertion, $existing_var_type, $key, $negated, $code_location, $suppressed_issues, $failed_reconciliation, $is_equality, $is_strict_equality); if ($simple_negated_type) { return $simple_negated_type; } } if ($assertion === 'iterable' || $assertion === 'countable') { $existing_var_type->removeType('array'); } if (!$is_equality && isset($existing_var_atomic_types['int']) && $existing_var_type->from_calculation && ($assertion === 'int' || $assertion === 'float')) { $existing_var_type->removeType($assertion); if ($assertion === 'int') { $existing_var_type->addType(new \Psalm\Type\Atomic\TFloat()); } else { $existing_var_type->addType(new \Psalm\Type\Atomic\TInt()); } $existing_var_type->from_calculation = \false; return $existing_var_type; } if (\strtolower($assertion) === 'traversable' && isset($existing_var_atomic_types['iterable'])) { /** @var Type\Atomic\TIterable */ $iterable = $existing_var_atomic_types['iterable']; $existing_var_type->removeType('iterable'); $existing_var_type->addType(new \Psalm\Type\Atomic\TArray([$iterable->type_params[0]->hasMixed() ? \Psalm\Type::getArrayKey() : clone $iterable->type_params[0], clone $iterable->type_params[1]])); } elseif (\strtolower($assertion) === 'int' && isset($existing_var_type->getAtomicTypes()['array-key'])) { $existing_var_type->removeType('array-key'); $existing_var_type->addType(new \Psalm\Type\Atomic\TString()); } elseif (\substr($assertion, 0, 9) === 'getclass-') { $assertion = \substr($assertion, 9); } elseif (!$is_equality) { $codebase = $statements_analyzer->getCodebase(); // if there wasn't a direct hit, go deeper, eliminating subtypes if (!$existing_var_type->removeType($assertion)) { foreach ($existing_var_type->getAtomicTypes() as $part_name => $existing_var_type_part) { if (!$existing_var_type_part->isObjectType() || \strpos($assertion, '-')) { continue; } $new_type_part = \Psalm\Type\Atomic::create($assertion); if (!$new_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { continue; } if (\Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $existing_var_type_part, $new_type_part, \false, \false)) { $existing_var_type->removeType($part_name); } elseif (\Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $new_type_part, $existing_var_type_part, \false, \false)) { $existing_var_type->different = \true; } } } } if ($is_strict_equality && $assertion !== 'isset' && ($key !== '$this' || !$statements_analyzer->getSource()->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $assertion = \Psalm\Type::parseString($assertion, null, $template_type_map); if ($key && $code_location && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($statements_analyzer->getCodebase(), $existing_var_type, $assertion)) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!=' . $assertion, \true, $negated, $code_location, $suppressed_issues); } } if (empty($existing_var_type->getAtomicTypes())) { if ($key !== '$this' || !$statements_analyzer->getSource()->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) { if ($key && $code_location && !$is_equality) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!' . $assertion, \false, $negated, $code_location, $suppressed_issues); } } $failed_reconciliation = 2; return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmptyMixed()]); } return $existing_var_type; } /** * @param string[] $suppressed_issues * */ private static function handleLiteralNegatedEquality(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $assertion, int $bracket_pos, \Psalm\Type\Union $existing_var_type, string $old_var_type_string, ?string $key, bool $negated, ?\Psalm\CodeLocation $code_location, array $suppressed_issues, bool $is_strict_equality) : \Psalm\Type\Union { $scalar_type = \substr($assertion, 0, $bracket_pos); $existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $did_remove_type = \false; $did_match_literal_type = \false; $scalar_var_type = null; if ($scalar_type === 'int') { if ($existing_var_type->hasInt()) { if ($existing_int_types = $existing_var_type->getLiteralInts()) { if (!$existing_var_type->hasPositiveInt()) { $did_match_literal_type = \true; } if (isset($existing_int_types[$assertion])) { $existing_var_type->removeType($assertion); $did_remove_type = \true; } } } else { $scalar_value = \substr($assertion, $bracket_pos + 1, -1); $scalar_var_type = \Psalm\Type::getInt(\false, (int) $scalar_value); } } elseif ($scalar_type === 'string' || $scalar_type === 'class-string' || $scalar_type === 'interface-string' || $scalar_type === 'trait-string' || $scalar_type === 'callable-string') { if ($existing_var_type->hasString()) { if ($existing_string_types = $existing_var_type->getLiteralStrings()) { $did_match_literal_type = \true; if (isset($existing_string_types[$assertion])) { $existing_var_type->removeType($assertion); $did_remove_type = \true; } } elseif ($assertion === 'string()') { $existing_var_type->addType(new \Psalm\Type\Atomic\TNonEmptyString()); } } elseif ($scalar_type === 'string') { $scalar_value = \substr($assertion, $bracket_pos + 1, -1); $scalar_var_type = \Psalm\Type::getString($scalar_value); } } elseif ($scalar_type === 'float') { if ($existing_var_type->hasFloat()) { if ($existing_float_types = $existing_var_type->getLiteralFloats()) { $did_match_literal_type = \true; if (isset($existing_float_types[$assertion])) { $existing_var_type->removeType($assertion); $did_remove_type = \true; } } } else { $scalar_value = \substr($assertion, $bracket_pos + 1, -1); $scalar_var_type = \Psalm\Type::getFloat((float) $scalar_value); } } if ($key && $code_location) { if ($did_match_literal_type && (!$did_remove_type || \count($existing_var_atomic_types) === 1)) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!' . $assertion, !$did_remove_type, $negated, $code_location, $suppressed_issues); } elseif ($scalar_var_type && $is_strict_equality && ($key !== '$this' || !$statements_analyzer->getSource()->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($statements_analyzer->getCodebase(), $existing_var_type, $scalar_var_type)) { self::triggerIssueForImpossible($existing_var_type, $old_var_type_string, $key, '!=' . $assertion, \true, $negated, $code_location, $suppressed_issues); } } } return $existing_var_type; } } getAtomicTypes() as $return_type_part) { $parts = self::expandAtomic($codebase, $return_type_part, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); if (\is_array($parts)) { $new_return_type_parts = \array_merge($new_return_type_parts, $parts); $has_array_output = \true; } else { $new_return_type_parts[] = $parts; } } if ($has_array_output) { $fleshed_out_type = \Psalm\Internal\Type\TypeCombination::combineTypes($new_return_type_parts, $codebase); } else { $fleshed_out_type = new \Psalm\Type\Union($new_return_type_parts); } $fleshed_out_type->from_docblock = $return_type->from_docblock; $fleshed_out_type->ignore_nullable_issues = $return_type->ignore_nullable_issues; $fleshed_out_type->ignore_falsable_issues = $return_type->ignore_falsable_issues; $fleshed_out_type->possibly_undefined = $return_type->possibly_undefined; $fleshed_out_type->possibly_undefined_from_try = $return_type->possibly_undefined_from_try; $fleshed_out_type->by_ref = $return_type->by_ref; $fleshed_out_type->initialized = $return_type->initialized; $fleshed_out_type->had_template = $return_type->had_template; $fleshed_out_type->parent_nodes = $return_type->parent_nodes; return $fleshed_out_type; } /** * @param string|Type\Atomic\TNamedObject|Type\Atomic\TTemplateParam|null $static_class_type * * @return Type\Atomic|non-empty-list */ public static function expandAtomic(\Psalm\Codebase $codebase, \Psalm\Type\Atomic &$return_type, ?string $self_class, $static_class_type, ?string $parent_class, bool $evaluate_class_constants = \true, bool $evaluate_conditional_types = \false, bool $final = \false) { if ($return_type instanceof \Psalm\Type\Atomic\TNamedObject || $return_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($return_type->extra_types) { $new_intersection_types = []; foreach ($return_type->extra_types as &$extra_type) { self::expandAtomic($codebase, $extra_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types); if ($extra_type instanceof \Psalm\Type\Atomic\TNamedObject && $extra_type->extra_types) { $new_intersection_types = \array_merge($new_intersection_types, $extra_type->extra_types); $extra_type->extra_types = []; } } if ($new_intersection_types) { $return_type->extra_types = \array_merge($return_type->extra_types, $new_intersection_types); } } if ($return_type instanceof \Psalm\Type\Atomic\TNamedObject) { $return_type_lc = \strtolower($return_type->value); if ($static_class_type && ($return_type_lc === 'static' || $return_type_lc === '$this')) { if (\is_string($static_class_type)) { $return_type->value = $static_class_type; } else { if ($return_type instanceof \Psalm\Type\Atomic\TGenericObject && $static_class_type instanceof \Psalm\Type\Atomic\TGenericObject) { $return_type->value = $static_class_type->value; } else { $return_type = clone $static_class_type; } } if (!$final && $return_type instanceof \Psalm\Type\Atomic\TNamedObject) { $return_type->was_static = \true; } } elseif ($return_type->was_static && ($static_class_type instanceof \Psalm\Type\Atomic\TNamedObject || $static_class_type instanceof \Psalm\Type\Atomic\TTemplateParam)) { $return_type = clone $return_type; $cloned_static = clone $static_class_type; $extra_static = $cloned_static->extra_types ?: []; $cloned_static->extra_types = null; if ($cloned_static->getKey(\false) !== $return_type->getKey(\false)) { $return_type->extra_types[$static_class_type->getKey()] = clone $cloned_static; } foreach ($extra_static as $extra_static_type) { if ($extra_static_type->getKey(\false) !== $return_type->getKey(\false)) { $return_type->extra_types[$extra_static_type->getKey()] = clone $extra_static_type; } } } elseif ($self_class && $return_type_lc === 'self') { $return_type->value = $self_class; } elseif ($parent_class && $return_type_lc === 'parent') { $return_type->value = $parent_class; } else { $return_type->value = $codebase->classlikes->getUnAliasedName($return_type->value); } } } if ($return_type instanceof \Psalm\Type\Atomic\TClassString && $return_type->as_type) { $new_as_type = clone $return_type->as_type; self::expandAtomic($codebase, $new_as_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); if ($new_as_type instanceof \Psalm\Type\Atomic\TNamedObject) { $return_type->as_type = $new_as_type; $return_type->as = $return_type->as_type->value; } } elseif ($return_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $new_as_type = self::expandUnion($codebase, clone $return_type->as, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); $return_type->as = $new_as_type; } if ($return_type instanceof \Psalm\Type\Atomic\TScalarClassConstant) { if ($return_type->fq_classlike_name === 'self' && $self_class) { $return_type->fq_classlike_name = $self_class; } if ($evaluate_class_constants && $codebase->classOrInterfaceExists($return_type->fq_classlike_name)) { if (\strtolower($return_type->const_name) === 'class') { return new \Psalm\Type\Atomic\TLiteralClassString($return_type->fq_classlike_name); } if (\strpos($return_type->const_name, '*') !== \false) { $class_storage = $codebase->classlike_storage_provider->get($return_type->fq_classlike_name); $matching_constants = \array_keys($class_storage->constants); $const_name_part = \substr($return_type->const_name, 0, -1); if ($const_name_part) { $matching_constants = \array_filter($matching_constants, function ($constant_name) use($const_name_part) : bool { return $constant_name !== $const_name_part && \strpos($constant_name, $const_name_part) === 0; }); } } else { $matching_constants = [$return_type->const_name]; } $matching_constant_types = []; foreach ($matching_constants as $matching_constant) { try { $class_constant = $codebase->classlikes->getClassConstantType($return_type->fq_classlike_name, $matching_constant, \ReflectionProperty::IS_PRIVATE); } catch (\Psalm\Exception\CircularReferenceException $e) { $class_constant = null; } if ($class_constant) { if ($class_constant->isSingle()) { $class_constant = clone $class_constant; $matching_constant_types = \array_merge(\array_values($class_constant->getAtomicTypes()), $matching_constant_types); } } } if ($matching_constant_types) { return $matching_constant_types; } } return $return_type; } if ($return_type instanceof \Psalm\Type\Atomic\TTypeAlias) { $declaring_fq_classlike_name = $return_type->declaring_fq_classlike_name; if ($declaring_fq_classlike_name === 'self' && $self_class) { $declaring_fq_classlike_name = $self_class; } if ($evaluate_class_constants && $codebase->classOrInterfaceExists($declaring_fq_classlike_name)) { $class_storage = $codebase->classlike_storage_provider->get($declaring_fq_classlike_name); $type_alias_name = $return_type->alias_name; if (isset($class_storage->type_aliases[$type_alias_name])) { $resolved_type_alias = $class_storage->type_aliases[$type_alias_name]; if ($resolved_type_alias->replacement_atomic_types) { $replacement_atomic_types = $resolved_type_alias->replacement_atomic_types; $recursively_fleshed_out_types = []; foreach ($replacement_atomic_types as $replacement_atomic_type) { $recursively_fleshed_out_type = self::expandAtomic($codebase, $replacement_atomic_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types); if (\is_array($recursively_fleshed_out_type)) { $recursively_fleshed_out_types = \array_merge($recursively_fleshed_out_type, $recursively_fleshed_out_types); } else { $recursively_fleshed_out_types[] = $recursively_fleshed_out_type; } } return $recursively_fleshed_out_types; } } } return $return_type; } if ($return_type instanceof \Psalm\Type\Atomic\TKeyOfClassConstant || $return_type instanceof \Psalm\Type\Atomic\TValueOfClassConstant) { if ($return_type->fq_classlike_name === 'self' && $self_class) { $return_type->fq_classlike_name = $self_class; } if ($evaluate_class_constants && $codebase->classOrInterfaceExists($return_type->fq_classlike_name)) { try { $class_constant_type = $codebase->classlikes->getClassConstantType($return_type->fq_classlike_name, $return_type->const_name, \ReflectionProperty::IS_PRIVATE); } catch (\Psalm\Exception\CircularReferenceException $e) { $class_constant_type = null; } if ($class_constant_type) { foreach ($class_constant_type->getAtomicTypes() as $const_type_atomic) { if ($const_type_atomic instanceof \Psalm\Type\Atomic\TKeyedArray || $const_type_atomic instanceof \Psalm\Type\Atomic\TArray) { if ($const_type_atomic instanceof \Psalm\Type\Atomic\TKeyedArray) { $const_type_atomic = $const_type_atomic->getGenericArrayType(); } if ($return_type instanceof \Psalm\Type\Atomic\TKeyOfClassConstant) { return \array_values($const_type_atomic->type_params[0]->getAtomicTypes()); } return \array_values($const_type_atomic->type_params[1]->getAtomicTypes()); } } } } return $return_type; } if ($return_type instanceof \Psalm\Type\Atomic\TArray || $return_type instanceof \Psalm\Type\Atomic\TGenericObject || $return_type instanceof \Psalm\Type\Atomic\TIterable) { foreach ($return_type->type_params as $k => $type_param) { /** @psalm-suppress PropertyTypeCoercion */ $return_type->type_params[$k] = self::expandUnion($codebase, $type_param, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); } } elseif ($return_type instanceof \Psalm\Type\Atomic\TKeyedArray) { foreach ($return_type->properties as &$property_type) { $property_type = self::expandUnion($codebase, $property_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); } } elseif ($return_type instanceof \Psalm\Type\Atomic\TList) { $return_type->type_param = self::expandUnion($codebase, $return_type->type_param, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); } if ($return_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { foreach ($return_type->properties as &$property_type) { $property_type = self::expandUnion($codebase, $property_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); } } if ($return_type instanceof \Psalm\Type\Atomic\TCallable || $return_type instanceof \Psalm\Type\Atomic\TClosure) { if ($return_type->params) { foreach ($return_type->params as $param) { if ($param->type) { $param->type = self::expandUnion($codebase, $param->type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); } } } if ($return_type->return_type) { $return_type->return_type = self::expandUnion($codebase, $return_type->return_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); } } if ($return_type instanceof \Psalm\Type\Atomic\TConditional) { if ($evaluate_conditional_types) { $assertion = null; if ($return_type->conditional_type->isSingle()) { foreach ($return_type->conditional_type->getAtomicTypes() as $condition_atomic_type) { $candidate = self::expandAtomic($codebase, $condition_atomic_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); if (!\is_array($candidate)) { $assertion = $candidate->getAssertionString(); } } } $if_conditional_return_types = []; foreach ($return_type->if_type->getAtomicTypes() as $if_atomic_type) { $candidate = self::expandAtomic($codebase, $if_atomic_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); $candidate_types = \is_array($candidate) ? $candidate : [$candidate]; $if_conditional_return_types = \array_merge($if_conditional_return_types, $candidate_types); } $else_conditional_return_types = []; foreach ($return_type->else_type->getAtomicTypes() as $else_atomic_type) { $candidate = self::expandAtomic($codebase, $else_atomic_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); $candidate_types = \is_array($candidate) ? $candidate : [$candidate]; $else_conditional_return_types = \array_merge($else_conditional_return_types, $candidate_types); } if ($assertion && $return_type->param_name === (string) $return_type->if_type) { $if_conditional_return_type = \Psalm\Internal\Type\TypeCombination::combineTypes($if_conditional_return_types, $codebase); $if_conditional_return_type = \Psalm\Internal\Type\SimpleAssertionReconciler::reconcile($assertion, $codebase, $if_conditional_return_type); if ($if_conditional_return_type) { $if_conditional_return_types = \array_values($if_conditional_return_type->getAtomicTypes()); } } if ($assertion && $return_type->param_name === (string) $return_type->else_type) { $else_conditional_return_type = \Psalm\Internal\Type\TypeCombination::combineTypes($else_conditional_return_types, $codebase); $else_conditional_return_type = \Psalm\Internal\Type\SimpleNegatedAssertionReconciler::reconcile($assertion, $else_conditional_return_type); if ($else_conditional_return_type) { $else_conditional_return_types = \array_values($else_conditional_return_type->getAtomicTypes()); } } $all_conditional_return_types = \array_merge($if_conditional_return_types, $else_conditional_return_types); foreach ($all_conditional_return_types as $i => $conditional_return_type) { if ($conditional_return_type instanceof \Psalm\Type\Atomic\TVoid && \count($all_conditional_return_types) > 1) { $all_conditional_return_types[$i] = new \Psalm\Type\Atomic\TNull(); $all_conditional_return_types[$i]->from_docblock = \true; } } $combined = \Psalm\Internal\Type\TypeCombination::combineTypes(\array_values($all_conditional_return_types), $codebase); return \array_values($combined->getAtomicTypes()); } $return_type->conditional_type = self::expandUnion($codebase, $return_type->conditional_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); $return_type->if_type = self::expandUnion($codebase, $return_type->if_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); $return_type->else_type = self::expandUnion($codebase, $return_type->else_type, $self_class, $static_class_type, $parent_class, $evaluate_class_constants, $evaluate_conditional_types, $final); } return $return_type; } } getAtomicTypes(); $had_template = \false; foreach ($original_atomic_types as $key => $atomic_type) { $atomic_types = \array_merge($atomic_types, self::handleAtomicStandin($atomic_type, $key, $template_result, $codebase, $statements_analyzer, $input_type, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth, \count($original_atomic_types) === 1, $union_type->isNullable(), $had_template)); } if ($replace) { if (\array_values($original_atomic_types) === $atomic_types) { return $union_type; } if (!$atomic_types) { throw new \UnexpectedValueException('Cannot remove all keys'); } $new_union_type = new \Psalm\Type\Union($atomic_types); $new_union_type->ignore_nullable_issues = $union_type->ignore_nullable_issues; $new_union_type->ignore_falsable_issues = $union_type->ignore_falsable_issues; $new_union_type->possibly_undefined = $union_type->possibly_undefined; if ($had_template) { $new_union_type->had_template = \true; } return $new_union_type; } return $union_type; } /** * @return list */ private static function handleAtomicStandin(\Psalm\Type\Atomic $atomic_type, string $key, \Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, ?\Psalm\Type\Union $input_type, ?int $input_arg_offset, ?string $calling_class, ?string $calling_function, bool $replace, bool $add_upper_bound, int $depth, bool $was_single, bool $was_nullable, bool &$had_template) : array { if ($bracket_pos = \strpos($key, '<')) { $key = \substr($key, 0, $bracket_pos); } if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam && isset($template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class])) { $a = self::handleTemplateParamStandin($atomic_type, $key, $input_type, $input_arg_offset, $calling_class, $calling_function, $template_result, $codebase, $statements_analyzer, $replace, $add_upper_bound, $depth, $was_nullable, $had_template); return $a; } if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParamClass && isset($template_result->template_types[$atomic_type->param_name])) { if ($replace) { return self::handleTemplateParamClassStandin($atomic_type, $input_type, $input_arg_offset, $template_result, $depth, $was_single); } } if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateIndexedAccess) { if ($replace) { $atomic_types = []; $include_first = \true; if (isset($template_result->template_types[$atomic_type->array_param_name][$atomic_type->defining_class]) && !empty($template_result->upper_bounds[$atomic_type->offset_param_name])) { $array_template_type = $template_result->template_types[$atomic_type->array_param_name][$atomic_type->defining_class][0]; $offset_template_type = \array_values($template_result->upper_bounds[$atomic_type->offset_param_name])[0][0]; if ($array_template_type->isSingle() && $offset_template_type->isSingle() && !$array_template_type->isMixed() && !$offset_template_type->isMixed()) { $array_template_type = \array_values($array_template_type->getAtomicTypes())[0]; $offset_template_type = \array_values($offset_template_type->getAtomicTypes())[0]; if ($array_template_type instanceof \Psalm\Type\Atomic\TKeyedArray && ($offset_template_type instanceof \Psalm\Type\Atomic\TLiteralString || $offset_template_type instanceof \Psalm\Type\Atomic\TLiteralInt) && isset($array_template_type->properties[$offset_template_type->value])) { $include_first = \false; $replacement_type = clone $array_template_type->properties[$offset_template_type->value]; foreach ($replacement_type->getAtomicTypes() as $replacement_atomic_type) { $atomic_types[] = $replacement_atomic_type; } } } } if ($include_first) { $atomic_types[] = $atomic_type; } return $atomic_types; } return [$atomic_type]; } if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateKeyOf) { if ($replace) { $atomic_types = []; $include_first = \true; if (isset($template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class])) { $template_type = $template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class][0]; if ($template_type->isSingle()) { $template_type = \array_values($template_type->getAtomicTypes())[0]; if ($template_type instanceof \Psalm\Type\Atomic\TKeyedArray || $template_type instanceof \Psalm\Type\Atomic\TArray || $template_type instanceof \Psalm\Type\Atomic\TList) { if ($template_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $key_type = $template_type->getGenericKeyType(); } elseif ($template_type instanceof \Psalm\Type\Atomic\TList) { $key_type = \Psalm\Type::getInt(); } else { $key_type = clone $template_type->type_params[0]; } $include_first = \false; foreach ($key_type->getAtomicTypes() as $key_atomic_type) { $atomic_types[] = $key_atomic_type; } } } } if ($include_first) { $atomic_types[] = $atomic_type; } return $atomic_types; } return [$atomic_type]; } $matching_atomic_types = []; if ($input_type && $codebase && !$input_type->hasMixed()) { $matching_atomic_types = self::findMatchingAtomicTypesForTemplate($input_type, $atomic_type, $key, $codebase, $statements_analyzer); } if (!$matching_atomic_types) { $atomic_type = $atomic_type->replaceTemplateTypesWithStandins($template_result, $codebase, $statements_analyzer, null, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth + 1); return [$atomic_type]; } $atomic_types = []; foreach ($matching_atomic_types as $matching_atomic_type) { $atomic_types[] = $atomic_type->replaceTemplateTypesWithStandins($template_result, $codebase, $statements_analyzer, $matching_atomic_type, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth + 1); } return $atomic_types; } /** * @return list */ private static function findMatchingAtomicTypesForTemplate(\Psalm\Type\Union $input_type, \Psalm\Type\Atomic $base_type, string $key, \Psalm\Codebase $codebase, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer) : array { $matching_atomic_types = []; foreach ($input_type->getAtomicTypes() as $input_key => $atomic_input_type) { if ($bracket_pos = \strpos($input_key, '<')) { $input_key = \substr($input_key, 0, $bracket_pos); } if ($input_key === $key) { $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } if ($atomic_input_type instanceof \Psalm\Type\Atomic\TClosure && $base_type instanceof \Psalm\Type\Atomic\TClosure) { $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } if ($atomic_input_type instanceof \Psalm\Type\Atomic\TCallable && $base_type instanceof \Psalm\Type\Atomic\TCallable) { $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } if ($atomic_input_type instanceof \Psalm\Type\Atomic\TClosure && $base_type instanceof \Psalm\Type\Atomic\TCallable) { $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } if (($atomic_input_type instanceof \Psalm\Type\Atomic\TArray || $atomic_input_type instanceof \Psalm\Type\Atomic\TKeyedArray || $atomic_input_type instanceof \Psalm\Type\Atomic\TList) && $key === 'iterable') { $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } if (\strpos($input_key, $key . '&') === 0) { $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } if ($atomic_input_type instanceof \Psalm\Type\Atomic\TLiteralClassString && $base_type instanceof \Psalm\Type\Atomic\TClassString && $base_type->as_type) { try { $classlike_storage = $codebase->classlike_storage_provider->get($atomic_input_type->value); if (isset($classlike_storage->template_type_extends[$base_type->as_type->value])) { $extends_list = $classlike_storage->template_type_extends[$base_type->as_type->value]; $new_generic_params = []; foreach ($extends_list as $extends_key => $value) { if (\is_string($extends_key)) { $new_generic_params[] = $value; } } if ($new_generic_params) { $atomic_input_type = new \Psalm\Type\Atomic\TClassString($base_type->as_type->value, new \Psalm\Type\Atomic\TGenericObject($base_type->as_type->value, $new_generic_params)); } $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } } catch (\InvalidArgumentException $e) { // do nothing } } if ($base_type instanceof \Psalm\Type\Atomic\TCallable) { $matching_atomic_type = \Psalm\Internal\Type\Comparator\CallableTypeComparator::getCallableFromAtomic($codebase, $atomic_input_type, null, $statements_analyzer); if ($matching_atomic_type) { $matching_atomic_types[$matching_atomic_type->getId()] = $matching_atomic_type; continue; } } if ($atomic_input_type instanceof \Psalm\Type\Atomic\TNamedObject && ($base_type instanceof \Psalm\Type\Atomic\TNamedObject || $base_type instanceof \Psalm\Type\Atomic\TIterable)) { if ($base_type instanceof \Psalm\Type\Atomic\TIterable) { if ($atomic_input_type->value === 'Traversable') { $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } $base_type = new \Psalm\Type\Atomic\TGenericObject('Traversable', $base_type->type_params); } try { $classlike_storage = $codebase->classlike_storage_provider->get($atomic_input_type->value); if ($atomic_input_type instanceof \Psalm\Type\Atomic\TGenericObject && isset($classlike_storage->template_type_extends[$base_type->value])) { $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } if (isset($classlike_storage->template_type_extends[$base_type->value])) { $extends_list = $classlike_storage->template_type_extends[$base_type->value]; $new_generic_params = []; foreach ($extends_list as $extends_key => $value) { if (\is_string($extends_key)) { $new_generic_params[] = $value; } } if (!$new_generic_params) { $atomic_input_type = new \Psalm\Type\Atomic\TNamedObject($atomic_input_type->value); } else { $atomic_input_type = new \Psalm\Type\Atomic\TGenericObject($atomic_input_type->value, $new_generic_params); } $matching_atomic_types[$atomic_input_type->getId()] = $atomic_input_type; continue; } } catch (\InvalidArgumentException $e) { // do nothing } } } return \array_values($matching_atomic_types); } /** * @return list */ private static function handleTemplateParamStandin(\Psalm\Type\Atomic\TTemplateParam $atomic_type, string $key, ?\Psalm\Type\Union $input_type, ?int $input_arg_offset, ?string $calling_class, ?string $calling_function, \Psalm\Internal\Type\TemplateResult $template_result, ?\Psalm\Codebase $codebase, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, bool $replace, bool $add_upper_bound, int $depth, bool $was_nullable, bool &$had_template) : array { $template_type = $template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class][0]; if ($template_type->getId() === $key) { return \array_values($template_type->getAtomicTypes()); } $replacement_type = $template_type; $param_name_key = $atomic_type->param_name; if (\strpos($key, '&')) { $param_name_key = $key; } $extra_types = []; if ($atomic_type->extra_types) { foreach ($atomic_type->extra_types as $extra_type) { $extra_type = self::replaceTemplateTypesWithStandins(new \Psalm\Type\Union([$extra_type]), $template_result, $codebase, $statements_analyzer, $input_type, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth + 1); if ($extra_type->isSingle()) { $extra_type = \array_values($extra_type->getAtomicTypes())[0]; if ($extra_type instanceof \Psalm\Type\Atomic\TNamedObject || $extra_type instanceof \Psalm\Type\Atomic\TTemplateParam || $extra_type instanceof \Psalm\Type\Atomic\TIterable || $extra_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { $extra_types[$extra_type->getKey()] = $extra_type; } } } } if ($replace) { $atomic_types = []; if ($replacement_type->hasMixed() && !$atomic_type->as->hasMixed()) { foreach ($atomic_type->as->getAtomicTypes() as $as_atomic_type) { $atomic_types[] = clone $as_atomic_type; } } else { if ($codebase) { $replacement_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $replacement_type, $calling_class, $calling_class, null); } if ($depth < 10) { $replacement_type = self::replaceTemplateTypesWithStandins($replacement_type, $template_result, $codebase, $statements_analyzer, $input_type, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth + 1); } foreach ($replacement_type->getAtomicTypes() as $replacement_atomic_type) { $replacements_found = \false; // @codingStandardsIgnoreStart if ($replacement_atomic_type instanceof \Psalm\Type\Atomic\TTemplateKeyOf && isset($template_result->template_types[$replacement_atomic_type->param_name][$replacement_atomic_type->defining_class][0])) { $keyed_template = $template_result->template_types[$replacement_atomic_type->param_name][$replacement_atomic_type->defining_class][0]; if ($keyed_template->isSingle()) { $keyed_template = \array_values($keyed_template->getAtomicTypes())[0]; } if ($keyed_template instanceof \Psalm\Type\Atomic\TKeyedArray || $keyed_template instanceof \Psalm\Type\Atomic\TArray || $keyed_template instanceof \Psalm\Type\Atomic\TList) { if ($keyed_template instanceof \Psalm\Type\Atomic\TKeyedArray) { $key_type = $keyed_template->getGenericKeyType(); } elseif ($keyed_template instanceof \Psalm\Type\Atomic\TList) { $key_type = \Psalm\Type::getInt(); } else { $key_type = $keyed_template->type_params[0]; } $replacements_found = \true; foreach ($key_type->getAtomicTypes() as $key_type_atomic) { $atomic_types[] = clone $key_type_atomic; } $template_result->upper_bounds[$atomic_type->param_name][$atomic_type->defining_class][0] = clone $key_type; } } if ($replacement_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam && $replacement_atomic_type->defining_class !== $calling_class && $replacement_atomic_type->defining_class !== 'fn-' . $calling_function) { foreach ($replacement_atomic_type->as->getAtomicTypes() as $nested_type_atomic) { $replacements_found = \true; $atomic_types[] = clone $nested_type_atomic; } } // @codingStandardsIgnoreEnd if (!$replacements_found) { $atomic_types[] = clone $replacement_atomic_type; } $had_template = \true; } } $matching_input_keys = []; if ($codebase) { $atomic_type->as = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $atomic_type->as, $calling_class, $calling_class, null); } $atomic_type->as = self::replaceTemplateTypesWithStandins($atomic_type->as, $template_result, $codebase, $statements_analyzer, $input_type, $input_arg_offset, $calling_class, $calling_function, $replace, $add_upper_bound, $depth + 1); if ($input_type && ($atomic_type->as->isMixed() || !$codebase || \Psalm\Internal\Type\Comparator\UnionTypeComparator::canBeContainedBy($codebase, $input_type, $atomic_type->as, \false, \false, $matching_input_keys))) { $generic_param = clone $input_type; if ($matching_input_keys) { $generic_param_keys = \array_keys($generic_param->getAtomicTypes()); foreach ($generic_param_keys as $atomic_key) { if (!isset($matching_input_keys[$atomic_key])) { $generic_param->removeType($atomic_key); } } } if ($was_nullable && $generic_param->isNullable() && !$generic_param->isNull()) { $generic_param->removeType('null'); } if ($add_upper_bound) { return \array_values($generic_param->getAtomicTypes()); } $generic_param->setFromDocblock(); if (isset($template_result->upper_bounds[$param_name_key][$atomic_type->defining_class][0])) { $existing_generic_param = $template_result->upper_bounds[$param_name_key][$atomic_type->defining_class]; $existing_depth = $existing_generic_param[1] ?? -1; $existing_arg_offset = $existing_generic_param[2] ?? $input_arg_offset; if ($existing_depth > $depth && $input_arg_offset === $existing_arg_offset) { return $atomic_types ?: [$atomic_type]; } if ($existing_depth === $depth || $input_arg_offset !== $existing_arg_offset) { $generic_param = \Psalm\Type::combineUnionTypes($template_result->upper_bounds[$param_name_key][$atomic_type->defining_class][0], $generic_param, $codebase); } } $template_result->upper_bounds[$param_name_key][$atomic_type->defining_class] = [$generic_param, $depth, $input_arg_offset]; } foreach ($atomic_types as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject || $atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam || $atomic_type instanceof \Psalm\Type\Atomic\TIterable || $atomic_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { $atomic_type->extra_types = $extra_types; } } return $atomic_types; } if ($add_upper_bound && $input_type) { $matching_input_keys = []; if ($codebase && \Psalm\Internal\Type\Comparator\UnionTypeComparator::canBeContainedBy($codebase, $input_type, $replacement_type, \false, \false, $matching_input_keys)) { $generic_param = clone $input_type; if ($matching_input_keys) { $generic_param_keys = \array_keys($generic_param->getAtomicTypes()); foreach ($generic_param_keys as $atomic_key) { if (!isset($matching_input_keys[$atomic_key])) { $generic_param->removeType($atomic_key); } } } if (isset($template_result->lower_bounds[$param_name_key][$atomic_type->defining_class][0])) { if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $template_result->lower_bounds[$param_name_key][$atomic_type->defining_class][0], $generic_param) || !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $generic_param, $template_result->lower_bounds[$param_name_key][$atomic_type->defining_class][0])) { $intersection_type = \Psalm\Type::intersectUnionTypes($template_result->lower_bounds[$param_name_key][$atomic_type->defining_class][0], $generic_param, $codebase); } else { $intersection_type = $generic_param; } if ($intersection_type) { $template_result->lower_bounds[$param_name_key][$atomic_type->defining_class][0] = $intersection_type; } else { $template_result->lower_bounds_unintersectable_types[] = $template_result->lower_bounds[$param_name_key][$atomic_type->defining_class][0]; $template_result->lower_bounds_unintersectable_types[] = $generic_param; $template_result->lower_bounds[$param_name_key][$atomic_type->defining_class][0] = \Psalm\Type::getMixed(); } } else { $template_result->lower_bounds[$param_name_key][$atomic_type->defining_class][0] = $generic_param; } } } return [$atomic_type]; } /** * @return non-empty-list */ public static function handleTemplateParamClassStandin(\Psalm\Type\Atomic\TTemplateParamClass $atomic_type, ?\Psalm\Type\Union $input_type, ?int $input_arg_offset, \Psalm\Internal\Type\TemplateResult $template_result, int $depth, bool $was_single) : array { $class_string = new \Psalm\Type\Atomic\TClassString($atomic_type->as, $atomic_type->as_type); $atomic_types = []; $atomic_types[] = $class_string; if ($input_type) { $valid_input_atomic_types = []; foreach ($input_type->getAtomicTypes() as $input_atomic_type) { if ($input_atomic_type instanceof \Psalm\Type\Atomic\TLiteralClassString) { $valid_input_atomic_types[] = new \Psalm\Type\Atomic\TNamedObject($input_atomic_type->value); } elseif ($input_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $valid_input_atomic_types[] = new \Psalm\Type\Atomic\TTemplateParam($input_atomic_type->param_name, $input_atomic_type->as_type ? new \Psalm\Type\Union([$input_atomic_type->as_type]) : ($input_atomic_type->as === 'object' ? \Psalm\Type::getObject() : \Psalm\Type::getMixed()), $input_atomic_type->defining_class); } elseif ($input_atomic_type instanceof \Psalm\Type\Atomic\TClassString) { if ($input_atomic_type->as_type) { $valid_input_atomic_types[] = clone $input_atomic_type->as_type; } elseif ($input_atomic_type->as !== 'object') { $valid_input_atomic_types[] = new \Psalm\Type\Atomic\TNamedObject($input_atomic_type->as); } else { $valid_input_atomic_types[] = new \Psalm\Type\Atomic\TObject(); } } elseif ($input_atomic_type instanceof \Psalm\Type\Atomic\TDependentGetClass) { $valid_input_atomic_types[] = new \Psalm\Type\Atomic\TObject(); } } $generic_param = null; if ($valid_input_atomic_types) { $generic_param = new \Psalm\Type\Union($valid_input_atomic_types); $generic_param->setFromDocblock(); } elseif ($was_single) { $generic_param = \Psalm\Type::getMixed(); } if ($generic_param) { if (isset($template_result->upper_bounds[$atomic_type->param_name][$atomic_type->defining_class])) { $template_result->upper_bounds[$atomic_type->param_name][$atomic_type->defining_class] = [\Psalm\Type::combineUnionTypes($generic_param, $template_result->upper_bounds[$atomic_type->param_name][$atomic_type->defining_class][0]), $depth]; } else { $template_result->upper_bounds[$atomic_type->param_name][$atomic_type->defining_class] = [$generic_param, $depth, $input_arg_offset]; } } } return $atomic_types; } /** * @param array> $template_types * * @return array{Union, 1?:int}|null */ public static function getRootTemplateType(array $template_types, string $param_name, string $defining_class, array $visited_classes = []) : ?array { if (isset($visited_classes[$defining_class])) { return null; } if (isset($template_types[$param_name][$defining_class])) { $mapped_type = $template_types[$param_name][$defining_class][0]; $mapped_type_atomic_types = \array_values($mapped_type->getAtomicTypes()); if (\count($mapped_type_atomic_types) > 1 || !$mapped_type_atomic_types[0] instanceof \Psalm\Type\Atomic\TTemplateParam) { return $template_types[$param_name][$defining_class]; } $first_template = $mapped_type_atomic_types[0]; return self::getRootTemplateType($template_types, $first_template->param_name, $first_template->defining_class, $visited_classes + [$defining_class => \true]) ?? $template_types[$param_name][$defining_class]; } return null; } /** * @param Atomic\TGenericObject|Atomic\TIterable $input_type_part * @param Atomic\TGenericObject|Atomic\TIterable $container_type_part * @return list */ public static function getMappedGenericTypeParams(\Psalm\Codebase $codebase, \Psalm\Type\Atomic $input_type_part, \Psalm\Type\Atomic $container_type_part, ?array &$container_type_params_covariant = null) : array { $input_type_params = $input_type_part->type_params; try { $input_class_storage = $codebase->classlike_storage_provider->get($input_type_part->value); $container_class_storage = $codebase->classlike_storage_provider->get($container_type_part->value); $container_type_params_covariant = $container_class_storage->template_covariants; } catch (\Throwable $e) { $input_class_storage = null; } if ($input_type_part->value !== $container_type_part->value && $input_class_storage) { $input_template_types = $input_class_storage->template_types; $i = 0; $replacement_templates = []; if ($input_template_types && (!$input_type_part instanceof \Psalm\Type\Atomic\TGenericObject || !$input_type_part->remapped_params) && (!$container_type_part instanceof \Psalm\Type\Atomic\TGenericObject || !$container_type_part->remapped_params)) { foreach ($input_template_types as $template_name => $_) { if (!isset($input_type_params[$i])) { break; } $replacement_templates[$template_name][$input_type_part->value] = [$input_type_params[$i]]; $i++; } } $template_extends = $input_class_storage->template_type_extends; if (isset($template_extends[$container_type_part->value])) { $params = $template_extends[$container_type_part->value]; $new_input_params = []; foreach ($params as $key => $extended_input_param_type) { if (\is_string($key)) { $new_input_param = null; foreach ($extended_input_param_type->getAtomicTypes() as $et) { if ($et instanceof \Psalm\Type\Atomic\TTemplateParam) { $ets = \Psalm\Internal\Codebase\Methods::getExtendedTemplatedTypes($et, $template_extends); } else { $ets = []; } if ($ets && $ets[0] instanceof \Psalm\Type\Atomic\TTemplateParam && isset($input_class_storage->template_types[$ets[0]->param_name][$ets[0]->defining_class])) { $old_params_offset = (int) \array_search($ets[0]->param_name, \array_keys($input_class_storage->template_types)); if (!isset($input_type_params[$old_params_offset])) { $candidate_param_type = \Psalm\Type::getMixed(); } else { $candidate_param_type = $input_type_params[$old_params_offset]; } } else { $candidate_param_type = new \Psalm\Type\Union([clone $et]); } $candidate_param_type->from_template_default = \true; if (!$new_input_param) { $new_input_param = $candidate_param_type; } else { $new_input_param = \Psalm\Type::combineUnionTypes($new_input_param, $candidate_param_type); } } $new_input_param = clone $new_input_param; $new_input_param->replaceTemplateTypesWithArgTypes(new \Psalm\Internal\Type\TemplateResult([], $replacement_templates), $codebase); $new_input_params[] = $new_input_param; } } $input_type_params = $new_input_params; } } return $input_type_params; } } $type_tokens * @param array{int,int}|null $php_version * @param array> $template_type_map * @param array $type_aliases * */ public static function parseTokens(array $type_tokens, ?array $php_version = null, array $template_type_map = [], array $type_aliases = []) : \Psalm\Type\Union { if (\count($type_tokens) === 1) { $only_token = $type_tokens[0]; // Note: valid identifiers can include class names or $this if (!\preg_match('@^(\\$this|\\\\?[a-zA-Z_\\x7f-\\xff][\\\\\\-0-9a-zA-Z_\\x7f-\\xff]*)$@', $only_token[0])) { if (!\is_numeric($only_token[0]) && \strpos($only_token[0], '\'') !== \false && \strpos($only_token[0], '"') !== \false) { throw new \Psalm\Exception\TypeParseTreeException("Invalid type '{$only_token[0]}'"); } } else { $only_token[0] = \Psalm\Internal\Type\TypeTokenizer::fixScalarTerms($only_token[0], $php_version); $atomic = \Psalm\Type\Atomic::create($only_token[0], $php_version, $template_type_map, $type_aliases); $atomic->offset_start = 0; $atomic->offset_end = \strlen($only_token[0]); return new \Psalm\Type\Union([$atomic]); } } $parse_tree = (new \Psalm\Internal\Type\ParseTreeCreator($type_tokens))->create(); $codebase = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance()->getCodebase(); $parsed_type = self::getTypeFromTree($parse_tree, $codebase, $php_version, $template_type_map, $type_aliases); if (!$parsed_type instanceof \Psalm\Type\Union) { $parsed_type = new \Psalm\Type\Union([$parsed_type]); } return $parsed_type; } /** * @param array{int,int}|null $php_version * @param array> $template_type_map * @param array $type_aliases * * @return Atomic|Union */ public static function getTypeFromTree(\Psalm\Internal\Type\ParseTree $parse_tree, \Psalm\Codebase $codebase, ?array $php_version = null, array $template_type_map = [], array $type_aliases = []) : \Psalm\Type\TypeNode { if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\GenericTree) { $generic_type = $parse_tree->value; $generic_params = []; foreach ($parse_tree->children as $i => $child_tree) { $tree_type = self::getTypeFromTree($child_tree, $codebase, null, $template_type_map, $type_aliases); if ($generic_type === 'class-string-map' && $i === 0) { if ($tree_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $template_type_map[$tree_type->param_name] = ['class-string-map' => [$tree_type->as]]; } elseif ($tree_type instanceof \Psalm\Type\Atomic\TNamedObject) { $template_type_map[$tree_type->value] = ['class-string-map' => [\Psalm\Type::getObject()]]; } } $generic_params[] = $tree_type instanceof \Psalm\Type\Union ? $tree_type : new \Psalm\Type\Union([$tree_type]); } $generic_type_value = \Psalm\Internal\Type\TypeTokenizer::fixScalarTerms($generic_type); if (($generic_type_value === 'array' || $generic_type_value === 'non-empty-array' || $generic_type_value === 'associative-array') && \count($generic_params) === 1) { \array_unshift($generic_params, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArrayKey()])); } elseif (\count($generic_params) === 1 && \in_array($generic_type_value, ['iterable', 'Traversable', 'Iterator', 'IteratorAggregate', 'arraylike-object'], \true)) { \array_unshift($generic_params, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TMixed()])); } elseif ($generic_type_value === 'Generator') { if (\count($generic_params) === 1) { \array_unshift($generic_params, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TMixed()])); } for ($i = 0, $l = 4 - \count($generic_params); $i < $l; ++$i) { $generic_params[] = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TMixed()]); } } if (!$generic_params) { throw new \Psalm\Exception\TypeParseTreeException('No generic params provided for type'); } if ($generic_type_value === 'array' || $generic_type_value === 'associative-array') { if ($generic_params[0]->isMixed()) { $generic_params[0] = \Psalm\Type::getArrayKey(); } return new \Psalm\Type\Atomic\TArray($generic_params); } if ($generic_type_value === 'arraylike-object') { $traversable = new \Psalm\Type\Atomic\TGenericObject('Traversable', $generic_params); $array_acccess = new \Psalm\Type\Atomic\TGenericObject('ArrayAccess', $generic_params); $traversable->extra_types[$array_acccess->getKey()] = $array_acccess; return $traversable; } if ($generic_type_value === 'non-empty-array') { if ($generic_params[0]->isMixed()) { $generic_params[0] = \Psalm\Type::getArrayKey(); } return new \Psalm\Type\Atomic\TNonEmptyArray($generic_params); } if ($generic_type_value === 'iterable') { return new \Psalm\Type\Atomic\TIterable($generic_params); } if ($generic_type_value === 'list') { return new \Psalm\Type\Atomic\TList($generic_params[0]); } if ($generic_type_value === 'non-empty-list') { return new \Psalm\Type\Atomic\TNonEmptyList($generic_params[0]); } if ($generic_type_value === 'class-string') { $class_name = (string) $generic_params[0]; if (isset($template_type_map[$class_name])) { $first_class = \array_keys($template_type_map[$class_name])[0]; return self::getGenericParamClass($class_name, $template_type_map[$class_name][$first_class][0], $first_class); } $param_union_types = \array_values($generic_params[0]->getAtomicTypes()); if (\count($param_union_types) > 1) { throw new \Psalm\Exception\TypeParseTreeException('Union types are not allowed in class string param'); } if (!$param_union_types[0] instanceof \Psalm\Type\Atomic\TNamedObject) { throw new \Psalm\Exception\TypeParseTreeException('Class string param should be a named object'); } return new \Psalm\Type\Atomic\TClassString($class_name, $param_union_types[0]); } if ($generic_type_value === 'class-string-map') { if (\count($generic_params) !== 2) { throw new \Psalm\Exception\TypeParseTreeException('There should only be two params for class-string-map, ' . \count($generic_params) . ' provided'); } $template_marker_parts = \array_values($generic_params[0]->getAtomicTypes()); $template_marker = $template_marker_parts[0]; $template_as_type = null; if ($template_marker instanceof \Psalm\Type\Atomic\TNamedObject) { $template_param_name = $template_marker->value; } elseif ($template_marker instanceof \Psalm\Type\Atomic\TTemplateParam) { $template_param_name = $template_marker->param_name; $template_as_type = \array_values($template_marker->as->getAtomicTypes())[0]; if (!$template_as_type instanceof \Psalm\Type\Atomic\TNamedObject) { throw new \Psalm\Exception\TypeParseTreeException('Unrecognised as type'); } } else { throw new \Psalm\Exception\TypeParseTreeException('Unrecognised class-string-map templated param'); } return new \Psalm\Type\Atomic\TClassStringMap($template_param_name, $template_as_type, $generic_params[1]); } if ($generic_type_value === 'key-of') { $param_name = (string) $generic_params[0]; if (isset($template_type_map[$param_name])) { $defining_class = \array_keys($template_type_map[$param_name])[0]; return new \Psalm\Type\Atomic\TTemplateKeyOf($param_name, $defining_class, $template_type_map[$param_name][$defining_class][0]); } $param_union_types = \array_values($generic_params[0]->getAtomicTypes()); if (\count($param_union_types) > 1) { throw new \Psalm\Exception\TypeParseTreeException('Union types are not allowed in key-of type'); } if (!$param_union_types[0] instanceof \Psalm\Type\Atomic\TScalarClassConstant) { throw new \Psalm\Exception\TypeParseTreeException('Untemplated key-of param ' . $param_name . ' should be a class constant'); } return new \Psalm\Type\Atomic\TKeyOfClassConstant($param_union_types[0]->fq_classlike_name, $param_union_types[0]->const_name); } if ($generic_type_value === 'value-of') { $param_name = (string) $generic_params[0]; if (isset($template_type_map[$param_name])) { $defining_class = \array_keys($template_type_map[$param_name])[0]; return new \Psalm\Type\Atomic\TTemplateKeyOf($param_name, $defining_class, $template_type_map[$param_name][$defining_class][0]); } $param_union_types = \array_values($generic_params[0]->getAtomicTypes()); if (\count($param_union_types) > 1) { throw new \Psalm\Exception\TypeParseTreeException('Union types are not allowed in value-of type'); } if (!$param_union_types[0] instanceof \Psalm\Type\Atomic\TScalarClassConstant) { throw new \Psalm\Exception\TypeParseTreeException('Untemplated value-of param ' . $param_name . ' should be a class constant'); } return new \Psalm\Type\Atomic\TValueOfClassConstant($param_union_types[0]->fq_classlike_name, $param_union_types[0]->const_name); } if (isset(\Psalm\Internal\Type\TypeTokenizer::PSALM_RESERVED_WORDS[$generic_type_value]) && $generic_type_value !== 'self' && $generic_type_value !== 'static') { throw new \Psalm\Exception\TypeParseTreeException('Cannot create generic object with reserved word'); } return new \Psalm\Type\Atomic\TGenericObject($generic_type_value, $generic_params); } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\UnionTree) { $has_null = \false; $atomic_types = []; foreach ($parse_tree->children as $child_tree) { if ($child_tree instanceof \Psalm\Internal\Type\ParseTree\NullableTree) { if (!isset($child_tree->children[0])) { throw new \Psalm\Exception\TypeParseTreeException('Invalid ? character'); } $atomic_type = self::getTypeFromTree($child_tree->children[0], $codebase, null, $template_type_map, $type_aliases); $has_null = \true; } else { $atomic_type = self::getTypeFromTree($child_tree, $codebase, null, $template_type_map, $type_aliases); } if ($atomic_type instanceof \Psalm\Type\Union) { foreach ($atomic_type->getAtomicTypes() as $type) { $atomic_types[] = $type; } continue; } $atomic_types[] = $atomic_type; } if ($has_null) { $atomic_types[] = new \Psalm\Type\Atomic\TNull(); } if (!$atomic_types) { throw new \Psalm\Exception\TypeParseTreeException('No atomic types found'); } return \Psalm\Internal\Type\TypeCombination::combineTypes($atomic_types); } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\IntersectionTree) { $intersection_types = \array_map( /** * @return Atomic */ function (\Psalm\Internal\Type\ParseTree $child_tree) use($codebase, $template_type_map, $type_aliases) { $atomic_type = self::getTypeFromTree($child_tree, $codebase, null, $template_type_map, $type_aliases); if (!$atomic_type instanceof \Psalm\Type\Atomic) { throw new \Psalm\Exception\TypeParseTreeException('Intersection types cannot contain unions'); } return $atomic_type; }, $parse_tree->children ); $first_type = \reset($intersection_types); $last_type = \end($intersection_types); $onlyTKeyedArray = $first_type instanceof \Psalm\Type\Atomic\TKeyedArray || $last_type instanceof \Psalm\Type\Atomic\TKeyedArray; foreach ($intersection_types as $intersection_type) { if (!$intersection_type instanceof \Psalm\Type\Atomic\TKeyedArray && ($intersection_type !== $first_type || !$first_type instanceof \Psalm\Type\Atomic\TArray) && ($intersection_type !== $last_type || !$last_type instanceof \Psalm\Type\Atomic\TArray)) { $onlyTKeyedArray = \false; break; } } if ($onlyTKeyedArray) { /** @var non-empty-array */ $properties = []; if ($first_type instanceof \Psalm\Type\Atomic\TArray) { \array_shift($intersection_types); } elseif ($last_type instanceof \Psalm\Type\Atomic\TArray) { \array_pop($intersection_types); } /** @var TKeyedArray $intersection_type */ foreach ($intersection_types as $intersection_type) { foreach ($intersection_type->properties as $property => $property_type) { if (!\array_key_exists($property, $properties)) { $properties[$property] = clone $property_type; continue; } $intersection_type = \Psalm\Type::intersectUnionTypes($properties[$property], $property_type, $codebase); if ($intersection_type === null) { throw new \Psalm\Exception\TypeParseTreeException('Incompatible intersection types for "' . $property . '", ' . $properties[$property] . ' and ' . $property_type . ' provided'); } $properties[$property] = $intersection_type; } } $keyed_array = new \Psalm\Type\Atomic\TKeyedArray($properties); if ($first_type instanceof \Psalm\Type\Atomic\TArray) { $keyed_array->previous_key_type = $first_type->type_params[0]; $keyed_array->previous_value_type = $first_type->type_params[1]; } elseif ($last_type instanceof \Psalm\Type\Atomic\TArray) { $keyed_array->previous_key_type = $last_type->type_params[0]; $keyed_array->previous_value_type = $last_type->type_params[1]; } return $keyed_array; } $keyed_intersection_types = []; if ($intersection_types[0] instanceof \Psalm\Type\Atomic\TTypeAlias) { foreach ($intersection_types as $intersection_type) { if (!$intersection_type instanceof \Psalm\Type\Atomic\TTypeAlias) { throw new \Psalm\Exception\TypeParseTreeException('Intersection types with a type alias can only be comprised of other type aliases, ' . \get_class($intersection_type) . ' provided'); } $keyed_intersection_types[$intersection_type->getKey()] = $intersection_type; } $first_type = \array_shift($keyed_intersection_types); if ($keyed_intersection_types) { $first_type->extra_types = $keyed_intersection_types; } } else { foreach ($intersection_types as $intersection_type) { if (!$intersection_type instanceof \Psalm\Type\Atomic\TIterable && !$intersection_type instanceof \Psalm\Type\Atomic\TNamedObject && !$intersection_type instanceof \Psalm\Type\Atomic\TTemplateParam && !$intersection_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { throw new \Psalm\Exception\TypeParseTreeException('Intersection types must be all objects or all object-like arrays, ' . \get_class($intersection_type) . ' provided'); } $keyed_intersection_types[$intersection_type instanceof \Psalm\Type\Atomic\TIterable ? $intersection_type->getId() : $intersection_type->getKey()] = $intersection_type; } $intersect_static = \false; if (isset($keyed_intersection_types['static'])) { unset($keyed_intersection_types['static']); $intersect_static = \true; } if (!$keyed_intersection_types && $intersect_static) { return new \Psalm\Type\Atomic\TNamedObject('static'); } $first_type = \array_shift($keyed_intersection_types); if ($intersect_static && $first_type instanceof \Psalm\Type\Atomic\TNamedObject) { $first_type->was_static = \true; } if ($keyed_intersection_types) { $first_type->extra_types = $keyed_intersection_types; } } return $first_type; } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayTree) { $properties = []; $type = $parse_tree->value; $is_tuple = \true; foreach ($parse_tree->children as $i => $property_branch) { if (!$property_branch instanceof \Psalm\Internal\Type\ParseTree\KeyedArrayPropertyTree) { $property_type = self::getTypeFromTree($property_branch, $codebase, null, $template_type_map, $type_aliases); $property_maybe_undefined = \false; $property_key = (string) $i; } elseif (\count($property_branch->children) === 1) { $property_type = self::getTypeFromTree($property_branch->children[0], $codebase, null, $template_type_map, $type_aliases); $property_maybe_undefined = $property_branch->possibly_undefined; $property_key = $property_branch->value; $is_tuple = \false; } else { throw new \Psalm\Exception\TypeParseTreeException('Missing property type'); } if ($property_key[0] === '\'' || $property_key[0] === '"') { $property_key = \stripslashes(\substr($property_key, 1, -1)); } if (!$property_type instanceof \Psalm\Type\Union) { $property_type = new \Psalm\Type\Union([$property_type]); } if ($property_maybe_undefined) { $property_type->possibly_undefined = \true; } $properties[$property_key] = $property_type; } if ($type !== 'array' && $type !== 'object' && $type !== 'callable-array') { throw new \Psalm\Exception\TypeParseTreeException('Unexpected brace character'); } if (!$properties) { throw new \Psalm\Exception\TypeParseTreeException('No properties supplied for TKeyedArray'); } if ($type === 'object') { return new \Psalm\Type\Atomic\TObjectWithProperties($properties); } if ($type === 'callable-array') { return new \Psalm\Type\Atomic\TCallableKeyedArray($properties); } $object_like = new \Psalm\Type\Atomic\TKeyedArray($properties); if ($is_tuple) { $object_like->sealed = \true; $object_like->is_list = \true; } return $object_like; } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\CallableWithReturnTypeTree) { $callable_type = self::getTypeFromTree($parse_tree->children[0], $codebase, null, $template_type_map, $type_aliases); if (!$callable_type instanceof \Psalm\Type\Atomic\TCallable && !$callable_type instanceof \Psalm\Type\Atomic\TClosure) { throw new \InvalidArgumentException('Parsing callable tree node should return TCallable'); } if (!isset($parse_tree->children[1])) { throw new \Psalm\Exception\TypeParseTreeException('Invalid return type'); } $return_type = self::getTypeFromTree($parse_tree->children[1], $codebase, null, $template_type_map, $type_aliases); $callable_type->return_type = $return_type instanceof \Psalm\Type\Union ? $return_type : new \Psalm\Type\Union([$return_type]); return $callable_type; } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\CallableTree) { $params = \array_map( /** * @return FunctionLikeParameter */ function (\Psalm\Internal\Type\ParseTree $child_tree) use($codebase, $template_type_map, $type_aliases) : FunctionLikeParameter { $is_variadic = \false; $is_optional = \false; if ($child_tree instanceof \Psalm\Internal\Type\ParseTree\CallableParamTree) { if (isset($child_tree->children[0])) { $tree_type = self::getTypeFromTree($child_tree->children[0], $codebase, null, $template_type_map, $type_aliases); } else { $tree_type = new \Psalm\Type\Atomic\TMixed(); } $is_variadic = $child_tree->variadic; $is_optional = $child_tree->has_default; } else { if ($child_tree instanceof \Psalm\Internal\Type\ParseTree\Value && \strpos($child_tree->value, '$') > 0) { $child_tree->value = \preg_replace('/(.+)\\$.*/', '$1', $child_tree->value); } $tree_type = self::getTypeFromTree($child_tree, $codebase, null, $template_type_map, $type_aliases); } $tree_type = $tree_type instanceof \Psalm\Type\Union ? $tree_type : new \Psalm\Type\Union([$tree_type]); $param = new \Psalm\Storage\FunctionLikeParameter('', \false, $tree_type, null, null, $is_optional, \false, $is_variadic); // type is not authoratative $param->signature_type = null; return $param; }, $parse_tree->children ); $pure = \strpos($parse_tree->value, 'pure-') === 0 ? \true : null; if (\in_array(\strtolower($parse_tree->value), ['closure', '\\closure'], \true)) { return new \Psalm\Type\Atomic\TClosure('Closure', $params, null, $pure); } return new \Psalm\Type\Atomic\TCallable('callable', $params, null, $pure); } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\EncapsulationTree) { return self::getTypeFromTree($parse_tree->children[0], $codebase, null, $template_type_map, $type_aliases); } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\NullableTree) { if (!isset($parse_tree->children[0])) { throw new \Psalm\Exception\TypeParseTreeException('Misplaced question mark'); } $non_nullable_type = self::getTypeFromTree($parse_tree->children[0], $codebase, null, $template_type_map, $type_aliases); if ($non_nullable_type instanceof \Psalm\Type\Union) { $non_nullable_type->addType(new \Psalm\Type\Atomic\TNull()); return $non_nullable_type; } return \Psalm\Internal\Type\TypeCombination::combineTypes([new \Psalm\Type\Atomic\TNull(), $non_nullable_type]); } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\MethodTree || $parse_tree instanceof \Psalm\Internal\Type\ParseTree\MethodWithReturnTypeTree) { throw new \Psalm\Exception\TypeParseTreeException('Misplaced brackets'); } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\IndexedAccessTree) { if (!isset($parse_tree->children[0]) || !$parse_tree->children[0] instanceof \Psalm\Internal\Type\ParseTree\Value) { throw new \Psalm\Exception\TypeParseTreeException('Unrecognised indexed access'); } $offset_param_name = $parse_tree->value; $array_param_name = $parse_tree->children[0]->value; if (!isset($template_type_map[$offset_param_name])) { throw new \Psalm\Exception\TypeParseTreeException('Unrecognised template param ' . $offset_param_name); } if (!isset($template_type_map[$array_param_name])) { throw new \Psalm\Exception\TypeParseTreeException('Unrecognised template param ' . $array_param_name); } $offset_template_data = $template_type_map[$offset_param_name]; $offset_defining_class = \array_keys($offset_template_data)[0]; if (!$offset_defining_class && isset($offset_template_data['']) && $offset_template_data[''][0]->isSingle()) { $offset_template_type = \array_values($offset_template_data[''][0]->getAtomicTypes())[0]; if ($offset_template_type instanceof \Psalm\Type\Atomic\TTemplateKeyOf) { $offset_defining_class = (string) $offset_template_type->defining_class; } } $array_defining_class = \array_keys($template_type_map[$array_param_name])[0]; if ($offset_defining_class !== $array_defining_class && \substr($offset_defining_class, 0, 3) !== 'fn-') { throw new \Psalm\Exception\TypeParseTreeException('Template params are defined in different locations'); } return new \Psalm\Type\Atomic\TTemplateIndexedAccess($array_param_name, $offset_param_name, $array_defining_class); } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\TemplateAsTree) { return new \Psalm\Type\Atomic\TTemplateParam($parse_tree->param_name, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($parse_tree->as)]), 'class-string-map'); } if ($parse_tree instanceof \Psalm\Internal\Type\ParseTree\ConditionalTree) { $template_param_name = $parse_tree->condition->param_name; if (!isset($template_type_map[$template_param_name])) { throw new \Psalm\Exception\TypeParseTreeException('Unrecognized template \'' . $template_param_name . '\''); } if (\count($parse_tree->children) !== 2) { throw new \Psalm\Exception\TypeParseTreeException('Invalid conditional'); } $first_class = \array_keys($template_type_map[$template_param_name])[0]; $conditional_type = self::getTypeFromTree($parse_tree->condition->children[0], $codebase, null, $template_type_map, $type_aliases); $if_type = self::getTypeFromTree($parse_tree->children[0], $codebase, null, $template_type_map, $type_aliases); $else_type = self::getTypeFromTree($parse_tree->children[1], $codebase, null, $template_type_map, $type_aliases); if ($conditional_type instanceof \Psalm\Type\Atomic) { $conditional_type = new \Psalm\Type\Union([$conditional_type]); } if ($if_type instanceof \Psalm\Type\Atomic) { $if_type = new \Psalm\Type\Union([$if_type]); } if ($else_type instanceof \Psalm\Type\Atomic) { $else_type = new \Psalm\Type\Union([$else_type]); } return new \Psalm\Type\Atomic\TConditional($template_param_name, $first_class, $template_type_map[$template_param_name][$first_class][0], $conditional_type, $if_type, $else_type); } if (!$parse_tree instanceof \Psalm\Internal\Type\ParseTree\Value) { throw new \InvalidArgumentException('Unrecognised parse tree type ' . \get_class($parse_tree)); } if ($parse_tree->value[0] === '"' || $parse_tree->value[0] === '\'') { return new \Psalm\Type\Atomic\TLiteralString(\substr($parse_tree->value, 1, -1)); } if (\strpos($parse_tree->value, '::')) { [$fq_classlike_name, $const_name] = \explode('::', $parse_tree->value); if (isset($template_type_map[$fq_classlike_name]) && $const_name === 'class') { $first_class = \array_keys($template_type_map[$fq_classlike_name])[0]; return self::getGenericParamClass($fq_classlike_name, $template_type_map[$fq_classlike_name][$first_class][0], $first_class); } if ($const_name === 'class') { return new \Psalm\Type\Atomic\TLiteralClassString($fq_classlike_name); } return new \Psalm\Type\Atomic\TScalarClassConstant($fq_classlike_name, $const_name); } if (\preg_match('/^\\-?(0|[1-9][0-9]*)(\\.[0-9]{1,})$/', $parse_tree->value)) { return new \Psalm\Type\Atomic\TLiteralFloat((float) $parse_tree->value); } if (\preg_match('/^\\-?(0|[1-9][0-9]*)$/', $parse_tree->value)) { return new \Psalm\Type\Atomic\TLiteralInt((int) $parse_tree->value); } if (!\preg_match('@^(\\$this|\\\\?[a-zA-Z_\\x7f-\\xff][\\\\\\-0-9a-zA-Z_\\x7f-\\xff]*)$@', $parse_tree->value)) { throw new \Psalm\Exception\TypeParseTreeException('Invalid type \'' . $parse_tree->value . '\''); } $atomic_type_string = \Psalm\Internal\Type\TypeTokenizer::fixScalarTerms($parse_tree->value, $php_version); $atomic_type = \Psalm\Type\Atomic::create($atomic_type_string, $php_version, $template_type_map, $type_aliases); $atomic_type->offset_start = $parse_tree->offset_start; $atomic_type->offset_end = $parse_tree->offset_end; return $atomic_type; } private static function getGenericParamClass(string $param_name, \Psalm\Type\Union $as, string $defining_class) : \Psalm\Type\Atomic\TTemplateParamClass { if ($as->hasMixed()) { return new \Psalm\Type\Atomic\TTemplateParamClass($param_name, 'object', null, $defining_class); } if (!$as->isSingle()) { throw new \Psalm\Exception\TypeParseTreeException('Invalid templated classname \'' . $as . '\''); } foreach ($as->getAtomicTypes() as $t) { if ($t instanceof \Psalm\Type\Atomic\TObject) { return new \Psalm\Type\Atomic\TTemplateParamClass($param_name, 'object', null, $defining_class); } if ($t instanceof \Psalm\Type\Atomic\TIterable) { $traversable = new \Psalm\Type\Atomic\TGenericObject('Traversable', $t->type_params); $as->substitute(new \Psalm\Type\Union([$t]), new \Psalm\Type\Union([$traversable])); return new \Psalm\Type\Atomic\TTemplateParamClass($param_name, $traversable->value, $traversable, $defining_class); } if ($t instanceof \Psalm\Type\Atomic\TTemplateParam) { $t_atomic_types = $t->as->getAtomicTypes(); $t_atomic_type = \count($t_atomic_types) === 1 ? \reset($t_atomic_types) : null; if (!$t_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $t_atomic_type = null; } return new \Psalm\Type\Atomic\TTemplateParamClass($t->param_name, $t_atomic_type ? $t_atomic_type->value : 'object', $t_atomic_type, $t->defining_class); } if (!$t instanceof \Psalm\Type\Atomic\TNamedObject) { throw new \Psalm\Exception\TypeParseTreeException('Invalid templated classname \'' . $t->getId() . '\''); } return new \Psalm\Type\Atomic\TTemplateParamClass($param_name, $t->value, $t, $defining_class); } throw new \LogicException('Should never get here'); } } value === $input_type_part->value; } if ($container_type_part instanceof \Psalm\Type\Atomic\TTemplateParamClass && \get_class($input_type_part) === \Psalm\Type\Atomic\TClassString::class) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TClassString && $container_type_part->as === 'object' && !$container_type_part->as_type) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TClassString && $input_type_part->as === 'object' && !$input_type_part->as_type) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_scalar = \true; } return \false; } $fake_container_object = $container_type_part instanceof \Psalm\Type\Atomic\TClassString && $container_type_part->as_type ? $container_type_part->as_type : new \Psalm\Type\Atomic\TNamedObject($container_type_part instanceof \Psalm\Type\Atomic\TClassString ? $container_type_part->as : $container_type_part->value); $fake_input_object = $input_type_part instanceof \Psalm\Type\Atomic\TClassString && $input_type_part->as_type ? $input_type_part->as_type : new \Psalm\Type\Atomic\TNamedObject($input_type_part instanceof \Psalm\Type\Atomic\TClassString ? $input_type_part->as : $input_type_part->value); return \Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $fake_input_object, $fake_container_object, $allow_interface_equality, \false, $atomic_comparison_result); } } extra_types && !$input_type_part instanceof \Psalm\Type\Atomic\TIterable) { $container_type_part = new \Psalm\Type\Atomic\TGenericObject('Traversable', $container_type_part->type_params); } if (!$input_type_part instanceof \Psalm\Type\Atomic\TGenericObject && !$input_type_part instanceof \Psalm\Type\Atomic\TIterable) { if ($input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classExists($input_type_part->value)) { $class_storage = $codebase->classlike_storage_provider->get($input_type_part->value); $container_class = $container_type_part->value; // attempt to transform it if (isset($class_storage->template_type_extends[$container_class])) { $extends_list = $class_storage->template_type_extends[$container_class]; $generic_params = []; foreach ($extends_list as $key => $value) { if (\is_string($key)) { $generic_params[] = $value; } } if (!$generic_params) { return \false; } $input_type_part = new \Psalm\Type\Atomic\TGenericObject($input_type_part->value, $generic_params); } } if (!$input_type_part instanceof \Psalm\Type\Atomic\TGenericObject) { if ($input_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $input_type_part = new \Psalm\Type\Atomic\TGenericObject($input_type_part->value, \array_fill(0, \count($container_type_part->type_params), \Psalm\Type::getMixed())); } else { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_mixed = \true; } return \false; } } } $container_type_params_covariant = []; $input_type_params = \Psalm\Internal\Type\UnionTemplateHandler::getMappedGenericTypeParams($codebase, $input_type_part, $container_type_part, $container_type_params_covariant); foreach ($input_type_params as $i => $input_param) { if (!isset($container_type_part->type_params[$i])) { break; } $container_param = $container_type_part->type_params[$i]; if ($input_param->isEmpty()) { if ($atomic_comparison_result) { if (!$atomic_comparison_result->replacement_atomic_type) { $atomic_comparison_result->replacement_atomic_type = clone $input_type_part; } if ($atomic_comparison_result->replacement_atomic_type instanceof \Psalm\Type\Atomic\TGenericObject) { /** @psalm-suppress PropertyTypeCoercion */ $atomic_comparison_result->replacement_atomic_type->type_params[$i] = clone $container_param; } } continue; } $param_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_param, $container_param, $input_param->ignore_nullable_issues, $input_param->ignore_falsable_issues, $param_comparison_result, $allow_interface_equality)) { if ($input_type_part->value === 'Generator' && $i === 2 && $param_comparison_result->type_coerced_from_mixed) { continue; } if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = $param_comparison_result->type_coerced === \true && $atomic_comparison_result->type_coerced !== \false; $atomic_comparison_result->type_coerced_from_mixed = $param_comparison_result->type_coerced_from_mixed === \true && $atomic_comparison_result->type_coerced_from_mixed !== \false; $atomic_comparison_result->type_coerced_from_as_mixed = $param_comparison_result->type_coerced_from_as_mixed === \true && $atomic_comparison_result->type_coerced_from_as_mixed !== \false; $atomic_comparison_result->to_string_cast = $param_comparison_result->to_string_cast === \true && $atomic_comparison_result->to_string_cast !== \false; $atomic_comparison_result->type_coerced_from_scalar = $param_comparison_result->type_coerced_from_scalar === \true && $atomic_comparison_result->type_coerced_from_scalar !== \false; $atomic_comparison_result->scalar_type_match_found = $param_comparison_result->scalar_type_match_found === \true && $atomic_comparison_result->scalar_type_match_found !== \false; } if (!$param_comparison_result->type_coerced_from_as_mixed) { $all_types_contain = \false; } } elseif (!$input_type_part instanceof \Psalm\Type\Atomic\TIterable && !$container_type_part instanceof \Psalm\Type\Atomic\TIterable && !$container_param->hasTemplate() && !$input_param->hasTemplate()) { if ($input_param->hasEmptyArray() || $input_param->hasLiteralValue()) { if ($atomic_comparison_result) { if (!$atomic_comparison_result->replacement_atomic_type) { $atomic_comparison_result->replacement_atomic_type = clone $input_type_part; } if ($atomic_comparison_result->replacement_atomic_type instanceof \Psalm\Type\Atomic\TGenericObject) { /** @psalm-suppress PropertyTypeCoercion */ $atomic_comparison_result->replacement_atomic_type->type_params[$i] = clone $container_param; } } } else { if (!($container_type_params_covariant[$i] ?? \false) && !$container_param->had_template) { // Make sure types are basically the same if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $container_param, $input_param, $container_param->ignore_nullable_issues, $container_param->ignore_falsable_issues, $param_comparison_result, $allow_interface_equality) || $param_comparison_result->type_coerced) { if ($container_param->hasFormerStaticObject() && $input_param->isFormerStaticObject() && \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_param, $container_param, $container_param->ignore_nullable_issues, $container_param->ignore_falsable_issues, $param_comparison_result, $allow_interface_equality)) { // do nothing } else { if ($container_param->hasMixed() || $container_param->isArrayKey()) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced_from_mixed = \true; } } else { $all_types_contain = \false; } if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \false; } } } } } } } if ($all_types_contain) { if ($atomic_comparison_result) { $atomic_comparison_result->to_string_cast = \false; } return \true; } return \false; } } is_pure && !$input_type_part->is_pure) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = $input_type_part->is_pure === null; } return \false; } if ($container_type_part->params !== null && $input_type_part->params === null) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_mixed = \true; } return \false; } if ($input_type_part->params !== null && $container_type_part->params !== null) { foreach ($input_type_part->params as $i => $input_param) { $container_param = null; if (isset($container_type_part->params[$i])) { $container_param = $container_type_part->params[$i]; } elseif ($container_type_part->params) { $last_param = \end($container_type_part->params); if ($last_param->is_variadic) { $container_param = $last_param; } } if (!$container_param) { if ($input_param->is_optional) { break; } return \false; } if ($container_param->type && !$container_param->type->hasMixed() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $container_param->type, $input_param->type ?: \Psalm\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) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_mixed = \true; } return \false; } $input_return = $input_type_part->return_type; if ($input_return->isVoid() && $container_type_part->return_type->isNullable()) { return \true; } if (!$container_type_part->return_type->isVoid() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_return, $container_type_part->return_type, \false, \false, $atomic_comparison_result)) { return \false; } } return \true; } public static function isNotExplicitlyCallableTypeCallable(\Psalm\Codebase $codebase, \Psalm\Type\Atomic $input_type_part, \Psalm\Type\Atomic\TCallable $container_type_part, ?\Psalm\Internal\Type\Comparator\TypeComparisonResult $atomic_comparison_result) : bool { if ($input_type_part instanceof \Psalm\Type\Atomic\TList) { if ($input_type_part->type_param->isMixed() || $input_type_part->type_param->hasScalar()) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced_from_mixed = \true; $atomic_comparison_result->type_coerced = \true; } return \false; } if (!$input_type_part->type_param->hasString()) { return \false; } if (!$input_type_part instanceof \Psalm\Type\Atomic\TCallableList) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced_from_mixed = \true; $atomic_comparison_result->type_coerced = \true; } return \false; } } if ($input_type_part instanceof \Psalm\Type\Atomic\TArray) { if ($input_type_part->type_params[1]->isMixed() || $input_type_part->type_params[1]->hasScalar()) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced_from_mixed = \true; $atomic_comparison_result->type_coerced = \true; } return \false; } if (!$input_type_part->type_params[1]->hasString()) { return \false; } if (!$input_type_part instanceof \Psalm\Type\Atomic\TCallableArray) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced_from_mixed = \true; $atomic_comparison_result->type_coerced = \true; } return \false; } } elseif ($input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $method_id = self::getCallableMethodIdFromTKeyedArray($input_type_part); if ($method_id === 'not-callable') { return \false; } if (!$method_id) { return \true; } try { $method_id = $codebase->methods->getDeclaringMethodId($method_id); if (!$method_id) { return \false; } $codebase->methods->getStorage($method_id); } catch (\Exception $e) { return \false; } } $input_callable = self::getCallableFromAtomic($codebase, $input_type_part, $container_type_part); if ($input_callable) { if (self::isContainedBy($codebase, $input_callable, $container_type_part, $atomic_comparison_result) === \false) { return \false; } } return \true; } /** * @return TCallable|TClosure|null */ public static function getCallableFromAtomic(\Psalm\Codebase $codebase, \Psalm\Type\Atomic $input_type_part, ?\Psalm\Type\Atomic\TCallable $container_type_part = null, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null) : ?\Psalm\Type\Atomic { if ($input_type_part instanceof \Psalm\Type\Atomic\TCallable || $input_type_part instanceof \Psalm\Type\Atomic\TClosure) { return $input_type_part; } if ($input_type_part instanceof \Psalm\Type\Atomic\TLiteralString && $input_type_part->value) { try { $function_storage = $codebase->functions->getStorage($statements_analyzer, \strtolower($input_type_part->value)); return new \Psalm\Type\Atomic\TCallable('callable', $function_storage->params, $function_storage->return_type, $function_storage->pure); } catch (\UnexpectedValueException $e) { if (\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($input_type_part->value)) { $args = []; $nodes = new \Psalm\Internal\Provider\NodeDataProvider(); if ($container_type_part && $container_type_part->params) { foreach ($container_type_part->params as $i => $param) { $arg = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable('_' . $i)); if ($param->type) { $nodes->setType($arg->value, $param->type); } $args[] = $arg; } } $matching_callable = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallableFromCallMapById($codebase, $input_type_part->value, $args, $nodes); $must_use = \false; $matching_callable->is_pure = $codebase->functions->isCallMapFunctionPure($codebase, $statements_analyzer ? $statements_analyzer->node_data : null, $input_type_part->value, null, $must_use); return $matching_callable; } } } elseif ($input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $method_id = self::getCallableMethodIdFromTKeyedArray($input_type_part); if ($method_id && $method_id !== 'not-callable') { try { $method_storage = $codebase->methods->getStorage($method_id); $method_fqcln = $method_id->fq_class_name; $converted_return_type = null; if ($method_storage->return_type) { $converted_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $method_storage->return_type, $method_fqcln, $method_fqcln, null); } return new \Psalm\Type\Atomic\TCallable('callable', $method_storage->params, $converted_return_type, $method_storage->pure); } catch (\UnexpectedValueException $e) { // do nothing } } } elseif ($input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $input_type_part->value === 'Closure') { return new \Psalm\Type\Atomic\TCallable(); } elseif ($input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classExists($input_type_part->value)) { $invoke_id = new \Psalm\Internal\MethodIdentifier($input_type_part->value, '__invoke'); if ($codebase->methods->methodExists($invoke_id)) { $declaring_method_id = $codebase->methods->getDeclaringMethodId($invoke_id); if ($declaring_method_id) { $method_storage = $codebase->methods->getStorage($declaring_method_id); $method_fqcln = $invoke_id->fq_class_name; $converted_return_type = null; if ($method_storage->return_type) { $converted_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $method_storage->return_type, $method_fqcln, $method_fqcln, null); } return new \Psalm\Type\Atomic\TCallable('callable', $method_storage->params, $converted_return_type, $method_storage->pure); } } } return null; } /** @return null|'not-callable'|\Psalm\Internal\MethodIdentifier */ public static function getCallableMethodIdFromTKeyedArray(\Psalm\Type\Atomic\TKeyedArray $input_type_part, ?\Psalm\Codebase $codebase = null, ?string $calling_method_id = null, ?string $file_name = null) { if (!isset($input_type_part->properties[0]) || !isset($input_type_part->properties[1])) { return 'not-callable'; } [$lhs, $rhs] = $input_type_part->properties; $rhs_low_info = $rhs->hasMixed() || $rhs->hasScalar(); if ($rhs_low_info || !$rhs->isSingleStringLiteral()) { if (!$rhs_low_info && !$rhs->hasString()) { return 'not-callable'; } if ($codebase && ($calling_method_id || $file_name)) { foreach ($lhs->getAtomicTypes() as $lhs_atomic_type) { if ($lhs_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $codebase->analyzer->addMixedMemberName(\strtolower($lhs_atomic_type->value) . '::', $calling_method_id ?: $file_name); } } } return null; } $method_name = $rhs->getSingleStringLiteral()->value; $class_name = null; if ($lhs->isSingleStringLiteral()) { $class_name = $lhs->getSingleStringLiteral()->value; if ($class_name[0] === '\\') { $class_name = \substr($class_name, 1); } } elseif ($lhs->isSingle()) { foreach ($lhs->getAtomicTypes() as $lhs_atomic_type) { if ($lhs_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $class_name = $lhs_atomic_type->value; } elseif ($lhs_atomic_type instanceof \Psalm\Type\Atomic\TClassString && $lhs_atomic_type->as) { $class_name = $lhs_atomic_type->as; } } } if ($class_name === 'self' || $class_name === 'static' || $class_name === 'parent') { return null; } if (!$class_name) { if ($codebase && ($calling_method_id || $file_name)) { $codebase->analyzer->addMixedMemberName(\strtolower($method_name), $calling_method_id ?: $file_name); } return null; } return new \Psalm\Internal\MethodIdentifier($class_name, \strtolower($method_name)); } } scalar_type_match_found = \true; } if ($input_type->possibly_undefined && !$input_type->possibly_undefined_from_try && !$container_type->possibly_undefined) { return \false; } if ($container_type->hasMixed() && !$container_type->isEmptyMixed()) { return \true; } $container_has_template = $container_type->hasTemplateOrStatic(); $input_atomic_types = \array_reverse($input_type->getAtomicTypes()); while ($input_type_part = \array_pop($input_atomic_types)) { if ($input_type_part instanceof \Psalm\Type\Atomic\TNull && $ignore_null) { continue; } if ($input_type_part instanceof \Psalm\Type\Atomic\TFalse && $ignore_false) { continue; } if ($input_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && !$container_has_template && !$input_type_part->extra_types) { $input_atomic_types = \array_merge($input_type_part->as->getAtomicTypes(), $input_atomic_types); continue; } $type_match_found = \false; $scalar_type_match_found = \false; $all_to_string_cast = \true; $all_type_coerced = null; $all_type_coerced_from_mixed = null; $all_type_coerced_from_as_mixed = null; $some_type_coerced = \false; $some_type_coerced_from_mixed = \false; if ($input_type_part instanceof \Psalm\Type\Atomic\TArrayKey && ($container_type->hasInt() && $container_type->hasString())) { continue; } foreach ($container_type->getAtomicTypes() as $container_type_part) { if ($ignore_null && $container_type_part instanceof \Psalm\Type\Atomic\TNull && !$input_type_part instanceof \Psalm\Type\Atomic\TNull) { continue; } if ($ignore_false && $container_type_part instanceof \Psalm\Type\Atomic\TFalse && !$input_type_part instanceof \Psalm\Type\Atomic\TFalse) { continue; } if ($union_comparison_result) { $atomic_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); } else { $atomic_comparison_result = null; } $is_atomic_contained_by = \Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, \true, $atomic_comparison_result); if ($input_type_part instanceof \Psalm\Type\Atomic\TMixed && $input_type->from_template_default && $input_type->from_docblock && $atomic_comparison_result && $atomic_comparison_result->type_coerced_from_mixed) { $atomic_comparison_result->type_coerced_from_as_mixed = \true; } if ($atomic_comparison_result) { if ($atomic_comparison_result->scalar_type_match_found !== null) { $scalar_type_match_found = $atomic_comparison_result->scalar_type_match_found; } if ($union_comparison_result && $atomic_comparison_result->type_coerced_from_scalar !== null) { $union_comparison_result->type_coerced_from_scalar = $atomic_comparison_result->type_coerced_from_scalar; } if ($is_atomic_contained_by && $union_comparison_result && $atomic_comparison_result->replacement_atomic_type) { if (!$union_comparison_result->replacement_union_type) { $union_comparison_result->replacement_union_type = clone $input_type; } $union_comparison_result->replacement_union_type->removeType($input_type->getKey()); $union_comparison_result->replacement_union_type->addType($atomic_comparison_result->replacement_atomic_type); } } if ($input_type_part instanceof \Psalm\Type\Atomic\TNumeric && $container_type->hasString() && $container_type->hasInt() && $container_type->hasFloat()) { $scalar_type_match_found = \false; $is_atomic_contained_by = \true; } if ($atomic_comparison_result) { if ($atomic_comparison_result->type_coerced) { $some_type_coerced = \true; } if ($atomic_comparison_result->type_coerced_from_mixed) { $some_type_coerced_from_mixed = \true; } if ($atomic_comparison_result->type_coerced !== \true || $all_type_coerced === \false) { $all_type_coerced = \false; } else { $all_type_coerced = \true; } if ($atomic_comparison_result->type_coerced_from_mixed !== \true || $all_type_coerced_from_mixed === \false) { $all_type_coerced_from_mixed = \false; } else { $all_type_coerced_from_mixed = \true; } if ($atomic_comparison_result->type_coerced_from_as_mixed !== \true || $all_type_coerced_from_as_mixed === \false) { $all_type_coerced_from_as_mixed = \false; } else { $all_type_coerced_from_as_mixed = \true; } } if ($is_atomic_contained_by) { $type_match_found = \true; if ($atomic_comparison_result) { if ($atomic_comparison_result->to_string_cast !== \true) { $all_to_string_cast = \false; } } $all_type_coerced_from_mixed = \false; $all_type_coerced_from_as_mixed = \false; $all_type_coerced = \false; } } if ($union_comparison_result) { // only set this flag if we're definite that the only // reason the type match has been found is because there // was a __toString cast if ($all_to_string_cast && $type_match_found) { $union_comparison_result->to_string_cast = \true; } if ($all_type_coerced) { $union_comparison_result->type_coerced = \true; } if ($all_type_coerced_from_mixed) { $union_comparison_result->type_coerced_from_mixed = \true; if ($input_type->from_template_default && $input_type->from_docblock || $all_type_coerced_from_as_mixed) { $union_comparison_result->type_coerced_from_as_mixed = \true; } } } if (!$type_match_found) { if ($union_comparison_result) { if ($some_type_coerced) { $union_comparison_result->type_coerced = \true; } if ($some_type_coerced_from_mixed) { $union_comparison_result->type_coerced_from_mixed = \true; if ($input_type->from_template_default && $input_type->from_docblock || $all_type_coerced_from_as_mixed) { $union_comparison_result->type_coerced_from_as_mixed = \true; } } if (!$scalar_type_match_found) { $union_comparison_result->scalar_type_match_found = \false; } } return \false; } } return \true; } /** * Used for comparing signature typehints, uses PHP's light contravariance rules * * */ public static function isContainedByInPhp(?\Psalm\Type\Union $input_type, \Psalm\Type\Union $container_type) : bool { if (!$input_type) { return \false; } if ($input_type->getId() === $container_type->getId()) { return \true; } if ($input_type->isNullable() && !$container_type->isNullable()) { return \false; } $input_type_not_null = clone $input_type; $input_type_not_null->removeType('null'); $container_type_not_null = clone $container_type; $container_type_not_null->removeType('null'); if ($input_type_not_null->getId() === $container_type_not_null->getId()) { return \true; } if ($input_type_not_null->hasArray() && $container_type_not_null->hasType('iterable')) { return \true; } return \false; } /** * Used for comparing docblock types to signature types before we know about all types * */ public static function isSimplyContainedBy(\Psalm\Type\Union $input_type, \Psalm\Type\Union $container_type) : bool { if ($input_type->getId() === $container_type->getId()) { return \true; } if ($input_type->isNullable() && !$container_type->isNullable()) { return \false; } $input_type_not_null = clone $input_type; $input_type_not_null->removeType('null'); $container_type_not_null = clone $container_type; $container_type_not_null->removeType('null'); foreach ($input_type->getAtomicTypes() as $input_key => $input_type_part) { foreach ($container_type->getAtomicTypes() as $container_key => $container_type_part) { if (\get_class($container_type_part) === \Psalm\Type\Atomic\TNamedObject::class && $input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $input_type_part->value === $container_type_part->value) { continue 2; } if ($input_key === $container_key) { continue 2; } } return \false; } return \true; } /** * Does the input param type match the given param type */ public static function canBeContainedBy(\Psalm\Codebase $codebase, \Psalm\Type\Union $input_type, \Psalm\Type\Union $container_type, bool $ignore_null = \false, bool $ignore_false = \false, array &$matching_input_keys = []) : bool { if ($container_type->hasMixed()) { return \true; } if ($input_type->possibly_undefined && !$container_type->possibly_undefined) { return \false; } foreach ($container_type->getAtomicTypes() as $container_type_part) { if ($container_type_part instanceof \Psalm\Type\Atomic\TNull && $ignore_null) { continue; } if ($container_type_part instanceof \Psalm\Type\Atomic\TFalse && $ignore_false) { continue; } foreach ($input_type->getAtomicTypes() as $input_type_part) { $atomic_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $is_atomic_contained_by = \Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, \false, \false, $atomic_comparison_result); if ($is_atomic_contained_by && !$atomic_comparison_result->to_string_cast || $atomic_comparison_result->type_coerced_from_mixed) { $matching_input_keys[$input_type_part->getKey()] = \true; } } } return !!$matching_input_keys; } /** * Can any part of the $type1 be equal to any part of $type2 * */ public static function canExpressionTypesBeIdentical(\Psalm\Codebase $codebase, \Psalm\Type\Union $type1, \Psalm\Type\Union $type2) : bool { if ($type1->hasMixed() || $type2->hasMixed()) { return \true; } if ($type1->isNullable() && $type2->isNullable()) { return \true; } foreach ($type1->getAtomicTypes() as $type1_part) { foreach ($type2->getAtomicTypes() as $type2_part) { $either_contains = \Psalm\Internal\Type\Comparator\AtomicTypeComparator::canBeIdentical($codebase, $type1_part, $type2_part); if ($either_contains) { return \true; } } } return \false; } } properties as $key => $container_property_type) { if (!isset($input_type_part->properties[$key])) { if (!$container_property_type->possibly_undefined) { $all_types_contain = \false; } continue; } $input_property_type = $input_type_part->properties[$key]; $property_type_comparison = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!$input_property_type->isEmpty() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_property_type, $container_property_type, $input_property_type->ignore_nullable_issues, $input_property_type->ignore_falsable_issues, $property_type_comparison, $allow_interface_equality) && !$property_type_comparison->type_coerced_from_scalar) { $inverse_property_type_comparison = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if ($atomic_comparison_result) { if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $container_property_type, $input_property_type, \false, \false, $inverse_property_type_comparison, $allow_interface_equality) || $inverse_property_type_comparison->type_coerced_from_scalar) { $atomic_comparison_result->type_coerced = \true; } } $all_types_contain = \false; } } if ($all_types_contain) { if ($atomic_comparison_result) { $atomic_comparison_result->to_string_cast = \false; } return \true; } return \false; } public static function isContainedByObjectWithProperties(\Psalm\Codebase $codebase, \Psalm\Type\Atomic\TNamedObject $input_type_part, \Psalm\Type\Atomic\TObjectWithProperties $container_type_part, bool $allow_interface_equality, ?\Psalm\Internal\Type\Comparator\TypeComparisonResult $atomic_comparison_result) : bool { $all_types_contain = \true; foreach ($container_type_part->properties as $property_name => $container_property_type) { if (!\is_string($property_name)) { continue; } if (!$codebase->classlikes->classOrInterfaceExists($input_type_part->value)) { $all_types_contain = \false; continue; } if (!$codebase->properties->propertyExists($input_type_part->value . '::$' . $property_name, \true)) { $all_types_contain = \false; continue; } $property_declaring_class = (string) $codebase->properties->getDeclaringClassForProperty($input_type_part . '::$' . $property_name, \true); $class_storage = $codebase->classlike_storage_provider->get($property_declaring_class); $input_property_storage = $class_storage->properties[$property_name]; $input_property_type = $input_property_storage->type ?: \Psalm\Type::getMixed(); $property_type_comparison = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!$input_property_type->isEmpty() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_property_type, $container_property_type, \false, \false, $property_type_comparison, $allow_interface_equality) && !$property_type_comparison->type_coerced_from_scalar) { $inverse_property_type_comparison = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $container_property_type, $input_property_type, \false, \false, $inverse_property_type_comparison, $allow_interface_equality) || $inverse_property_type_comparison->type_coerced_from_scalar) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } } $all_types_contain = \false; } } return $all_types_contain; } } extra_types ?: []; $intersection_input_types[$input_type_part->getKey(\false)] = $input_type_part; if ($input_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { foreach ($input_type_part->as->getAtomicTypes() as $g) { if ($g instanceof \Psalm\Type\Atomic\TNamedObject && $g->extra_types) { $intersection_input_types = \array_merge($intersection_input_types, $g->extra_types); } } } $intersection_container_types = $container_type_part->extra_types ?: []; $intersection_container_types[$container_type_part->getKey(\false)] = $container_type_part; if ($container_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { foreach ($container_type_part->as->getAtomicTypes() as $g) { if ($g instanceof \Psalm\Type\Atomic\TNamedObject && $g->extra_types) { $intersection_container_types = \array_merge($intersection_container_types, $g->extra_types); } } } foreach ($intersection_container_types as $container_type_key => $intersection_container_type) { $container_was_static = \false; if ($intersection_container_type instanceof \Psalm\Type\Atomic\TIterable) { $intersection_container_type_lower = 'iterable'; } elseif ($intersection_container_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { $intersection_container_type_lower = 'object'; } elseif ($intersection_container_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$allow_interface_equality) { if (isset($intersection_input_types[$container_type_key])) { continue; } if (\substr($intersection_container_type->defining_class, 0, 3) === 'fn-') { foreach ($intersection_input_types as $intersection_input_type) { if ($intersection_input_type instanceof \Psalm\Type\Atomic\TTemplateParam && \substr($intersection_input_type->defining_class, 0, 3) === 'fn-' && $intersection_input_type->defining_class !== $intersection_container_type->defining_class) { continue 2; } } } return \false; } if ($intersection_container_type->as->isMixed()) { continue; } $intersection_container_type_lower = null; foreach ($intersection_container_type->as->getAtomicTypes() as $g) { if ($g instanceof \Psalm\Type\Atomic\TNull) { continue; } if ($g instanceof \Psalm\Type\Atomic\TObject) { continue 2; } if (!$g instanceof \Psalm\Type\Atomic\TNamedObject) { continue 2; } $intersection_container_type_lower = \strtolower($g->value); } if ($intersection_container_type_lower === null) { return \false; } } else { $container_was_static = $intersection_container_type->was_static; $intersection_container_type_lower = \strtolower($codebase->classlikes->getUnAliasedName($intersection_container_type->value)); } foreach ($intersection_input_types as $intersection_input_key => $intersection_input_type) { $input_was_static = \false; if ($intersection_input_type instanceof \Psalm\Type\Atomic\TIterable) { $intersection_input_type_lower = 'iterable'; } elseif ($intersection_input_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { $intersection_input_type_lower = 'object'; } elseif ($intersection_input_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($intersection_input_type->as->isMixed()) { continue; } $intersection_input_type_lower = null; foreach ($intersection_input_type->as->getAtomicTypes() as $g) { if ($g instanceof \Psalm\Type\Atomic\TNull) { continue; } if (!$g instanceof \Psalm\Type\Atomic\TNamedObject) { continue 2; } $intersection_input_type_lower = \strtolower($g->value); } if ($intersection_input_type_lower === null) { return \false; } } else { $input_was_static = $intersection_input_type->was_static; $intersection_input_type_lower = \strtolower($codebase->classlikes->getUnAliasedName($intersection_input_type->value)); } if ($intersection_container_type instanceof \Psalm\Type\Atomic\TTemplateParam && $intersection_input_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($intersection_container_type->param_name !== $intersection_input_type->param_name || (string) $intersection_container_type->defining_class !== (string) $intersection_input_type->defining_class && \substr($intersection_input_type->defining_class, 0, 3) !== 'fn-' && \substr($intersection_container_type->defining_class, 0, 3) !== 'fn-') { if (\substr($intersection_input_type->defining_class, 0, 3) !== 'fn-') { $input_class_storage = $codebase->classlike_storage_provider->get($intersection_input_type->defining_class); if (isset($input_class_storage->template_type_extends[$intersection_container_type->defining_class][$intersection_container_type->param_name])) { continue; } } return \false; } } if (!$intersection_container_type instanceof \Psalm\Type\Atomic\TTemplateParam || $intersection_input_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($intersection_container_type_lower === $intersection_input_type_lower) { if ($container_was_static && !$input_was_static && !$intersection_input_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } continue; } continue 2; } if ($intersection_input_type_lower === 'generator' && \in_array($intersection_container_type_lower, ['iterator', 'traversable', 'iterable'], \true)) { continue 2; } if ($intersection_container_type_lower === 'iterable') { if ($intersection_input_type_lower === 'traversable' || $codebase->classlikes->classExists($intersection_input_type_lower) && $codebase->classlikes->classImplements($intersection_input_type_lower, 'Traversable') || $codebase->classlikes->interfaceExists($intersection_input_type_lower) && $codebase->classlikes->interfaceExtends($intersection_input_type_lower, 'Traversable')) { continue 2; } } if ($intersection_input_type_lower === 'traversable' && $intersection_container_type_lower === 'iterable') { continue 2; } $input_type_is_interface = $codebase->interfaceExists($intersection_input_type_lower); $container_type_is_interface = $codebase->interfaceExists($intersection_container_type_lower); if ($allow_interface_equality && $container_type_is_interface && ($input_type_is_interface || !isset($intersection_container_types[$intersection_input_key]))) { continue 2; } if ($codebase->classExists($intersection_input_type_lower) && $codebase->classOrInterfaceExists($intersection_container_type_lower) && $codebase->classExtendsOrImplements($intersection_input_type_lower, $intersection_container_type_lower)) { if ($container_was_static && !$input_was_static) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } continue; } continue 2; } if ($input_type_is_interface && $codebase->interfaceExtends($intersection_input_type_lower, $intersection_container_type_lower)) { continue 2; } } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::isMock($intersection_input_type_lower)) { return \true; } } return \false; } return \true; } } type_params[0]->getAtomicTypes() as $atomic_key_type) { if ($atomic_key_type instanceof \Psalm\Type\Atomic\TLiteralString || $atomic_key_type instanceof \Psalm\Type\Atomic\TLiteralInt) { $properties[$atomic_key_type->value] = clone $input_type_part->type_params[1]; $properties[$atomic_key_type->value]->possibly_undefined = \true; } else { $all_string_int_literals = \false; } } if ($all_string_int_literals && $properties) { $input_type_part = new \Psalm\Type\Atomic\TKeyedArray($properties); return \Psalm\Internal\Type\Comparator\KeyedArrayComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $atomic_comparison_result); } } if ($container_type_part instanceof \Psalm\Type\Atomic\TList && $input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($input_type_part->is_list) { $input_type_part = $input_type_part->getList(); } else { return \false; } } if ($container_type_part instanceof \Psalm\Type\Atomic\TList && $input_type_part instanceof \Psalm\Type\Atomic\TClassStringMap) { return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TList && $input_type_part instanceof \Psalm\Type\Atomic\TArray && $input_type_part->type_params[1]->isEmpty()) { return !$container_type_part instanceof \Psalm\Type\Atomic\TNonEmptyList; } if ($input_type_part instanceof \Psalm\Type\Atomic\TList && $container_type_part instanceof \Psalm\Type\Atomic\TList) { if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_type_part->type_param, $container_type_part->type_param, $input_type_part->type_param->ignore_nullable_issues, $input_type_part->type_param->ignore_falsable_issues, $atomic_comparison_result, $allow_interface_equality)) { return \false; } return $input_type_part instanceof \Psalm\Type\Atomic\TNonEmptyList || !$container_type_part instanceof \Psalm\Type\Atomic\TNonEmptyList; } if ($container_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $generic_container_type_part = $container_type_part->getGenericArrayType(); $container_type_part = $generic_container_type_part; } if ($input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $input_type_part = $input_type_part->getGenericArrayType(); } if ($input_type_part instanceof \Psalm\Type\Atomic\TClassStringMap) { $input_type_part = new \Psalm\Type\Atomic\TArray([$input_type_part->getStandinKeyParam(), clone $input_type_part->value_param]); } if ($container_type_part instanceof \Psalm\Type\Atomic\TClassStringMap) { $container_type_part = new \Psalm\Type\Atomic\TArray([$container_type_part->getStandinKeyParam(), clone $container_type_part->value_param]); } if ($container_type_part instanceof \Psalm\Type\Atomic\TList) { $all_types_contain = \false; if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } $container_type_part = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), clone $container_type_part->type_param]); } if ($input_type_part instanceof \Psalm\Type\Atomic\TList) { if ($input_type_part instanceof \Psalm\Type\Atomic\TNonEmptyList) { $input_type_part = new \Psalm\Type\Atomic\TNonEmptyArray([\Psalm\Type::getInt(), clone $input_type_part->type_param]); } else { $input_type_part = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), clone $input_type_part->type_param]); } } foreach ($input_type_part->type_params as $i => $input_param) { if ($i > 1) { break; } $container_param = $container_type_part->type_params[$i]; if ($i === 0 && $input_param->hasMixed() && $container_param->hasString() && $container_param->hasInt()) { continue; } if ($input_param->isEmpty() && $container_type_part instanceof \Psalm\Type\Atomic\TNonEmptyArray) { return \false; } $param_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!$input_param->isEmpty() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_param, $container_param, $input_param->ignore_nullable_issues, $input_param->ignore_falsable_issues, $param_comparison_result, $allow_interface_equality)) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = $param_comparison_result->type_coerced === \true && $atomic_comparison_result->type_coerced !== \false; $atomic_comparison_result->type_coerced_from_mixed = $param_comparison_result->type_coerced_from_mixed === \true && $atomic_comparison_result->type_coerced_from_mixed !== \false; $atomic_comparison_result->type_coerced_from_as_mixed = $param_comparison_result->type_coerced_from_as_mixed === \true && $atomic_comparison_result->type_coerced_from_as_mixed !== \false; $atomic_comparison_result->to_string_cast = $param_comparison_result->to_string_cast === \true && $atomic_comparison_result->to_string_cast !== \false; $atomic_comparison_result->type_coerced_from_scalar = $param_comparison_result->type_coerced_from_scalar === \true && $atomic_comparison_result->type_coerced_from_scalar !== \false; $atomic_comparison_result->scalar_type_match_found = $param_comparison_result->scalar_type_match_found === \true && $atomic_comparison_result->scalar_type_match_found !== \false; } if (!$param_comparison_result->type_coerced_from_as_mixed) { $all_types_contain = \false; } } } if ($container_type_part instanceof \Psalm\Type\Atomic\TNonEmptyArray && !$input_type_part instanceof \Psalm\Type\Atomic\TNonEmptyArray) { if ($all_types_contain && $atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($all_types_contain) { if ($atomic_comparison_result) { $atomic_comparison_result->to_string_cast = \false; } return \true; } return \false; } } extra_types)) && ($input_type_part instanceof \Psalm\Type\Atomic\TTemplateParam || $input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && isset($input_type_part->extra_types))) { return \Psalm\Internal\Type\Comparator\ObjectComparator::isShallowlyContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $atomic_comparison_result); } if ($container_type_part instanceof \Psalm\Type\Atomic\TMixed || $container_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $container_type_part->as->isMixed() && !$container_type_part->extra_types && $input_type_part instanceof \Psalm\Type\Atomic\TMixed) { if (\get_class($container_type_part) === \Psalm\Type\Atomic\TEmptyMixed::class && \get_class($input_type_part) === \Psalm\Type\Atomic\TMixed::class) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_mixed = \true; } return \false; } return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TNever || $input_type_part instanceof \Psalm\Type\Atomic\TEmpty) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TMixed || $input_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $input_type_part->as->isMixed() && !$input_type_part->extra_types) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_mixed = \true; } return \false; } if ($input_type_part instanceof \Psalm\Type\Atomic\TNull) { if ($container_type_part instanceof \Psalm\Type\Atomic\TNull) { return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && ($container_type_part->as->isNullable() || $container_type_part->as->isMixed())) { return \true; } return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TNull) { return \false; } if ($input_type_part instanceof \Psalm\Type\Atomic\Scalar && $container_type_part instanceof \Psalm\Type\Atomic\Scalar) { return \Psalm\Internal\Type\Comparator\ScalarTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $allow_float_int_equality, $atomic_comparison_result); } if ($input_type_part instanceof \Psalm\Type\Atomic\TCallableKeyedArray && $container_type_part instanceof \Psalm\Type\Atomic\TArray) { return \Psalm\Internal\Type\Comparator\ArrayTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $atomic_comparison_result); } if ($container_type_part instanceof \Psalm\Type\Atomic\TCallable && $input_type_part instanceof \Psalm\Type\Atomic\TCallable || $container_type_part instanceof \Psalm\Type\Atomic\TClosure && $input_type_part instanceof \Psalm\Type\Atomic\TClosure) { return \Psalm\Internal\Type\Comparator\CallableTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $atomic_comparison_result); } if ($container_type_part instanceof \Psalm\Type\Atomic\TClosure && $input_type_part instanceof \Psalm\Type\Atomic\TCallable) { if (\Psalm\Internal\Type\Comparator\CallableTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $atomic_comparison_result) === \false) { return \false; } if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TClosure) { if (!$input_type_part instanceof \Psalm\Type\Atomic\TClosure) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_mixed = \true; } return \false; } return \Psalm\Internal\Type\Comparator\CallableTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $atomic_comparison_result); } if ($container_type_part instanceof \Psalm\Type\Atomic\TCallable && $input_type_part instanceof \Psalm\Type\Atomic\TClosure) { return \Psalm\Internal\Type\Comparator\CallableTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $atomic_comparison_result); } if ($input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $input_type_part->value === 'Closure' && $container_type_part instanceof \Psalm\Type\Atomic\TCallable) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TObject && $container_type_part instanceof \Psalm\Type\Atomic\TCallable) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TCallableObject && $container_type_part instanceof \Psalm\Type\Atomic\TObject) { return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TKeyedArray && $input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray || $container_type_part instanceof \Psalm\Type\Atomic\TObjectWithProperties && $input_type_part instanceof \Psalm\Type\Atomic\TObjectWithProperties) { return \Psalm\Internal\Type\Comparator\KeyedArrayComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $atomic_comparison_result); } if (($input_type_part instanceof \Psalm\Type\Atomic\TArray || $input_type_part instanceof \Psalm\Type\Atomic\TList || $input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray || $input_type_part instanceof \Psalm\Type\Atomic\TClassStringMap) && ($container_type_part instanceof \Psalm\Type\Atomic\TArray || $container_type_part instanceof \Psalm\Type\Atomic\TList || $container_type_part instanceof \Psalm\Type\Atomic\TKeyedArray || $container_type_part instanceof \Psalm\Type\Atomic\TClassStringMap)) { return \Psalm\Internal\Type\Comparator\ArrayTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $atomic_comparison_result); } if (($input_type_part instanceof \Psalm\Type\Atomic\TNamedObject || $input_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $input_type_part->as->hasObjectType() || $input_type_part instanceof \Psalm\Type\Atomic\TIterable) && ($container_type_part instanceof \Psalm\Type\Atomic\TNamedObject || $container_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $container_type_part->isObjectType() || $container_type_part instanceof \Psalm\Type\Atomic\TIterable) && \Psalm\Internal\Type\Comparator\ObjectComparator::isShallowlyContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $atomic_comparison_result)) { if ($container_type_part instanceof \Psalm\Type\Atomic\TGenericObject || $container_type_part instanceof \Psalm\Type\Atomic\TIterable) { return \Psalm\Internal\Type\Comparator\GenericTypeComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $atomic_comparison_result); } if ($container_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $container_type_part->was_static && !$input_type_part->was_static) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($atomic_comparison_result) { $atomic_comparison_result->to_string_cast = \false; } return \true; } if (\get_class($input_type_part) === \Psalm\Type\Atomic\TObject::class && \get_class($container_type_part) === \Psalm\Type\Atomic\TObject::class) { return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $input_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { return \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_type_part->as, $container_type_part->as, \false, \false, $atomic_comparison_result, $allow_interface_equality); } if ($container_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { foreach ($container_type_part->as->getAtomicTypes() as $container_as_type_part) { if (self::isContainedBy($codebase, $input_type_part, $container_as_type_part, $allow_interface_equality, $allow_float_int_equality, $atomic_comparison_result)) { if ($allow_interface_equality || $input_type_part instanceof \Psalm\Type\Atomic\TArray && !$input_type_part->type_params[1]->isEmpty() || $input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { return \true; } } } return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TConditional) { $atomic_types = \array_merge(\array_values($container_type_part->if_type->getAtomicTypes()), \array_values($container_type_part->else_type->getAtomicTypes())); foreach ($atomic_types as $container_as_type_part) { if (self::isContainedBy($codebase, $input_type_part, $container_as_type_part, $allow_interface_equality, $allow_float_int_equality, $atomic_comparison_result)) { return \true; } } return \false; } if ($input_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($input_type_part->extra_types) { foreach ($input_type_part->extra_types as $extra_type) { if (self::isContainedBy($codebase, $extra_type, $container_type_part, $allow_interface_equality, $allow_float_int_equality, $atomic_comparison_result)) { return \true; } } } foreach ($input_type_part->as->getAtomicTypes() as $input_as_type_part) { if ($input_as_type_part instanceof \Psalm\Type\Atomic\TNull && $container_type_part instanceof \Psalm\Type\Atomic\TNull) { continue; } if (self::isContainedBy($codebase, $input_as_type_part, $container_type_part, $allow_interface_equality, $allow_float_int_equality, $atomic_comparison_result)) { return \true; } } return \false; } if ($input_type_part instanceof \Psalm\Type\Atomic\TConditional) { $input_atomic_types = \array_merge(\array_values($input_type_part->if_type->getAtomicTypes()), \array_values($input_type_part->else_type->getAtomicTypes())); foreach ($input_atomic_types as $input_as_type_part) { if (self::isContainedBy($codebase, $input_as_type_part, $container_type_part, $allow_interface_equality, $allow_float_int_equality, $atomic_comparison_result)) { return \true; } } return \false; } if ($input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $input_type_part->value === 'static' && $container_type_part instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($container_type_part->value) === 'self') { return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TIterable) { if ($input_type_part instanceof \Psalm\Type\Atomic\TArray || $input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray || $input_type_part instanceof \Psalm\Type\Atomic\TList) { if ($input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $input_type_part = $input_type_part->getGenericArrayType(); } elseif ($input_type_part instanceof \Psalm\Type\Atomic\TList) { $input_type_part = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $input_type_part->type_param]); } $all_types_contain = \true; foreach ($input_type_part->type_params as $i => $input_param) { $container_param_offset = $i - (2 - \count($container_type_part->type_params)); if ($container_param_offset === -1) { continue; } $container_param = $container_type_part->type_params[$container_param_offset]; if ($i === 0 && $input_param->hasMixed() && $container_param->hasString() && $container_param->hasInt()) { continue; } $array_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!$input_param->isEmpty() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_param, $container_param, $input_param->ignore_nullable_issues, $input_param->ignore_falsable_issues, $array_comparison_result, $allow_interface_equality) && !$array_comparison_result->type_coerced_from_scalar) { if ($atomic_comparison_result && $array_comparison_result->type_coerced_from_mixed) { $atomic_comparison_result->type_coerced_from_mixed = \true; } $all_types_contain = \false; } } if ($all_types_contain) { if ($atomic_comparison_result) { $atomic_comparison_result->to_string_cast = \false; } return \true; } return \false; } if ($input_type_part->hasTraversableInterface($codebase)) { return \true; } } if ($container_type_part instanceof \Psalm\Type\Atomic\TString || $container_type_part instanceof \Psalm\Type\Atomic\TScalar) { if ($input_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { // check whether the object has a __toString method if ($codebase->classOrInterfaceExists($input_type_part->value)) { if ($codebase->php_major_version >= 8 && ($input_type_part->value === 'Stringable' || $codebase->classlikes->classExists($input_type_part->value) && $codebase->classlikes->classImplements($input_type_part->value, 'Stringable') || $codebase->classlikes->interfaceExtends($input_type_part->value, 'Stringable'))) { if ($atomic_comparison_result) { $atomic_comparison_result->to_string_cast = \true; } return \true; } if ($codebase->methods->methodExists(new \Psalm\Internal\MethodIdentifier($input_type_part->value, '__tostring'))) { if ($atomic_comparison_result) { $atomic_comparison_result->to_string_cast = \true; } return \true; } } // PHP 5.6 doesn't support this natively, so this introduces a bug *just* when checking PHP 5.6 code if ($input_type_part->value === 'ReflectionType') { if ($atomic_comparison_result) { $atomic_comparison_result->to_string_cast = \true; } return \true; } } elseif ($input_type_part instanceof \Psalm\Type\Atomic\TObjectWithProperties && isset($input_type_part->methods['__toString'])) { if ($atomic_comparison_result) { $atomic_comparison_result->to_string_cast = \true; } return \true; } } if ($container_type_part instanceof \Psalm\Type\Atomic\TCallable && ($input_type_part instanceof \Psalm\Type\Atomic\TLiteralString || $input_type_part instanceof \Psalm\Type\Atomic\TCallableString || $input_type_part instanceof \Psalm\Type\Atomic\TArray || $input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray || $input_type_part instanceof \Psalm\Type\Atomic\TList || $input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classOrInterfaceExists($input_type_part->value) && $codebase->methodExists($input_type_part->value . '::__invoke'))) { return \Psalm\Internal\Type\Comparator\CallableTypeComparator::isNotExplicitlyCallableTypeCallable($codebase, $input_type_part, $container_type_part, $atomic_comparison_result); } if ($container_type_part instanceof \Psalm\Type\Atomic\TObject && $input_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { if ($container_type_part instanceof \Psalm\Type\Atomic\TObjectWithProperties && $input_type_part->value !== 'stdClass') { return \Psalm\Internal\Type\Comparator\KeyedArrayComparator::isContainedByObjectWithProperties($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $atomic_comparison_result); } return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $container_type_part->was_static && !$input_type_part->was_static) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($input_type_part instanceof \Psalm\Type\Atomic\TObject && $container_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $input_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classOrInterfaceExists($input_type_part->value) && ($codebase->classExists($container_type_part->value) && $codebase->classExtendsOrImplements($container_type_part->value, $input_type_part->value) || $codebase->interfaceExists($container_type_part->value) && $codebase->interfaceExtends($container_type_part->value, $input_type_part->value))) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } return $input_type_part->getKey() === $container_type_part->getKey(); } /** * Does the input param atomic type match the given param atomic type */ public static function canBeIdentical(\Psalm\Codebase $codebase, \Psalm\Type\Atomic $type1_part, \Psalm\Type\Atomic $type2_part) : bool { if (\get_class($type1_part) === \Psalm\Type\Atomic\TList::class && $type2_part instanceof \Psalm\Type\Atomic\TNonEmptyList || \get_class($type2_part) === \Psalm\Type\Atomic\TList::class && $type1_part instanceof \Psalm\Type\Atomic\TNonEmptyList) { return \Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $type1_part->type_param, $type2_part->type_param); } if (\get_class($type1_part) === \Psalm\Type\Atomic\TArray::class && $type2_part instanceof \Psalm\Type\Atomic\TNonEmptyArray || \get_class($type2_part) === \Psalm\Type\Atomic\TArray::class && $type1_part instanceof \Psalm\Type\Atomic\TNonEmptyArray) { return \Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $type1_part->type_params[0], $type2_part->type_params[0]) && \Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $type1_part->type_params[1], $type2_part->type_params[1]); } $first_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $second_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $either_contains = \Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $type1_part, $type2_part, \true, \false, $first_comparison_result) && !$first_comparison_result->to_string_cast || \Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $type2_part, $type1_part, \true, \false, $second_comparison_result) && !$second_comparison_result->to_string_cast || $first_comparison_result->type_coerced && $second_comparison_result->type_coerced; if ($either_contains) { return \true; } return \false; } } type_coerced = \true; } return \false; } if (($input_type_part instanceof \Psalm\Type\Atomic\TLowercaseString || $input_type_part instanceof \Psalm\Type\Atomic\TNonEmptyLowercaseString) && \get_class($container_type_part) === \Psalm\Type\Atomic\TString::class) { return \true; } if (($container_type_part instanceof \Psalm\Type\Atomic\TLowercaseString || $container_type_part instanceof \Psalm\Type\Atomic\TNonEmptyLowercaseString) && $input_type_part instanceof \Psalm\Type\Atomic\TString) { if ($input_type_part instanceof \Psalm\Type\Atomic\TLowercaseString && $container_type_part instanceof \Psalm\Type\Atomic\TLowercaseString || $input_type_part instanceof \Psalm\Type\Atomic\TNonEmptyLowercaseString && $container_type_part instanceof \Psalm\Type\Atomic\TNonEmptyLowercaseString) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TNonEmptyLowercaseString && $container_type_part instanceof \Psalm\Type\Atomic\TLowercaseString) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TLowercaseString && $container_type_part instanceof \Psalm\Type\Atomic\TNonEmptyLowercaseString) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($input_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { if (\strtolower($input_type_part->value) === $input_type_part->value) { return $input_type_part->value || $container_type_part instanceof \Psalm\Type\Atomic\TLowercaseString; } return \false; } if ($input_type_part instanceof \Psalm\Type\Atomic\TClassString) { return \false; } if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TDependentGetClass) { $first_type = \array_values($container_type_part->as_type->getAtomicTypes())[0]; $container_type_part = new \Psalm\Type\Atomic\TClassString('object', $first_type instanceof \Psalm\Type\Atomic\TNamedObject ? $first_type : null); } if ($input_type_part instanceof \Psalm\Type\Atomic\TDependentGetClass) { $first_type = \array_values($input_type_part->as_type->getAtomicTypes())[0]; if ($first_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $object_type = \array_values($first_type->as->getAtomicTypes())[0]; $input_type_part = new \Psalm\Type\Atomic\TTemplateParamClass($first_type->param_name, $first_type->as->getId(), $object_type instanceof \Psalm\Type\Atomic\TNamedObject ? $object_type : null, $first_type->defining_class); } else { $input_type_part = new \Psalm\Type\Atomic\TClassString('object', $first_type instanceof \Psalm\Type\Atomic\TNamedObject ? $first_type : null); } } if ($input_type_part instanceof \Psalm\Type\Atomic\TDependentGetType) { $input_type_part = new \Psalm\Type\Atomic\TString(); if ($container_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { return isset(\Psalm\Internal\Analyzer\ClassLikeAnalyzer::GETTYPE_TYPES[$container_type_part->value]); } } if ($container_type_part instanceof \Psalm\Type\Atomic\TDependentGetDebugType) { return $input_type_part instanceof \Psalm\Type\Atomic\TString; } if ($input_type_part instanceof \Psalm\Type\Atomic\TDependentGetDebugType) { $input_type_part = new \Psalm\Type\Atomic\TString(); } if ($container_type_part instanceof \Psalm\Type\Atomic\TDependentGetType) { $container_type_part = new \Psalm\Type\Atomic\TString(); if ($input_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { return isset(\Psalm\Internal\Analyzer\ClassLikeAnalyzer::GETTYPE_TYPES[$input_type_part->value]); } } if ($input_type_part instanceof \Psalm\Type\Atomic\TFalse && $container_type_part instanceof \Psalm\Type\Atomic\TBool && !$container_type_part instanceof \Psalm\Type\Atomic\TTrue) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TTrue && $container_type_part instanceof \Psalm\Type\Atomic\TBool && !$container_type_part instanceof \Psalm\Type\Atomic\TFalse) { return \true; } // from https://wiki.php.net/rfc/scalar_type_hints_v5: // // > int types can resolve a parameter type of float if ($input_type_part instanceof \Psalm\Type\Atomic\TInt && $container_type_part instanceof \Psalm\Type\Atomic\TFloat && !$container_type_part instanceof \Psalm\Type\Atomic\TLiteralFloat && $allow_float_int_equality) { return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TArrayKey && $input_type_part instanceof \Psalm\Type\Atomic\TNumeric) { return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TArrayKey && ($input_type_part instanceof \Psalm\Type\Atomic\TInt || $input_type_part instanceof \Psalm\Type\Atomic\TString || $input_type_part instanceof \Psalm\Type\Atomic\TTemplateKeyOf)) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TTemplateKeyOf) { foreach ($input_type_part->as->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TArray) { /** @var Scalar $array_key_atomic */ foreach ($atomic_type->type_params[0]->getAtomicTypes() as $array_key_atomic) { if (!self::isContainedBy($codebase, $array_key_atomic, $container_type_part, $allow_interface_equality, $allow_float_int_equality, $atomic_comparison_result)) { return \false; } } } } return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TArrayKey && ($container_type_part instanceof \Psalm\Type\Atomic\TInt || $container_type_part instanceof \Psalm\Type\Atomic\TString)) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_mixed = \true; $atomic_comparison_result->scalar_type_match_found = \true; } return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TScalar && $input_type_part instanceof \Psalm\Type\Atomic\Scalar) { return \true; } if (\get_class($container_type_part) === \Psalm\Type\Atomic\TInt::class && $input_type_part instanceof \Psalm\Type\Atomic\TLiteralInt) { return \true; } if (\get_class($container_type_part) === \Psalm\Type\Atomic\TInt::class && $input_type_part instanceof \Psalm\Type\Atomic\TPositiveInt) { return \true; } if (\get_class($container_type_part) === \Psalm\Type\Atomic\TFloat::class && $input_type_part instanceof \Psalm\Type\Atomic\TLiteralFloat) { return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TNonEmptyString && $input_type_part instanceof \Psalm\Type\Atomic\TLiteralString && $input_type_part->value === '') { return \false; } if ((\get_class($container_type_part) === \Psalm\Type\Atomic\TString::class || \get_class($container_type_part) === \Psalm\Type\Atomic\TNonEmptyString::class || \get_class($container_type_part) === \Psalm\Type\Atomic\TSingleLetter::class) && $input_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { return \true; } if (\get_class($input_type_part) === \Psalm\Type\Atomic\TInt::class && $container_type_part instanceof \Psalm\Type\Atomic\TLiteralInt || \get_class($input_type_part) === \Psalm\Type\Atomic\TPositiveInt::class && $container_type_part instanceof \Psalm\Type\Atomic\TLiteralInt && $container_type_part->value > 0) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_scalar = \true; } return \false; } if ($input_type_part instanceof \Psalm\Type\Atomic\TInt && $container_type_part instanceof \Psalm\Type\Atomic\TPositiveInt) { if ($input_type_part instanceof \Psalm\Type\Atomic\TPositiveInt) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TLiteralInt) { return $input_type_part->value > 0; } if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_scalar = \true; } return \false; } if (\get_class($input_type_part) === \Psalm\Type\Atomic\TFloat::class && $container_type_part instanceof \Psalm\Type\Atomic\TLiteralFloat) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_scalar = \true; } return \false; } if ((\get_class($input_type_part) === \Psalm\Type\Atomic\TString::class || \get_class($input_type_part) === \Psalm\Type\Atomic\TSingleLetter::class || \get_class($input_type_part) === \Psalm\Type\Atomic\TNonEmptyString::class) && $container_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_scalar = \true; } return \false; } if (($input_type_part instanceof \Psalm\Type\Atomic\TLowercaseString || $input_type_part instanceof \Psalm\Type\Atomic\TNonEmptyLowercaseString) && $container_type_part instanceof \Psalm\Type\Atomic\TLiteralString && \strtolower($container_type_part->value) === $container_type_part->value) { if ($atomic_comparison_result && ($container_type_part->value || $input_type_part instanceof \Psalm\Type\Atomic\TLowercaseString)) { $atomic_comparison_result->type_coerced = \true; $atomic_comparison_result->type_coerced_from_scalar = \true; } return \false; } if (($container_type_part instanceof \Psalm\Type\Atomic\TClassString || $container_type_part instanceof \Psalm\Type\Atomic\TLiteralClassString) && ($input_type_part instanceof \Psalm\Type\Atomic\TClassString || $input_type_part instanceof \Psalm\Type\Atomic\TLiteralClassString)) { return \Psalm\Internal\Type\Comparator\ClassStringComparator::isContainedBy($codebase, $input_type_part, $container_type_part, $allow_interface_equality, $atomic_comparison_result); } if ($container_type_part instanceof \Psalm\Type\Atomic\TString && $input_type_part instanceof \Psalm\Type\Atomic\TTraitString) { return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TTraitString && (\get_class($input_type_part) === \Psalm\Type\Atomic\TString::class || \get_class($input_type_part) === \Psalm\Type\Atomic\TNonEmptyString::class)) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if (($input_type_part instanceof \Psalm\Type\Atomic\TClassString || $input_type_part instanceof \Psalm\Type\Atomic\TLiteralClassString) && (\get_class($container_type_part) === \Psalm\Type\Atomic\TString::class || \get_class($container_type_part) === \Psalm\Type\Atomic\TSingleLetter::class || \get_class($container_type_part) === \Psalm\Type\Atomic\TNonEmptyString::class)) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TCallableString && (\get_class($container_type_part) === \Psalm\Type\Atomic\TString::class || \get_class($container_type_part) === \Psalm\Type\Atomic\TSingleLetter::class || \get_class($container_type_part) === \Psalm\Type\Atomic\TNonEmptyString::class)) { return \true; } if ($container_type_part instanceof \Psalm\Type\Atomic\TString && ($input_type_part instanceof \Psalm\Type\Atomic\TNumericString || $input_type_part instanceof \Psalm\Type\Atomic\THtmlEscapedString)) { if ($container_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { if (\is_numeric($container_type_part->value) && $atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TString && ($container_type_part instanceof \Psalm\Type\Atomic\TNumericString || $container_type_part instanceof \Psalm\Type\Atomic\THtmlEscapedString)) { if ($input_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { return \is_numeric($input_type_part->value); } if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TCallableString && $input_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { $input_callable = \Psalm\Internal\Type\Comparator\CallableTypeComparator::getCallableFromAtomic($codebase, $input_type_part); $container_callable = \Psalm\Internal\Type\Comparator\CallableTypeComparator::getCallableFromAtomic($codebase, $container_type_part); if ($input_callable && $container_callable) { if (\Psalm\Internal\Type\Comparator\CallableTypeComparator::isContainedBy($codebase, $input_callable, $container_callable, $atomic_comparison_result ?: new \Psalm\Internal\Type\Comparator\TypeComparisonResult()) === \false) { return \false; } } return \true; } if ($input_type_part->getKey() === $container_type_part->getKey()) { return \true; } if (($container_type_part instanceof \Psalm\Type\Atomic\TClassString || $container_type_part instanceof \Psalm\Type\Atomic\TLiteralClassString || $container_type_part instanceof \Psalm\Type\Atomic\TCallableString) && $input_type_part instanceof \Psalm\Type\Atomic\TString) { if ($atomic_comparison_result) { $atomic_comparison_result->type_coerced = \true; } return \false; } if ($container_type_part instanceof \Psalm\Type\Atomic\TNumeric && $input_type_part->isNumericType()) { return \true; } if ($input_type_part instanceof \Psalm\Type\Atomic\TNumeric) { if ($container_type_part->isNumericType()) { if ($atomic_comparison_result) { $atomic_comparison_result->scalar_type_match_found = \true; } } } if ($input_type_part instanceof \Psalm\Type\Atomic\Scalar) { if (!$container_type_part instanceof \Psalm\Type\Atomic\TLiteralInt && !$container_type_part instanceof \Psalm\Type\Atomic\TLiteralString && !$container_type_part instanceof \Psalm\Type\Atomic\TLiteralFloat) { if ($atomic_comparison_result) { $atomic_comparison_result->scalar_type_match_found = \true; } } } return \false; } } */ private $included_files = []; /** * @template T * @param callable():T $f * @return T */ public function runAndCollect(callable $f) { $before = \get_included_files(); $ret = $f(); $after = \get_included_files(); $included = \array_diff($after, $before); $this->included_files = \array_values(\array_unique(\array_merge($this->included_files, $included))); return $ret; } /** @return list */ public function getIncludedFiles() : array { return $this->included_files; } /** @return list */ public function getFilteredIncludedFiles() : array { return \array_values(\preg_grep('@^phar://@', $this->getIncludedFiles(), \PREG_GREP_INVERT)); } } */ public $inferred_property_types = []; public function __construct(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ $class, \Psalm\Internal\Analyzer\SourceAnalyzer $source, ?string $fq_class_name) { if (!$fq_class_name) { $fq_class_name = self::getAnonymousClassName($class, $source->getFilePath()); } parent::__construct($class, $source, $fq_class_name); if (!$this->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { throw new \InvalidArgumentException('Bad'); } if ($this->class->extends) { $this->parent_fq_class_name = self::getFQCLNFromNameObject($this->class->extends, $this->source->getAliases()); } } public static function getAnonymousClassName(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ $class, string $file_path) : string { return \preg_replace('/[^A-Za-z0-9]/', '_', $file_path) . '_' . $class->getLine() . '_' . (int) $class->getAttribute('startFilePos'); } /** * @return null|false */ public function analyze(?\Psalm\Context $class_context = null, ?\Psalm\Context $global_context = null) : ?bool { $class = $this->class; if (!$class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { throw new \LogicException('Something went badly wrong'); } $fq_class_name = $class_context && $class_context->self ? $class_context->self : $this->fq_class_name; $storage = $this->storage; if ($storage->has_visitor_issues) { return null; } if ($class->name && (\preg_match('/(^|\\\\)(int|float|bool|string|void|null|false|true|object|mixed)$/i', $fq_class_name) || \strtolower($fq_class_name) === 'resource')) { $class_name_parts = \explode('\\', $fq_class_name); $class_name = \array_pop($class_name_parts); if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ReservedWord($class_name . ' is a reserved word', new \Psalm\CodeLocation($this, $class->name, null, \true), $class_name), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } return null; } $project_analyzer = $this->file_analyzer->project_analyzer; $codebase = $this->getCodebase(); if ($codebase->alter_code && $class->name && $codebase->classes_to_move) { if (isset($codebase->classes_to_move[\strtolower($this->fq_class_name)])) { $destination_class = $codebase->classes_to_move[\strtolower($this->fq_class_name)]; $source_class_parts = \explode('\\', $this->fq_class_name); $destination_class_parts = \explode('\\', $destination_class); \array_pop($source_class_parts); \array_pop($destination_class_parts); $source_ns = \implode('\\', $source_class_parts); $destination_ns = \implode('\\', $destination_class_parts); if (\strtolower($source_ns) !== \strtolower($destination_ns)) { if ($storage->namespace_name_location) { $bounds = $storage->namespace_name_location->getSelectionBounds(); $file_manipulations = [new \Psalm\FileManipulation($bounds[0], $bounds[1], $destination_ns)]; \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($this->getFilePath(), $file_manipulations); } elseif (!$source_ns) { $first_statement_pos = $this->getFileAnalyzer()->getFirstStatementOffset(); if ($first_statement_pos === -1) { $first_statement_pos = (int) $class->getAttribute('startFilePos'); } $file_manipulations = [new \Psalm\FileManipulation($first_statement_pos, $first_statement_pos, 'namespace ' . $destination_ns . ';' . "\n\n", \true)]; \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($this->getFilePath(), $file_manipulations); } } } $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $this, $class->name, $this->fq_class_name, null); } foreach ($storage->docblock_issues as $docblock_issue) { \Psalm\IssueBuffer::add($docblock_issue); } $classlike_storage_provider = $codebase->classlike_storage_provider; $parent_fq_class_name = $this->parent_fq_class_name; if ($class->extends) { if (!$parent_fq_class_name) { throw new \UnexpectedValueException('Parent class should be filled in for ' . $fq_class_name); } $parent_reference_location = new \Psalm\CodeLocation($this, $class->extends); if (self::checkFullyQualifiedClassLikeName($this->getSource(), $parent_fq_class_name, $parent_reference_location, null, null, $storage->suppressed_issues + $this->getSuppressedIssues(), \false) === \false) { return \false; } if ($codebase->alter_code && $codebase->classes_to_move) { $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $this, $class->extends, $parent_fq_class_name, null); } try { $parent_class_storage = $classlike_storage_provider->get($parent_fq_class_name); $code_location = new \Psalm\CodeLocation($this, $class->extends, $class_context ? $class_context->include_location : null, \true); if ($parent_class_storage->is_trait || $parent_class_storage->is_interface) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedClass($parent_fq_class_name . ' is not a class', $code_location, $parent_fq_class_name . ' as class'), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if ($parent_class_storage->final) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidExtendClass('Class ' . $fq_class_name . ' may not inherit from final class ' . $parent_fq_class_name, $code_location, $fq_class_name), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if ($parent_class_storage->deprecated) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedClass($parent_fq_class_name . ' is marked deprecated', $code_location, $parent_fq_class_name), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if (!\Psalm\Internal\Analyzer\NamespaceAnalyzer::isWithin($fq_class_name, $parent_class_storage->internal)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InternalClass($parent_fq_class_name . ' is internal to ' . $parent_class_storage->internal . ' but called from ' . $fq_class_name, $code_location, $parent_fq_class_name), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if ($parent_class_storage->external_mutation_free && !$storage->external_mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingImmutableAnnotation($parent_fq_class_name . ' is marked immutable, but ' . $fq_class_name . ' is not marked immutable', $code_location), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if ($storage->mutation_free && !$parent_class_storage->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MutableDependency($fq_class_name . ' is marked immutable but ' . $parent_fq_class_name . ' is not', $code_location), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if ($codebase->store_node_types) { $codebase->analyzer->addNodeReference($this->getFilePath(), $class->extends, $codebase->classlikes->classExists($parent_fq_class_name) ? $parent_fq_class_name : '*' . \implode('\\', $class->extends->parts)); } $code_location = new \Psalm\CodeLocation($this, $class->name ?: $class, $class_context ? $class_context->include_location : null, \true); if ($storage->template_type_extends_count !== null) { $this->checkTemplateParams($codebase, $storage, $parent_class_storage, $code_location, $storage->template_type_extends_count); } } catch (\InvalidArgumentException $e) { // do nothing } } foreach ($class->implements as $interface_name) { $fq_interface_name = self::getFQCLNFromNameObject($interface_name, $this->source->getAliases()); $codebase->analyzer->addNodeReference($this->getFilePath(), $interface_name, $codebase->classlikes->interfaceExists($fq_interface_name) ? $fq_interface_name : '*' . \implode('\\', $interface_name->parts)); $interface_location = new \Psalm\CodeLocation($this, $interface_name); if (self::checkFullyQualifiedClassLikeName($this, $fq_interface_name, $interface_location, null, null, $this->getSuppressedIssues(), \false) === \false) { continue; } if ($codebase->store_node_types && $fq_class_name) { $bounds = $interface_location->getSelectionBounds(); $codebase->analyzer->addOffsetReference($this->getFilePath(), $bounds[0], $bounds[1], $fq_interface_name); } $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $this, $interface_name, $fq_interface_name, null); $fq_interface_name_lc = \strtolower($fq_interface_name); try { $interface_storage = $classlike_storage_provider->get($fq_interface_name_lc); } catch (\InvalidArgumentException $e) { continue; } $code_location = new \Psalm\CodeLocation($this, $interface_name, $class_context ? $class_context->include_location : null, \true); if (!$interface_storage->is_interface) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedInterface($fq_interface_name . ' is not an interface', $code_location, $fq_interface_name), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if (isset($storage->template_type_implements_count[$fq_interface_name_lc])) { $expected_param_count = $storage->template_type_implements_count[$fq_interface_name_lc]; $this->checkTemplateParams($codebase, $storage, $interface_storage, $code_location, $expected_param_count); } } if ($storage->template_types) { foreach ($storage->template_types as $param_name => $_) { $fq_classlike_name = \Psalm\Type::getFQCLNFromString($param_name, $this->getAliases()); if ($codebase->classOrInterfaceExists($fq_classlike_name)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ReservedWord('Cannot use ' . $param_name . ' as template name since the class already exists', new \Psalm\CodeLocation($this, $this->class), 'resource'), $this->getSuppressedIssues())) { // fall through } } } } if (($storage->templatedMixins || $storage->namedMixins) && $storage->mixin_declaring_fqcln === $storage->name) { /** @var non-empty-array $mixins */ $mixins = \array_merge($storage->templatedMixins, $storage->namedMixins); $union = new \Psalm\Type\Union($mixins); $union->check($this, new \Psalm\CodeLocation($this, $class->name ?: $class, null, \true), $this->getSuppressedIssues()); } if ($storage->template_type_extends) { foreach ($storage->template_type_extends as $type_map) { foreach ($type_map as $atomic_type) { $atomic_type->check($this, new \Psalm\CodeLocation($this, $class->name ?: $class, null, \true), $this->getSuppressedIssues()); } } } if ($storage->invalid_dependencies) { return null; } $class_interfaces = $storage->class_implements; foreach ($class_interfaces as $interface_name) { try { $interface_storage = $classlike_storage_provider->get($interface_name); } catch (\InvalidArgumentException $e) { continue; } $code_location = new \Psalm\CodeLocation($this, $class->name ? $class->name : $class, $class_context ? $class_context->include_location : null, \true); if ($interface_storage->deprecated) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedInterface($interface_name . ' is marked deprecated', $code_location, $interface_name), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if ($interface_storage->external_mutation_free && !$storage->external_mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingImmutableAnnotation($interface_name . ' is marked immutable, but ' . $fq_class_name . ' is not marked immutable', $code_location), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } foreach ($interface_storage->methods as $interface_method_name_lc => $interface_method_storage) { if ($interface_method_storage->visibility === self::VISIBILITY_PUBLIC) { $implementer_declaring_method_id = $codebase->methods->getDeclaringMethodId(new \Psalm\Internal\MethodIdentifier($this->fq_class_name, $interface_method_name_lc)); $implementer_method_storage = null; $implementer_classlike_storage = null; if ($implementer_declaring_method_id) { $implementer_fq_class_name = $implementer_declaring_method_id->fq_class_name; $implementer_method_storage = $codebase->methods->getStorage($implementer_declaring_method_id); $implementer_classlike_storage = $classlike_storage_provider->get($implementer_fq_class_name); } if (!$implementer_method_storage) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnimplementedInterfaceMethod('Method ' . $interface_method_name_lc . ' is not defined on class ' . $storage->name, $code_location), $storage->suppressed_issues + $this->getSuppressedIssues())) { return \false; } return null; } $implementer_appearing_method_id = $codebase->methods->getAppearingMethodId(new \Psalm\Internal\MethodIdentifier($this->fq_class_name, $interface_method_name_lc)); $implementer_visibility = $implementer_method_storage->visibility; if ($implementer_appearing_method_id && $implementer_appearing_method_id !== $implementer_declaring_method_id) { $appearing_fq_class_name = $implementer_appearing_method_id->fq_class_name; $appearing_method_name = $implementer_appearing_method_id->method_name; $appearing_class_storage = $classlike_storage_provider->get($appearing_fq_class_name); if (isset($appearing_class_storage->trait_visibility_map[$appearing_method_name])) { $implementer_visibility = $appearing_class_storage->trait_visibility_map[$appearing_method_name]; } } if ($implementer_visibility !== self::VISIBILITY_PUBLIC) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleMethod('Interface-defined method ' . $implementer_method_storage->cased_name . ' must be public in ' . $storage->name, $code_location), $storage->suppressed_issues + $this->getSuppressedIssues())) { return \false; } return null; } if ($interface_method_storage->is_static && !$implementer_method_storage->is_static) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMismatch('Method ' . $implementer_method_storage->cased_name . ' should be static like ' . $storage->name . '::' . $interface_method_storage->cased_name, $code_location), $implementer_method_storage->suppressed_issues)) { return \false; } } if ($storage->abstract && $implementer_method_storage === $interface_method_storage) { continue; } \Psalm\Internal\Analyzer\MethodComparator::compare($codebase, null, $implementer_classlike_storage ?: $storage, $interface_storage, $implementer_method_storage, $interface_method_storage, $this->fq_class_name, $implementer_visibility, $code_location, $implementer_method_storage->suppressed_issues, \false); } } } if (!$class_context) { $class_context = new \Psalm\Context($this->fq_class_name); $class_context->parent = $parent_fq_class_name; } if ($global_context) { $class_context->strict_types = $global_context->strict_types; } if ($this->leftover_stmts) { (new \Psalm\Internal\Analyzer\StatementsAnalyzer($this, new \Psalm\Internal\Provider\NodeDataProvider()))->analyze($this->leftover_stmts, $class_context); } if (!$storage->abstract) { foreach ($storage->declaring_method_ids as $declaring_method_id) { $method_storage = $codebase->methods->getStorage($declaring_method_id); $declaring_class_name = $declaring_method_id->fq_class_name; $method_name_lc = $declaring_method_id->method_name; if ($method_storage->abstract) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnimplementedAbstractMethod('Method ' . $method_name_lc . ' is not defined on class ' . $this->fq_class_name . ', defined abstract in ' . $declaring_class_name, new \Psalm\CodeLocation($this, $class->name ? $class->name : $class, $class_context->include_location, \true)), $storage->suppressed_issues + $this->getSuppressedIssues())) { return \false; } } } } self::addContextProperties($this, $storage, $class_context, $this->fq_class_name, $this->parent_fq_class_name, $class->stmts); $constructor_analyzer = null; $member_stmts = []; foreach ($class->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $method_analyzer = $this->analyzeClassMethod($stmt, $storage, $this, $class_context, $global_context); if ($stmt->name->name === '__construct') { $constructor_analyzer = $method_analyzer; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { if ($this->analyzeTraitUse($this->source->getAliases(), $stmt, $project_analyzer, $storage, $class_context, $global_context, $constructor_analyzer) === \false) { return \false; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { foreach ($stmt->props as $prop) { if ($prop->default) { $member_stmts[] = $stmt; } if ($codebase->alter_code) { $property_id = \strtolower($this->fq_class_name) . '::$' . $prop->name; $property_storage = $codebase->properties->getStorage($property_id); if ($property_storage->type && $property_storage->type_location && $property_storage->type_location !== $property_storage->signature_type_location) { $replace_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $property_storage->type, $this->getFQCLN(), $this->getFQCLN(), $this->getParentFQCLN()); $codebase->classlikes->handleDocblockTypeInMigration($codebase, $this, $replace_type, $property_storage->type_location, null); } foreach ($codebase->properties_to_rename as $original_property_id => $new_property_name) { if ($property_id === $original_property_id) { $file_manipulations = [new \Psalm\FileManipulation((int) $prop->name->getAttribute('startFilePos'), (int) $prop->name->getAttribute('endFilePos') + 1, '$' . $new_property_name)]; \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($this->getFilePath(), $file_manipulations); } } } } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst) { $member_stmts[] = $stmt; foreach ($stmt->consts as $const) { $const_id = \strtolower($this->fq_class_name) . '::' . $const->name; foreach ($codebase->class_constants_to_rename as $original_const_id => $new_const_name) { if ($const_id === $original_const_id) { $file_manipulations = [new \Psalm\FileManipulation((int) $const->name->getAttribute('startFilePos'), (int) $const->name->getAttribute('endFilePos') + 1, $new_const_name)]; \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($this->getFilePath(), $file_manipulations); } } } } } $statements_analyzer = new \Psalm\Internal\Analyzer\StatementsAnalyzer($this, new \Psalm\Internal\Provider\NodeDataProvider()); $statements_analyzer->analyze($member_stmts, $class_context, $global_context, \true); $config = \Psalm\Config::getInstance(); $this->checkPropertyInitialization($codebase, $config, $storage, $class_context, $global_context, $constructor_analyzer); foreach ($class->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property && !isset($stmt->type)) { $this->checkForMissingPropertyType($this, $stmt, $class_context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { foreach ($stmt->traits as $trait) { $fq_trait_name = self::getFQCLNFromNameObject($trait, $this->source->getAliases()); try { $trait_file_analyzer = $project_analyzer->getFileAnalyzerForClassLike($fq_trait_name); } catch (\Exception $e) { continue; } $trait_storage = $codebase->classlike_storage_provider->get($fq_trait_name); $trait_node = $codebase->classlikes->getTraitNode($fq_trait_name); $trait_aliases = $trait_storage->aliases; if ($trait_aliases === null) { continue; } $trait_analyzer = new \Psalm\Internal\Analyzer\TraitAnalyzer($trait_node, $trait_file_analyzer, $fq_trait_name, $trait_aliases); $fq_trait_name_lc = \strtolower($fq_trait_name); if (isset($storage->template_type_uses_count[$fq_trait_name_lc])) { $expected_param_count = $storage->template_type_uses_count[$fq_trait_name_lc]; $this->checkTemplateParams($codebase, $storage, $trait_storage, new \Psalm\CodeLocation($this, $trait), $expected_param_count); } foreach ($trait_node->stmts as $trait_stmt) { if ($trait_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { $this->checkForMissingPropertyType($trait_analyzer, $trait_stmt, $class_context); } } $trait_file_analyzer->clearSourceBeforeDestruction(); } } } $pseudo_methods = $storage->pseudo_methods + $storage->pseudo_static_methods; foreach ($pseudo_methods as $pseudo_method_name => $pseudo_method_storage) { $pseudo_method_id = new \Psalm\Internal\MethodIdentifier($this->fq_class_name, $pseudo_method_name); $overridden_method_ids = $codebase->methods->getOverriddenMethodIds($pseudo_method_id); if ($overridden_method_ids && $pseudo_method_name !== '__construct' && $pseudo_method_storage->location) { foreach ($overridden_method_ids as $overridden_method_id) { $parent_method_storage = $codebase->methods->getStorage($overridden_method_id); $overridden_fq_class_name = $overridden_method_id->fq_class_name; $parent_storage = $classlike_storage_provider->get($overridden_fq_class_name); \Psalm\Internal\Analyzer\MethodComparator::compare($codebase, null, $storage, $parent_storage, $pseudo_method_storage, $parent_method_storage, $this->fq_class_name, $pseudo_method_storage->visibility ?: 0, $storage->location ?: $pseudo_method_storage->location, $storage->suppressed_issues, \true, \false); } } } $plugin_classes = $codebase->config->after_classlike_checks; if ($plugin_classes) { $file_manipulations = []; foreach ($plugin_classes as $plugin_fq_class_name) { if ($plugin_fq_class_name::afterStatementAnalysis($class, $storage, $this, $codebase, $file_manipulations) === \false) { return \false; } } if ($file_manipulations) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($this->getFilePath(), $file_manipulations); } } return null; } public static function addContextProperties(\Psalm\StatementsSource $statements_source, \Psalm\Storage\ClassLikeStorage $storage, \Psalm\Context $class_context, string $fq_class_name, ?string $parent_fq_class_name, array $stmts = []) : void { $codebase = $statements_source->getCodebase(); foreach ($storage->appearing_property_ids as $property_name => $appearing_property_id) { $property_class_name = $codebase->properties->getDeclaringClassForProperty($appearing_property_id, \true); if ($property_class_name === null) { continue; } $property_class_storage = $codebase->classlike_storage_provider->get($property_class_name); $property_storage = $property_class_storage->properties[$property_name]; if (isset($storage->overridden_property_ids[$property_name])) { foreach ($storage->overridden_property_ids[$property_name] as $overridden_property_id) { [$guide_class_name] = \explode('::$', $overridden_property_id); $guide_class_storage = $codebase->classlike_storage_provider->get($guide_class_name); $guide_property_storage = $guide_class_storage->properties[$property_name]; if ($property_storage->visibility > $guide_property_storage->visibility && $property_storage->location) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\OverriddenPropertyAccess('Property ' . $guide_class_storage->name . '::$' . $property_name . ' has different access level than ' . $storage->name . '::$' . $property_name, $property_storage->location))) { // fall through } continue; } } } if ($property_storage->type) { $property_type = clone $property_storage->type; if (!$property_type->isMixed() && !$property_storage->has_default && !($property_type->isNullable() && $property_type->from_docblock)) { $property_type->initialized = \false; } } else { $property_type = \Psalm\Type::getMixed(); if (!$property_storage->has_default) { $property_type->initialized = \false; } } $property_type_location = $property_storage->type_location; $fleshed_out_type = !$property_type->isMixed() ? \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $property_type, $fq_class_name, $fq_class_name, $parent_fq_class_name, \true, \false, $storage->final) : $property_type; $class_template_params = \Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector::collect($codebase, $property_class_storage, $storage, null, new \Psalm\Type\Atomic\TNamedObject($fq_class_name), '$this'); $template_result = new \Psalm\Internal\Type\TemplateResult($class_template_params ?: [], []); if ($class_template_params) { $fleshed_out_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($fleshed_out_type, $template_result, $codebase, null, null, null, $class_context->self); } if ($property_type_location && !$fleshed_out_type->isMixed()) { $stmt = \array_filter($stmts, function ($stmt) use($property_name) : bool { return $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property && isset($stmt->props[0]->name->name) && $stmt->props[0]->name->name === $property_name; }); $suppressed = []; if (\count($stmt) > 0) { /** @var PhpParser\Node\Stmt\Property $stmt */ $stmt = \array_pop($stmt); $docComment = $stmt->getDocComment(); if ($docComment) { try { $docBlock = \Psalm\DocComment::parsePreservingLength($docComment); $suppressed = $docBlock->tags['psalm-suppress'] ?? []; } catch (\Psalm\Exception\DocblockParseException $e) { // do nothing to keep original behavior } } } $fleshed_out_type->check($statements_source, $property_type_location, $storage->suppressed_issues + $statements_source->getSuppressedIssues() + $suppressed, [], \false); } if ($property_storage->is_static) { $property_id = $fq_class_name . '::$' . $property_name; $class_context->vars_in_scope[$property_id] = $fleshed_out_type; } else { $class_context->vars_in_scope['$this->' . $property_name] = $fleshed_out_type; } } foreach ($storage->pseudo_property_get_types as $property_name => $property_type) { $property_name = \substr($property_name, 1); if (isset($class_context->vars_in_scope['$this->' . $property_name])) { $fleshed_out_type = !$property_type->isMixed() ? \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $property_type, $fq_class_name, $fq_class_name, $parent_fq_class_name) : $property_type; $class_context->vars_in_scope['$this->' . $property_name] = $fleshed_out_type; } } } private function checkPropertyInitialization(\Psalm\Codebase $codebase, \Psalm\Config $config, \Psalm\Storage\ClassLikeStorage $storage, \Psalm\Context $class_context, ?\Psalm\Context $global_context = null, ?\Psalm\Internal\Analyzer\MethodAnalyzer $constructor_analyzer = null) : void { if (!$config->reportIssueInFile('PropertyNotSetInConstructor', $this->getFilePath())) { return; } if (!isset($storage->declaring_method_ids['__construct']) && !$config->reportIssueInFile('MissingConstructor', $this->getFilePath())) { return; } $fq_class_name = $class_context->self ? $class_context->self : $this->fq_class_name; $fq_class_name_lc = \strtolower($fq_class_name); $included_file_path = $this->getFilePath(); $method_already_analyzed = $codebase->analyzer->isMethodAlreadyAnalyzed($included_file_path, $fq_class_name_lc . '::__construct', \true); if ($method_already_analyzed && !$codebase->diff_methods) { // this can happen when re-analysing a class that has been include()d inside another return; } /** @var PhpParser\Node\Stmt\Class_ */ $class = $this->class; $classlike_storage_provider = $codebase->classlike_storage_provider; $class_storage = $classlike_storage_provider->get($fq_class_name_lc); $constructor_appearing_fqcln = $fq_class_name_lc; $uninitialized_variables = []; $uninitialized_properties = []; $uninitialized_typed_properties = []; $uninitialized_private_properties = \false; foreach ($storage->appearing_property_ids as $property_name => $appearing_property_id) { $property_class_name = $codebase->properties->getDeclaringClassForProperty($appearing_property_id, \true); if ($property_class_name === null) { continue; } $property_class_storage = $classlike_storage_provider->get($property_class_name); $property = $property_class_storage->properties[$property_name]; $property_is_initialized = isset($property_class_storage->initialized_properties[$property_name]); if ($property->is_static) { continue; } if ($property->has_default || $property_is_initialized) { continue; } if ($property->type && $property->type->isNullable() && $property->type->from_docblock) { continue; } if ($codebase->diff_methods && $method_already_analyzed && $property->location) { [$start, $end] = $property->location->getSelectionBounds(); $existing_issues = $codebase->analyzer->getExistingIssuesForFile($this->getFilePath(), $start, $end, 'PropertyNotSetInConstructor'); if ($existing_issues) { \Psalm\IssueBuffer::addIssues([$this->getFilePath() => $existing_issues]); continue; } } if ($property->location) { $codebase->analyzer->removeExistingDataForFile($this->getFilePath(), $property->location->raw_file_start, $property->location->raw_file_end, 'PropertyNotSetInConstructor'); } $codebase->file_reference_provider->addMethodReferenceToMissingClassMember($fq_class_name_lc . '::__construct', \strtolower($property_class_name) . '::$' . $property_name); if ($property->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { $uninitialized_private_properties = \true; } $uninitialized_variables[] = '$this->' . $property_name; $uninitialized_properties[$property_class_name . '::$' . $property_name] = $property; if ($property->type && !$property->type->isMixed()) { $uninitialized_typed_properties[$property_class_name . '::$' . $property_name] = $property; } } if (!$uninitialized_properties) { return; } if (!$storage->abstract && !$constructor_analyzer && isset($storage->declaring_method_ids['__construct']) && isset($storage->appearing_method_ids['__construct']) && $class->extends) { $constructor_declaring_fqcln = $storage->declaring_method_ids['__construct']->fq_class_name; $constructor_appearing_fqcln = $storage->appearing_method_ids['__construct']->fq_class_name; $constructor_class_storage = $classlike_storage_provider->get($constructor_declaring_fqcln); // ignore oldstyle constructors and classes without any declared properties if ($constructor_class_storage->user_defined && !$constructor_class_storage->stubbed && isset($constructor_class_storage->methods['__construct'])) { $constructor_storage = $constructor_class_storage->methods['__construct']; $fake_constructor_params = \array_map(function (\Psalm\Storage\FunctionLikeParameter $param) : PhpParser\Node\Param { $fake_param = new \_HumbugBoxd02f763d3c56\PhpParser\Builder\Param($param->name); if ($param->signature_type) { $fake_param->setType((string) $param->signature_type); } return $fake_param->getNode(); }, $constructor_storage->params); $fake_constructor_stmt_args = \array_map(function (\Psalm\Storage\FunctionLikeParameter $param) : PhpParser\Node\Arg { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($param->name)); }, $constructor_storage->params); $fake_constructor_stmts = [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($constructor_declaring_fqcln), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('__construct'), $fake_constructor_stmt_args, ['startLine' => $class->extends->getLine(), 'startFilePos' => $class->extends->getAttribute('startFilePos'), 'endFilePos' => $class->extends->getAttribute('endFilePos'), 'comments' => [new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc('/** @psalm-suppress InaccessibleMethod */', $class->extends->getLine(), (int) $class->extends->getAttribute('startFilePos'))]]), ['startLine' => $class->extends->getLine(), 'startFilePos' => $class->extends->getAttribute('startFilePos'), 'endFilePos' => $class->extends->getAttribute('endFilePos'), 'comments' => [new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc('/** @psalm-suppress InaccessibleMethod */', $class->extends->getLine(), (int) $class->extends->getAttribute('startFilePos'))]])]; $fake_stmt = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('__construct'), ['type' => \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC, 'params' => $fake_constructor_params, 'stmts' => $fake_constructor_stmts], ['startLine' => $class->extends->getLine(), 'startFilePos' => $class->extends->getAttribute('startFilePos'), 'endFilePos' => $class->extends->getAttribute('endFilePos')]); $codebase->analyzer->disableMixedCounts(); $was_collecting_initializations = $class_context->collect_initializations; $class_context->collect_initializations = \true; $class_context->collect_nonprivate_initializations = !$uninitialized_private_properties; $constructor_analyzer = $this->analyzeClassMethod($fake_stmt, $storage, $this, $class_context, $global_context, \true); $class_context->collect_initializations = $was_collecting_initializations; $codebase->analyzer->enableMixedCounts(); } } if ($constructor_analyzer) { $method_context = clone $class_context; $method_context->collect_initializations = \true; $method_context->collect_nonprivate_initializations = !$uninitialized_private_properties; $method_context->self = $fq_class_name; $this_atomic_object_type = new \Psalm\Type\Atomic\TNamedObject($fq_class_name); $this_atomic_object_type->was_static = !$storage->final; $method_context->vars_in_scope['$this'] = new \Psalm\Type\Union([$this_atomic_object_type]); $method_context->vars_possibly_in_scope['$this'] = \true; $method_context->calling_method_id = \strtolower($fq_class_name) . '::__construct'; $constructor_analyzer->analyze($method_context, new \Psalm\Internal\Provider\NodeDataProvider(), $global_context, \true); foreach ($uninitialized_properties as $property_id => $property_storage) { [, $property_name] = \explode('::$', $property_id); if (!isset($method_context->vars_in_scope['$this->' . $property_name])) { $end_type = \Psalm\Type::getVoid(); $end_type->initialized = \false; } else { $end_type = $method_context->vars_in_scope['$this->' . $property_name]; } $constructor_class_property_storage = $property_storage; $error_location = $property_storage->location; if ($storage->declaring_property_ids[$property_name] !== $fq_class_name) { $error_location = $storage->location ?: $storage->stmt_location; } if ($fq_class_name_lc !== $constructor_appearing_fqcln && $property_storage->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { $a_class_storage = $classlike_storage_provider->get($end_type->initialized_class ?: $constructor_appearing_fqcln); if (!isset($a_class_storage->declaring_property_ids[$property_name])) { $constructor_class_property_storage = null; } else { $declaring_property_class = $a_class_storage->declaring_property_ids[$property_name]; $constructor_class_property_storage = $classlike_storage_provider->get($declaring_property_class)->properties[$property_name]; } } if ($property_storage->location && $error_location && (!$end_type->initialized || $property_storage !== $constructor_class_property_storage)) { if ($property_storage->type) { $expected_visibility = $uninitialized_private_properties ? 'private or final ' : ''; if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PropertyNotSetInConstructor('Property ' . $class_storage->name . '::$' . $property_name . ' is not defined in constructor of ' . $this->fq_class_name . ' and in any ' . $expected_visibility . 'methods called in the constructor', $error_location, $property_id), $storage->suppressed_issues + $this->getSuppressedIssues())) { // do nothing } } elseif (!$property_storage->has_default) { if (isset($this->inferred_property_types[$property_name])) { $this->inferred_property_types[$property_name]->addType(new \Psalm\Type\Atomic\TNull()); $this->inferred_property_types[$property_name]->setFromDocblock(); } } } } $codebase->analyzer->setAnalyzedMethod($included_file_path, $fq_class_name_lc . '::__construct', \true); return; } if (!$storage->abstract && $uninitialized_typed_properties) { foreach ($uninitialized_typed_properties as $id => $uninitialized_property) { if ($uninitialized_property->location) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingConstructor($class_storage->name . ' has an uninitialized property ' . $id . ', but no constructor', $uninitialized_property->location, $class_storage->name . '::' . $uninitialized_variables[0]), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } } } } /** * @return false|null */ private function analyzeTraitUse(\Psalm\Aliases $aliases, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse $stmt, \Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, \Psalm\Storage\ClassLikeStorage $storage, \Psalm\Context $class_context, ?\Psalm\Context $global_context = null, ?\Psalm\Internal\Analyzer\MethodAnalyzer &$constructor_analyzer = null, ?\Psalm\Internal\Analyzer\TraitAnalyzer $previous_trait_analyzer = null) : ?bool { $codebase = $this->getCodebase(); $previous_context_include_location = $class_context->include_location; foreach ($stmt->traits as $trait_name) { $trait_location = new \Psalm\CodeLocation($this, $trait_name, null, \true); $class_context->include_location = new \Psalm\CodeLocation($this, $trait_name, null, \true); $fq_trait_name = self::getFQCLNFromNameObject($trait_name, $aliases); if (!$codebase->classlikes->hasFullyQualifiedTraitName($fq_trait_name, $trait_location)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedTrait('Trait ' . $fq_trait_name . ' does not exist', new \Psalm\CodeLocation($previous_trait_analyzer ?: $this, $trait_name)), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } return \false; } else { if (!$codebase->traitHasCorrectCase($fq_trait_name)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedTrait('Trait ' . $fq_trait_name . ' has wrong casing', new \Psalm\CodeLocation($previous_trait_analyzer ?: $this, $trait_name)), $storage->suppressed_issues + $this->getSuppressedIssues())) { return \false; } continue; } $fq_trait_name_resolved = $codebase->classlikes->getUnAliasedName($fq_trait_name); $trait_storage = $codebase->classlike_storage_provider->get($fq_trait_name_resolved); if ($trait_storage->deprecated) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedTrait('Trait ' . $fq_trait_name . ' is deprecated', new \Psalm\CodeLocation($previous_trait_analyzer ?: $this, $trait_name)), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if ($trait_storage->extension_requirement !== null) { $extension_requirement = $codebase->classlikes->getUnAliasedName($trait_storage->extension_requirement); $extensionRequirementMet = \in_array($extension_requirement, $storage->parent_classes); if (!$extensionRequirementMet) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ExtensionRequirementViolation($fq_trait_name . ' requires using class to extend ' . $extension_requirement . ', but ' . $storage->name . ' does not', new \Psalm\CodeLocation($previous_trait_analyzer ?: $this, $trait_name)), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } } foreach ($trait_storage->implementation_requirements as $implementation_requirement) { $implementation_requirement = $codebase->classlikes->getUnAliasedName($implementation_requirement); $implementationRequirementMet = \in_array($implementation_requirement, $storage->class_implements); if (!$implementationRequirementMet) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImplementationRequirementViolation($fq_trait_name . ' requires using class to implement ' . $implementation_requirement . ', but ' . $storage->name . ' does not', new \Psalm\CodeLocation($previous_trait_analyzer ?: $this, $trait_name)), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } } if ($storage->mutation_free && !$trait_storage->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MutableDependency($storage->name . ' is marked immutable but ' . $fq_trait_name . ' is not', new \Psalm\CodeLocation($previous_trait_analyzer ?: $this, $trait_name)), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } $trait_file_analyzer = $project_analyzer->getFileAnalyzerForClassLike($fq_trait_name_resolved); $trait_node = $codebase->classlikes->getTraitNode($fq_trait_name_resolved); $trait_aliases = $trait_storage->aliases; if ($trait_aliases === null) { continue; } $trait_analyzer = new \Psalm\Internal\Analyzer\TraitAnalyzer($trait_node, $trait_file_analyzer, $fq_trait_name_resolved, $trait_aliases); foreach ($trait_node->stmts as $trait_stmt) { if ($trait_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $trait_method_analyzer = $this->analyzeClassMethod($trait_stmt, $storage, $trait_analyzer, $class_context, $global_context); if ($trait_stmt->name->name === '__construct') { $constructor_analyzer = $trait_method_analyzer; } } elseif ($trait_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { if ($this->analyzeTraitUse($trait_aliases, $trait_stmt, $project_analyzer, $storage, $class_context, $global_context, $constructor_analyzer, $trait_analyzer) === \false) { return \false; } } } $trait_file_analyzer->clearSourceBeforeDestruction(); } } $class_context->include_location = $previous_context_include_location; return null; } private function checkForMissingPropertyType(\Psalm\StatementsSource $source, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property $stmt, \Psalm\Context $context) : void { $fq_class_name = $source->getFQCLN(); $property_name = $stmt->props[0]->name->name; $codebase = $this->getCodebase(); $property_id = $fq_class_name . '::$' . $property_name; $declaring_property_class = $codebase->properties->getDeclaringClassForProperty($property_id, \true); if (!$declaring_property_class) { return; } $fq_class_name = $declaring_property_class; // gets inherited property type $class_property_type = $codebase->properties->getPropertyType($property_id, \false, $source, $context); $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $property_storage = $class_storage->properties[$property_name]; if ($class_property_type && ($property_storage->type_location || !$codebase->alter_code)) { return; } $message = 'Property ' . $property_id . ' does not have a declared type'; $suggested_type = $property_storage->suggested_type; if (isset($this->inferred_property_types[$property_name])) { $suggested_type = $suggested_type ? \Psalm\Type::combineUnionTypes($suggested_type, $this->inferred_property_types[$property_name], $codebase) : $this->inferred_property_types[$property_name]; } if ($suggested_type && !$property_storage->has_default && $property_storage->is_static) { $suggested_type->addType(new \Psalm\Type\Atomic\TNull()); } if ($suggested_type && !$suggested_type->isNull()) { $message .= ' - consider ' . \str_replace(['', ''], '', (string) $suggested_type); } $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); if ($codebase->alter_code && $source === $this && isset($project_analyzer->getIssuesToFix()['MissingPropertyType']) && !\in_array('MissingPropertyType', $this->getSuppressedIssues()) && $suggested_type) { if ($suggested_type->hasMixed() || $suggested_type->isNull()) { return; } self::addOrUpdatePropertyType($project_analyzer, $stmt, $suggested_type, $this, $suggested_type->from_docblock); return; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingPropertyType($message, new \Psalm\CodeLocation($source, $stmt->props[0]->name), $property_id), $this->source->getSuppressedIssues())) { // fall through } } private static function addOrUpdatePropertyType(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property $property, \Psalm\Type\Union $inferred_type, \Psalm\StatementsSource $source, bool $docblock_only = \false) : void { $manipulator = \Psalm\Internal\FileManipulation\PropertyDocblockManipulator::getForProperty($project_analyzer, $source->getFilePath(), $property); $codebase = $project_analyzer->getCodebase(); $allow_native_type = !$docblock_only && $codebase->php_major_version >= 7 && ($codebase->php_major_version > 7 || $codebase->php_minor_version >= 4) && $codebase->allow_backwards_incompatible_changes; $manipulator->setType($allow_native_type ? (string) $inferred_type->toPhpString($source->getNamespace(), $source->getAliasedClassesFlipped(), $source->getFQCLN(), $codebase->php_major_version, $codebase->php_minor_version) : null, $inferred_type->toNamespacedString($source->getNamespace(), $source->getAliasedClassesFlipped(), $source->getFQCLN(), \false), $inferred_type->toNamespacedString($source->getNamespace(), $source->getAliasedClassesFlipped(), $source->getFQCLN(), \true), $inferred_type->canBeFullyExpressedInPhp()); } private function analyzeClassMethod(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod $stmt, \Psalm\Storage\ClassLikeStorage $class_storage, \Psalm\Internal\Analyzer\SourceAnalyzer $source, \Psalm\Context $class_context, ?\Psalm\Context $global_context = null, bool $is_fake = \false) : ?\Psalm\Internal\Analyzer\MethodAnalyzer { $config = \Psalm\Config::getInstance(); if ($stmt->stmts === null && !$stmt->isAbstract()) { \Psalm\IssueBuffer::add(new \Psalm\Issue\ParseError('Non-abstract class method must have statements', new \Psalm\CodeLocation($this, $stmt))); return null; } try { $method_analyzer = new \Psalm\Internal\Analyzer\MethodAnalyzer($stmt, $source); } catch (\UnexpectedValueException $e) { \Psalm\IssueBuffer::add(new \Psalm\Issue\ParseError('Problem loading method: ' . $e->getMessage(), new \Psalm\CodeLocation($this, $stmt))); return null; } $actual_method_id = $method_analyzer->getMethodId(); $project_analyzer = $source->getProjectAnalyzer(); $codebase = $source->getCodebase(); $analyzed_method_id = $actual_method_id; $included_file_path = $source->getFilePath(); if ($class_context->self && \strtolower($class_context->self) !== \strtolower((string) $source->getFQCLN())) { $analyzed_method_id = $method_analyzer->getMethodId($class_context->self); $declaring_method_id = $codebase->methods->getDeclaringMethodId($analyzed_method_id); if ((string) $actual_method_id !== (string) $declaring_method_id) { // the method is an abstract trait method $declaring_method_storage = $method_analyzer->getFunctionLikeStorage(); if (!$declaring_method_storage instanceof \Psalm\Storage\MethodStorage) { throw new \LogicException('This should never happen'); } if ($declaring_method_id && $declaring_method_storage->abstract) { $implementer_method_storage = $codebase->methods->getStorage($declaring_method_id); $declaring_storage = $codebase->classlike_storage_provider->get($actual_method_id->fq_class_name); \Psalm\Internal\Analyzer\MethodComparator::compare($codebase, null, $class_storage, $declaring_storage, $implementer_method_storage, $declaring_method_storage, $this->fq_class_name, $implementer_method_storage->visibility, new \Psalm\CodeLocation($source, $stmt), $implementer_method_storage->suppressed_issues, \false); } return null; } } $trait_safe_method_id = \strtolower((string) $analyzed_method_id); $actual_method_id_str = \strtolower((string) $actual_method_id); if ($actual_method_id_str !== $trait_safe_method_id) { $trait_safe_method_id .= '&' . $actual_method_id_str; } $method_already_analyzed = $codebase->analyzer->isMethodAlreadyAnalyzed($included_file_path, $trait_safe_method_id); $start = (int) $stmt->getAttribute('startFilePos'); $end = (int) $stmt->getAttribute('endFilePos'); $comments = $stmt->getComments(); if ($comments) { $start = $comments[0]->getStartFilePos(); } if ($codebase->diff_methods && $method_already_analyzed && !$class_context->collect_initializations && !$class_context->collect_mutations && !$is_fake) { $project_analyzer->progress->debug('Skipping analysis of pre-analyzed method ' . $analyzed_method_id . "\n"); $existing_issues = $codebase->analyzer->getExistingIssuesForFile($source->getFilePath(), $start, $end); \Psalm\IssueBuffer::addIssues([$source->getFilePath() => $existing_issues]); return $method_analyzer; } $codebase->analyzer->removeExistingDataForFile($source->getFilePath(), $start, $end); $method_context = clone $class_context; foreach ($method_context->vars_in_scope as $context_var_id => $context_type) { $method_context->vars_in_scope[$context_var_id] = clone $context_type; } $method_context->collect_exceptions = $config->check_for_throws_docblock; $type_provider = new \Psalm\Internal\Provider\NodeDataProvider(); $method_analyzer->analyze($method_context, $type_provider, $global_context ? clone $global_context : null); if ($stmt->name->name !== '__construct' && $config->reportIssueInFile('InvalidReturnType', $source->getFilePath()) && $class_context->self) { self::analyzeClassMethodReturnType($stmt, $method_analyzer, $source, $type_provider, $codebase, $class_storage, $class_context->self, $analyzed_method_id, $actual_method_id, $method_context->has_returned); } if (!$method_already_analyzed && !$class_context->collect_initializations && !$class_context->collect_mutations && !$is_fake) { $codebase->analyzer->setAnalyzedMethod($included_file_path, $trait_safe_method_id); } return $method_analyzer; } public static function analyzeClassMethodReturnType(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod $stmt, \Psalm\Internal\Analyzer\MethodAnalyzer $method_analyzer, \Psalm\Internal\Analyzer\SourceAnalyzer $source, \Psalm\Internal\Provider\NodeDataProvider $type_provider, \Psalm\Codebase $codebase, \Psalm\Storage\ClassLikeStorage $class_storage, string $fq_classlike_name, \Psalm\Internal\MethodIdentifier $analyzed_method_id, \Psalm\Internal\MethodIdentifier $actual_method_id, bool $did_explicitly_return) : void { $secondary_return_type_location = null; $actual_method_storage = $codebase->methods->getStorage($actual_method_id); $return_type_location = $codebase->methods->getMethodReturnTypeLocation($actual_method_id, $secondary_return_type_location); $original_fq_classlike_name = $fq_classlike_name; $return_type = $codebase->methods->getMethodReturnType($analyzed_method_id, $fq_classlike_name, $method_analyzer); if ($return_type && $class_storage->template_type_extends) { $declaring_method_id = $codebase->methods->getDeclaringMethodId($analyzed_method_id); if ($declaring_method_id) { $declaring_class_name = $declaring_method_id->fq_class_name; $class_storage = $codebase->classlike_storage_provider->get($declaring_class_name); } if ($class_storage->template_types) { $template_params = []; foreach ($class_storage->template_types as $param_name => $template_map) { $key = \array_keys($template_map)[0]; $template_params[] = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParam($param_name, \reset($template_map)[0], $key)]); } $this_object_type = new \Psalm\Type\Atomic\TGenericObject($original_fq_classlike_name, $template_params); } else { $this_object_type = new \Psalm\Type\Atomic\TNamedObject($original_fq_classlike_name); } $class_template_params = \Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector::collect($codebase, $class_storage, $codebase->classlike_storage_provider->get($original_fq_classlike_name), \strtolower($stmt->name->name), $this_object_type) ?: []; $template_result = new \Psalm\Internal\Type\TemplateResult($class_template_params ?: [], []); $return_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($return_type, $template_result, $codebase, null, null, null, $original_fq_classlike_name); } $overridden_method_ids = isset($class_storage->overridden_method_ids[\strtolower($stmt->name->name)]) ? $class_storage->overridden_method_ids[\strtolower($stmt->name->name)] : []; if (!$return_type && !$class_storage->is_interface && $overridden_method_ids) { foreach ($overridden_method_ids as $interface_method_id) { $interface_class = $interface_method_id->fq_class_name; if (!$codebase->classlikes->interfaceExists($interface_class)) { continue; } $interface_return_type = $codebase->methods->getMethodReturnType($interface_method_id, $interface_class); $interface_return_type_location = $codebase->methods->getMethodReturnTypeLocation($interface_method_id); \Psalm\Internal\Analyzer\FunctionLike\ReturnTypeAnalyzer::verifyReturnType($stmt, $stmt->getStmts() ?: [], $source, $type_provider, $method_analyzer, $interface_return_type, $interface_class, $interface_return_type_location, [$analyzed_method_id], $did_explicitly_return); } } if ($actual_method_storage->overridden_downstream) { $overridden_method_ids['overridden::downstream'] = 'overridden::downstream'; } \Psalm\Internal\Analyzer\FunctionLike\ReturnTypeAnalyzer::verifyReturnType($stmt, $stmt->getStmts() ?: [], $source, $type_provider, $method_analyzer, $return_type, $fq_classlike_name, $return_type_location, $overridden_method_ids, $did_explicitly_return); } private function checkTemplateParams(\Psalm\Codebase $codebase, \Psalm\Storage\ClassLikeStorage $storage, \Psalm\Storage\ClassLikeStorage $parent_storage, \Psalm\CodeLocation $code_location, int $expected_param_count) : void { $template_type_count = $parent_storage->template_types === null ? 0 : \count($parent_storage->template_types); if ($template_type_count > $expected_param_count) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingTemplateParam($storage->name . ' has missing template params, expecting ' . $template_type_count, $code_location), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } elseif ($template_type_count < $expected_param_count) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooManyTemplateParams($storage->name . ' has too many template params, expecting ' . $template_type_count, $code_location), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } if ($parent_storage->template_types && $storage->template_type_extends) { $i = 0; $previous_extended = []; foreach ($parent_storage->template_types as $template_name => $type_map) { foreach ($type_map as $declaring_class => $template_type) { if (isset($storage->template_type_extends[$parent_storage->name][$template_name])) { $extended_type = $storage->template_type_extends[$parent_storage->name][$template_name]; if (isset($parent_storage->template_covariants[$i]) && !$parent_storage->template_covariants[$i]) { foreach ($extended_type->getAtomicTypes() as $t) { if ($t instanceof \Psalm\Type\Atomic\TTemplateParam && $storage->template_types && $storage->template_covariants && ($local_offset = \array_search($t->param_name, \array_keys($storage->template_types))) !== \false && !empty($storage->template_covariants[$local_offset])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidTemplateParam('Cannot extend an invariant template param ' . $template_name . ' into a covariant context', $code_location), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } } } if (!$template_type[0]->isMixed()) { $template_type_copy = clone $template_type[0]; $template_result = new \Psalm\Internal\Type\TemplateResult($previous_extended ?: [], []); $template_type_copy = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($template_type_copy, $template_result, $codebase, null, $extended_type, null, null); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $extended_type, $template_type_copy)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidTemplateParam('Extended template param ' . $template_name . ' expects type ' . $template_type_copy->getId() . ', type ' . $extended_type->getId() . ' given', $code_location), $storage->suppressed_issues + $this->getSuppressedIssues())) { // fall through } } else { $previous_extended[$template_name] = [$declaring_class => [$extended_type]]; } } else { $previous_extended[$template_name] = [$declaring_class => [$extended_type]]; } } } $i++; } } } } getCodebase(); $file_storage_provider = $codebase->file_storage_provider; $file_storage = $file_storage_provider->get($source->getFilePath()); $namespace = $source->getNamespace(); $function_id = ($namespace ? \strtolower($namespace) . '\\' : '') . \strtolower($function->name->name); if (!isset($file_storage->functions[$function_id])) { throw new \UnexpectedValueException('Function ' . $function_id . ' should be defined in ' . $source->getFilePath()); } $storage = $file_storage->functions[$function_id]; parent::__construct($function, $source, $storage); } /** * @return non-empty-lowercase-string */ public function getFunctionId() : string { $namespace = $this->source->getNamespace(); /** @var non-empty-lowercase-string */ return ($namespace ? \strtolower($namespace) . '\\' : '') . \strtolower($this->function->name->name); } public static function analyzeStatement(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ $stmt, \Psalm\Context $context) : void { foreach ($stmt->stmts as $function_stmt) { if ($function_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Global_) { foreach ($function_stmt->vars as $var) { if ($var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { if (\is_string($var->name)) { $var_id = '$' . $var->name; // registers variable in global context $context->hasVariable($var_id); } } } } elseif (!$function_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop) { break; } } $codebase = $statements_analyzer->getCodebase(); if (!$codebase->register_stub_files && !$codebase->register_autoload_files) { $function_name = \strtolower($stmt->name->name); if ($ns = $statements_analyzer->getNamespace()) { $fq_function_name = \strtolower($ns) . '\\' . $function_name; } else { $fq_function_name = $function_name; } $function_context = new \Psalm\Context($context->self); $function_context->strict_types = $context->strict_types; $config = \Psalm\Config::getInstance(); $function_context->collect_exceptions = $config->check_for_throws_docblock; if ($function_analyzer = $statements_analyzer->getFunctionAnalyzer($fq_function_name)) { $function_analyzer->analyze($function_context, $statements_analyzer->node_data, $context); if ($config->reportIssueInFile('InvalidReturnType', $statements_analyzer->getFilePath())) { $method_id = $function_analyzer->getId(); $function_storage = $codebase->functions->getStorage($statements_analyzer, \strtolower($method_id)); $return_type = $function_storage->return_type; $return_type_location = $function_storage->return_type_location; $function_analyzer->verifyReturnType($stmt->getStmts(), $statements_analyzer, $return_type, $statements_analyzer->getFQCLN(), $return_type_location, $function_context->has_returned); } } } } } */ public $taint_trace; /** * @var ?string * @readonly */ public $dupe_key; /** * @param ?list $taint_trace */ public function __construct(string $severity, int $line_from, int $line_to, string $type, string $message, string $file_name, string $file_path, string $snippet, string $selected_text, int $from, int $to, int $snippet_from, int $snippet_to, int $column_from, int $column_to, int $shortcode = 0, int $error_level = -1, ?array $taint_trace = null, ?string $dupe_key = null) { $this->severity = $severity; $this->line_from = $line_from; $this->line_to = $line_to; $this->type = $type; $this->message = $message; $this->file_name = $file_name; $this->file_path = $file_path; $this->snippet = $snippet; $this->selected_text = $selected_text; $this->from = $from; $this->to = $to; $this->snippet_from = $snippet_from; $this->snippet_to = $snippet_to; $this->column_from = $column_from; $this->column_to = $column_to; $this->shortcode = $shortcode; $this->error_level = $error_level; $this->link = 'https://psalm.dev/' . \str_pad((string) $shortcode, 3, "0", \STR_PAD_LEFT); $this->taint_trace = $taint_trace; $this->dupe_key = $dupe_key; } } > */ protected static $public_namespace_constants = []; public function __construct(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_ $namespace, \Psalm\Internal\Analyzer\FileAnalyzer $source) { $this->source = $source; $this->namespace = $namespace; $this->namespace_name = $this->namespace->name ? \implode('\\', $this->namespace->name->parts) : ''; } public function collectAnalyzableInformation() : void { $leftover_stmts = []; if (!isset(self::$public_namespace_constants[$this->namespace_name])) { self::$public_namespace_constants[$this->namespace_name] = []; } $codebase = $this->getCodebase(); foreach ($this->namespace->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike) { $this->collectAnalyzableClassLike($stmt); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_) { $this->visitUse($stmt); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { $this->visitGroupUse($stmt); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_) { foreach ($stmt->consts as $const) { self::$public_namespace_constants[$this->namespace_name][$const->name->name] = \Psalm\Type::getMixed(); } $leftover_stmts[] = $stmt; } else { $leftover_stmts[] = $stmt; } } if ($leftover_stmts) { $statements_analyzer = new \Psalm\Internal\Analyzer\StatementsAnalyzer($this, new \Psalm\Internal\Provider\NodeDataProvider()); $context = new \Psalm\Context(); $context->is_global = \true; $context->defineGlobals(); $context->collect_exceptions = $codebase->config->check_for_throws_in_global_scope; $statements_analyzer->analyze($leftover_stmts, $context, null, \true); $file_context = $this->source->context; if ($file_context) { $file_context->mergeExceptions($context); } } } public function collectAnalyzableClassLike(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike $stmt) : void { if (!$stmt->name) { throw new \UnexpectedValueException('Did not expect anonymous class here'); } $fq_class_name = \Psalm\Type::getFQCLNFromString($stmt->name->name, $this->getAliases()); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { $this->source->addNamespacedClassAnalyzer($fq_class_name, new \Psalm\Internal\Analyzer\ClassAnalyzer($stmt, $this, $fq_class_name)); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_) { $this->source->addNamespacedInterfaceAnalyzer($fq_class_name, new \Psalm\Internal\Analyzer\InterfaceAnalyzer($stmt, $this, $fq_class_name)); } } public function getNamespace() : string { return $this->namespace_name; } public function setConstType(string $const_name, \Psalm\Type\Union $const_type) : void { self::$public_namespace_constants[$this->namespace_name][$const_name] = $const_type; } /** * @return array */ public static function getConstantsForNamespace(string $namespace_name, int $visibility) : array { // @todo this does not allow for loading in namespace constants not already defined in the current sweep if (!isset(self::$public_namespace_constants[$namespace_name])) { self::$public_namespace_constants[$namespace_name] = []; } if ($visibility === \ReflectionProperty::IS_PUBLIC) { return self::$public_namespace_constants[$namespace_name]; } throw new \InvalidArgumentException('Given $visibility not supported'); } public function getFileAnalyzer() : \Psalm\Internal\Analyzer\FileAnalyzer { return $this->source; } /** * Returns true if $className is the same as, or starts with $namespace, in a case-insensitive comparison. * * * @psalm-pure */ public static function isWithin(string $calling_namespace, string $namespace) : bool { if ($namespace === '') { return \true; // required to prevent a warning from strpos with empty needle in PHP < 8 } $calling_namespace = \strtolower(\trim($calling_namespace, '\\') . '\\'); $namespace = \strtolower(\trim($namespace, '\\') . '\\'); return $calling_namespace === $namespace || \strpos($calling_namespace, $namespace) === 0; } /** * @param string $fullyQualifiedClassName, e.g. '\Psalm\Internal\Analyzer\NamespaceAnalyzer' * * @return string , e.g. 'Psalm' * * @psalm-pure */ public static function getNameSpaceRoot(string $fullyQualifiedClassName) : string { return \preg_replace('/^([^\\\\]+).*/', '$1', $fullyQualifiedClassName); } } label = $label; $this->entry_path_type = $entry_path_type; $this->entry_path_description = $entry_path_description; $this->line_from = $line_from; $this->line_to = $line_to; $this->file_name = $file_name; $this->file_path = $file_path; $this->snippet = $snippet; $this->selected_text = $selected_text; $this->from = $from; $this->to = $to; $this->snippet_from = $snippet_from; $this->snippet_to = $snippet_to; $this->column_from = $column_from; $this->column_to = $column_to; } } getCodebase(); $method_name_lc = \strtolower((string) $function->name); $source_fqcln = (string) $source->getFQCLN(); $source_fqcln_lc = \strtolower($source_fqcln); $method_id = new \Psalm\Internal\MethodIdentifier($source_fqcln, $method_name_lc); if (!$storage) { try { $storage = $codebase->methods->getStorage($method_id); } catch (\UnexpectedValueException $e) { $class_storage = $codebase->classlike_storage_provider->get($source_fqcln_lc); if (!$class_storage->parent_classes) { throw $e; } $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if (!$declaring_method_id) { throw $e; } // happens for fake constructors $storage = $codebase->methods->getStorage($declaring_method_id); } } parent::__construct($function, $source, $storage); } /** * Determines whether a given method is static or not * @param array $suppressed_issues */ public static function checkStatic(\Psalm\Internal\MethodIdentifier $method_id, bool $self_call, bool $is_context_dynamic, \Psalm\Codebase $codebase, \Psalm\CodeLocation $code_location, array $suppressed_issues, ?bool &$is_dynamic_this_method = \false) : bool { $codebase_methods = $codebase->methods; if ($method_id->fq_class_name === 'Closure' && $method_id->method_name === 'fromcallable') { return \true; } $original_method_id = $method_id; $method_id = $codebase_methods->getDeclaringMethodId($method_id); if (!$method_id) { throw new \LogicException('Declaring method for ' . $original_method_id . ' should not be null'); } $storage = $codebase_methods->getStorage($method_id); if (!$storage->is_static) { if ($self_call) { if (!$is_context_dynamic) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NonStaticSelfCall('Method ' . $codebase_methods->getCasedMethodId($method_id) . ' is not static, but is called ' . 'using self::', $code_location), $suppressed_issues)) { return \false; } } else { $is_dynamic_this_method = \true; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidStaticInvocation('Method ' . $codebase_methods->getCasedMethodId($method_id) . ' is not static, but is called ' . 'statically', $code_location), $suppressed_issues)) { return \false; } } } return \true; } /** * @param string[] $suppressed_issues * @param lowercase-string|null $calling_method_id * */ public static function checkMethodExists(\Psalm\Codebase $codebase, \Psalm\Internal\MethodIdentifier $method_id, \Psalm\CodeLocation $code_location, array $suppressed_issues, ?string $calling_method_id = null) : ?bool { if ($codebase->methods->methodExists($method_id, $calling_method_id, !$calling_method_id || $calling_method_id !== \strtolower((string) $method_id) ? $code_location : null, null, $code_location->file_path)) { return \true; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedMethod('Method ' . $method_id . ' does not exist', $code_location, (string) $method_id), $suppressed_issues)) { return \false; } return null; } public static function isMethodVisible(\Psalm\Internal\MethodIdentifier $method_id, \Psalm\Context $context, \Psalm\StatementsSource $source) : bool { $codebase = $source->getCodebase(); $fq_classlike_name = $method_id->fq_class_name; $method_name = $method_id->method_name; if ($codebase->methods->visibility_provider->has($fq_classlike_name)) { $method_visible = $codebase->methods->visibility_provider->isMethodVisible($source, $fq_classlike_name, $method_name, $context, null); if ($method_visible !== null) { return $method_visible; } } $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if (!$declaring_method_id) { // this can happen for methods in the callmap that were not reflected return \true; } $appearing_method_id = $codebase->methods->getAppearingMethodId($method_id); $appearing_method_class = null; if ($appearing_method_id) { $appearing_method_class = $appearing_method_id->fq_class_name; // if the calling class is the same, we know the method exists, so it must be visible if ($appearing_method_class === $context->self) { return \true; } } $declaring_method_class = $declaring_method_id->fq_class_name; if ($source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer && \strtolower($declaring_method_class) === \strtolower((string) $source->getFQCLN())) { return \true; } $storage = $codebase->methods->getStorage($declaring_method_id); switch ($storage->visibility) { case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC: return \true; case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE: return $context->self && $appearing_method_class === $context->self; case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED: if (!$context->self) { return \false; } if ($appearing_method_class && $codebase->classExtends($appearing_method_class, $context->self)) { return \true; } if ($appearing_method_class && !$codebase->classExtends($context->self, $appearing_method_class)) { return \false; } } return \true; } /** * Check that __clone, __construct, and __destruct do not have a return type * hint in their signature. * * @return false|null */ public static function checkMethodSignatureMustOmitReturnType(\Psalm\Storage\MethodStorage $method_storage, \Psalm\CodeLocation $code_location) : ?bool { if ($method_storage->signature_return_type === null) { return null; } $cased_method_name = $method_storage->cased_name; $methodsOfInterest = ['__clone', '__construct', '__destruct']; if (\in_array($cased_method_name, $methodsOfInterest)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMustOmitReturnType('Method ' . $cased_method_name . ' must not declare a return type', $code_location))) { return \false; } } return null; } public function getMethodId(?string $context_self = null) : \Psalm\Internal\MethodIdentifier { $function_name = (string) $this->function->name; return new \Psalm\Internal\MethodIdentifier($context_self ?: (string) $this->source->getFQCLN(), \strtolower($function_name)); } } class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_) { throw new \LogicException('Something went badly wrong'); } $project_analyzer = $this->file_analyzer->project_analyzer; $codebase = $project_analyzer->getCodebase(); $config = $project_analyzer->getConfig(); if ($this->class->extends) { foreach ($this->class->extends as $extended_interface) { $extended_interface_name = self::getFQCLNFromNameObject($extended_interface, $this->getAliases()); $parent_reference_location = new \Psalm\CodeLocation($this, $extended_interface); if (!$codebase->classOrInterfaceExists($extended_interface_name, $parent_reference_location)) { // we should not normally get here return; } try { $extended_interface_storage = $codebase->classlike_storage_provider->get($extended_interface_name); } catch (\InvalidArgumentException $e) { continue; } if (!$extended_interface_storage->is_interface) { $code_location = new \Psalm\CodeLocation($this, $extended_interface); if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedInterface($extended_interface_name . ' is not an interface', $code_location, $extended_interface_name), $this->getSuppressedIssues())) { // fall through } } if ($codebase->store_node_types && $extended_interface_name) { $bounds = $parent_reference_location->getSelectionBounds(); $codebase->analyzer->addOffsetReference($this->getFilePath(), $bounds[0], $bounds[1], $extended_interface_name); } } } $fq_interface_name = $this->getFQCLN(); if (!$fq_interface_name) { throw new \UnexpectedValueException('bad'); } $class_storage = $codebase->classlike_storage_provider->get($fq_interface_name); foreach ($this->class->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $method_analyzer = new \Psalm\Internal\Analyzer\MethodAnalyzer($stmt, $this); $type_provider = new \Psalm\Internal\Provider\NodeDataProvider(); $method_analyzer->analyze(new \Psalm\Context($this->getFQCLN()), $type_provider); $actual_method_id = $method_analyzer->getMethodId(); if ($stmt->name->name !== '__construct' && $config->reportIssueInFile('InvalidReturnType', $this->getFilePath())) { \Psalm\Internal\Analyzer\ClassAnalyzer::analyzeClassMethodReturnType($stmt, $method_analyzer, $this, $type_provider, $codebase, $class_storage, $fq_interface_name, $actual_method_id, $actual_method_id, \false); } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { \Psalm\IssueBuffer::add(new \Psalm\Issue\ParseError('Interfaces cannot have properties', new \Psalm\CodeLocation($this, $stmt))); return; } } } } getCodebase(); $function_id = \strtolower($source->getFilePath()) . ':' . $function->getLine() . ':' . (int) $function->getAttribute('startFilePos') . ':-:closure'; $storage = $codebase->getClosureStorage($source->getFilePath(), $function_id); parent::__construct($function, $source, $storage); } public function getTemplateTypeMap() : ?array { return $this->source->getTemplateTypeMap(); } /** * @return non-empty-lowercase-string */ public function getClosureId() : string { return \strtolower($this->getFilePath()) . ':' . $this->function->getLine() . ':' . (int) $this->function->getAttribute('startFilePos') . ':-:closure'; } /** * @param PhpParser\Node\Expr\Closure|PhpParser\Node\Expr\ArrowFunction $stmt */ public static function analyzeExpression(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $stmt, \Psalm\Context $context) : bool { $closure_analyzer = new \Psalm\Internal\Analyzer\ClosureAnalyzer($stmt, $statements_analyzer); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure && self::analyzeClosureUses($statements_analyzer, $stmt, $context) === \false) { return \false; } $use_context = new \Psalm\Context($context->self); $codebase = $statements_analyzer->getCodebase(); if (!$statements_analyzer->isStatic()) { if ($context->collect_mutations && $context->self && $codebase->classExtends($context->self, (string) $statements_analyzer->getFQCLN())) { /** @psalm-suppress PossiblyUndefinedStringArrayOffset */ $use_context->vars_in_scope['$this'] = clone $context->vars_in_scope['$this']; } elseif ($context->self) { $this_atomic = new \Psalm\Type\Atomic\TNamedObject($context->self); $this_atomic->was_static = \true; $use_context->vars_in_scope['$this'] = new \Psalm\Type\Union([$this_atomic]); } } foreach ($context->vars_in_scope as $var => $type) { if (\strpos($var, '$this->') === 0) { $use_context->vars_in_scope[$var] = clone $type; } } if ($context->self) { $self_class_storage = $codebase->classlike_storage_provider->get($context->self); \Psalm\Internal\Analyzer\ClassAnalyzer::addContextProperties($statements_analyzer, $self_class_storage, $use_context, $context->self, $statements_analyzer->getParentFQCLN()); } foreach ($context->vars_possibly_in_scope as $var => $_) { if (\strpos($var, '$this->') === 0) { $use_context->vars_possibly_in_scope[$var] = \true; } } $byref_uses = []; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure) { foreach ($stmt->uses as $use) { if (!\is_string($use->var->name)) { continue; } $use_var_id = '$' . $use->var->name; if ($use->byRef) { $byref_uses[$use_var_id] = \true; } // insert the ref into the current context if passed by ref, as whatever we're passing // the closure to could execute it straight away. if (!$context->hasVariable($use_var_id) && $use->byRef) { $context->vars_in_scope[$use_var_id] = \Psalm\Type::getMixed(); } if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph) { $parent_nodes = $context->vars_in_scope[$use_var_id]->parent_nodes; foreach ($parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('closure-use', 'closure use', null), 'closure-use'); } } $use_context->vars_in_scope[$use_var_id] = $context->hasVariable($use_var_id) && !$use->byRef ? clone $context->vars_in_scope[$use_var_id] : \Psalm\Type::getMixed(); $use_context->vars_possibly_in_scope[$use_var_id] = \true; } } else { $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $short_closure_visitor = new \Psalm\Internal\PhpVisitor\ShortClosureVisitor(); $traverser->addVisitor($short_closure_visitor); $traverser->traverse($stmt->getStmts()); foreach ($short_closure_visitor->getUsedVariables() as $use_var_id => $_) { if ($context->hasVariable($use_var_id)) { $use_context->vars_in_scope[$use_var_id] = clone $context->vars_in_scope[$use_var_id]; if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph) { $parent_nodes = $context->vars_in_scope[$use_var_id]->parent_nodes; foreach ($parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('closure-use', 'closure use', null), 'closure-use'); } } } else { $use_context->vars_in_scope[$use_var_id] = \Psalm\Type::getMixed(); } $use_context->vars_possibly_in_scope[$use_var_id] = \true; } } $use_context->calling_method_id = $context->calling_method_id; $closure_analyzer->analyze($use_context, $statements_analyzer->node_data, $context, \false, $byref_uses); if ($closure_analyzer->inferred_impure && $statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) { $statements_analyzer->getSource()->inferred_impure = \true; } if ($closure_analyzer->inferred_has_mutation && $statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) { $statements_analyzer->getSource()->inferred_has_mutation = \true; } if (!$statements_analyzer->node_data->getType($stmt)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getClosure()); } return \true; } /** * @return false|null */ public static function analyzeClosureUses(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure $stmt, \Psalm\Context $context) : ?bool { $param_names = \array_map(function (\_HumbugBoxd02f763d3c56\PhpParser\Node\Param $p) : string { if (!$p->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || !\is_string($p->var->name)) { return ''; } return $p->var->name; }, $stmt->params); foreach ($stmt->uses as $use) { if (!\is_string($use->var->name)) { continue; } $use_var_id = '$' . $use->var->name; if (\in_array($use->var->name, $param_names)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DuplicateParam('Closure use duplicates param name ' . $use_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $use->var)), $statements_analyzer->getSuppressedIssues())) { return \false; } } if (!$context->hasVariable($use_var_id)) { if ($use_var_id === '$argv' || $use_var_id === '$argc') { continue; } if ($use->byRef) { $context->vars_in_scope[$use_var_id] = \Psalm\Type::getMixed(); $context->vars_possibly_in_scope[$use_var_id] = \true; if (!$statements_analyzer->hasVariable($use_var_id)) { $statements_analyzer->registerVariable($use_var_id, new \Psalm\CodeLocation($statements_analyzer, $use->var), null); } return null; } if (!isset($context->vars_possibly_in_scope[$use_var_id])) { if ($context->check_variables) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedVariable('Cannot find referenced variable ' . $use_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $use->var)), $statements_analyzer->getSuppressedIssues())) { return \false; } return null; } } $first_appearance = $statements_analyzer->getFirstAppearance($use_var_id); if ($first_appearance) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedVariable('Possibly undefined variable ' . $use_var_id . ', first seen on line ' . $first_appearance->getLineNumber(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $use->var)), $statements_analyzer->getSuppressedIssues())) { return \false; } continue; } if ($context->check_variables) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedVariable('Cannot find referenced variable ' . $use_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $use->var)), $statements_analyzer->getSuppressedIssues())) { return \false; } continue; } } elseif ($use->byRef) { $new_type = \Psalm\Type::getMixed(); $new_type->parent_nodes = $context->vars_in_scope[$use_var_id]->parent_nodes; $context->remove($use_var_id); $context->vars_in_scope[$use_var_id] = $new_type; } } return null; } } */ private $aliased_classes = []; /** * @var array */ private $aliased_class_locations = []; /** * @var array */ private $aliased_classes_flipped = []; /** * @var array */ private $aliased_classes_flipped_replaceable = []; /** * @var array */ private $aliased_functions = []; /** * @var array */ private $aliased_constants = []; public function visitUse(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_ $stmt) : void { $codebase = $this->getCodebase(); foreach ($stmt->uses as $use) { $use_path = \implode('\\', $use->name->parts); $use_alias = $use->alias ? $use->alias->name : $use->name->getLast(); switch ($use->type !== \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $stmt->type) { case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION: $this->aliased_functions[\strtolower($use_alias)] = $use_path; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT: $this->aliased_constants[$use_alias] = $use_path; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL: $codebase->analyzer->addOffsetReference($this->getFilePath(), (int) $use->getAttribute('startFilePos'), (int) $use->getAttribute('endFilePos'), $use_path); if ($codebase->collect_locations) { // register the path $codebase->use_referencing_locations[\strtolower($use_path)][] = new \Psalm\CodeLocation($this, $use); $codebase->use_referencing_files[$this->getFilePath()][\strtolower($use_path)] = \true; } if ($codebase->alter_code) { if (isset($codebase->class_transforms[\strtolower($use_path)])) { $new_fq_class_name = $codebase->class_transforms[\strtolower($use_path)]; $file_manipulations = []; $file_manipulations[] = new \Psalm\FileManipulation((int) $use->getAttribute('startFilePos'), (int) $use->getAttribute('endFilePos') + 1, $new_fq_class_name . ($use->alias ? ' as ' . $use_alias : '')); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($this->getFilePath(), $file_manipulations); } $this->aliased_classes_flipped_replaceable[\strtolower($use_path)] = $use_alias; } $this->aliased_classes[\strtolower($use_alias)] = $use_path; $this->aliased_class_locations[\strtolower($use_alias)] = new \Psalm\CodeLocation($this, $stmt); $this->aliased_classes_flipped[\strtolower($use_path)] = $use_alias; break; } } } public function visitGroupUse(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse $stmt) : void { $use_prefix = \implode('\\', $stmt->prefix->parts); $codebase = $this->getCodebase(); foreach ($stmt->uses as $use) { $use_path = $use_prefix . '\\' . \implode('\\', $use->name->parts); $use_alias = $use->alias ? $use->alias->name : $use->name->getLast(); switch ($use->type !== \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $stmt->type) { case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION: $this->aliased_functions[\strtolower($use_alias)] = $use_path; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT: $this->aliased_constants[$use_alias] = $use_path; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL: if ($codebase->collect_locations) { // register the path $codebase->use_referencing_locations[\strtolower($use_path)][] = new \Psalm\CodeLocation($this, $use); } $this->aliased_classes[\strtolower($use_alias)] = $use_path; $this->aliased_classes_flipped[\strtolower($use_path)] = $use_alias; break; } } } /** * @return array */ public function getAliasedClassesFlipped() : array { return $this->aliased_classes_flipped; } /** * @return array */ public function getAliasedClassesFlippedReplaceable() : array { return $this->aliased_classes_flipped_replaceable; } public function getAliases() : \Psalm\Aliases { return new \Psalm\Aliases($this->getNamespace(), $this->aliased_classes, $this->aliased_functions, $this->aliased_constants); } } $formula_1 * @param list $formula_2 * @param array $new_assigned_var_ids */ public static function checkForParadox(array $formula_1, array $formula_2, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node $stmt, array $new_assigned_var_ids) : void { try { $negated_formula2 = \Psalm\Type\Algebra::negateFormula($formula_2); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { return; } $formula_1_hashes = []; foreach ($formula_1 as $formula_1_clause) { $formula_1_hashes[$formula_1_clause->hash] = \true; } $formula_2_hashes = []; foreach ($formula_2 as $formula_2_clause) { $hash = $formula_2_clause->hash; if (!$formula_2_clause->generated && !$formula_2_clause->wedge && $formula_2_clause->reconcilable && (isset($formula_1_hashes[$hash]) || isset($formula_2_hashes[$hash])) && !\array_intersect_key($new_assigned_var_ids, $formula_2_clause->possibilities)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition($formula_2_clause . ' has already been asserted', new \Psalm\CodeLocation($statements_analyzer, $stmt), null), $statements_analyzer->getSuppressedIssues())) { // fall through } } foreach ($formula_2_clause->possibilities as $key => $values) { if (!$formula_2_clause->generated && \count($values) > 1 && !isset($new_assigned_var_ids[$key]) && \count(\array_unique($values)) < \count($values)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParadoxicalCondition('Found a redundant condition when evaluating assertion (' . $formula_2_clause . ')', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } $formula_2_hashes[$hash] = \true; } // remove impossible types foreach ($negated_formula2 as $negated_clause_2) { if (\count($negated_formula2) === 1) { foreach ($negated_clause_2->possibilities as $key => $values) { if (\count($values) > 1 && !isset($new_assigned_var_ids[$key]) && \count(\array_unique($values)) < \count($values)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition('Found a redundant condition when evaluating ' . $key, new \Psalm\CodeLocation($statements_analyzer, $stmt), null), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } if (!$negated_clause_2->reconcilable || $negated_clause_2->wedge) { continue; } foreach ($formula_1 as $clause_1) { if ($negated_clause_2 === $clause_1 || !$clause_1->reconcilable || $clause_1->wedge) { continue; } $negated_clause_2_contains_1_possibilities = \true; foreach ($clause_1->possibilities as $key => $keyed_possibilities) { if (!isset($negated_clause_2->possibilities[$key])) { $negated_clause_2_contains_1_possibilities = \false; break; } if ($negated_clause_2->possibilities[$key] != $keyed_possibilities) { $negated_clause_2_contains_1_possibilities = \false; break; } } if ($negated_clause_2_contains_1_possibilities) { $mini_formula_2 = \Psalm\Type\Algebra::negateFormula([$negated_clause_2]); if (!$mini_formula_2[0]->wedge) { if (\count($mini_formula_2) > 1) { $paradox_message = 'Condition ((' . \implode(') && (', $mini_formula_2) . '))' . ' contradicts a previously-established condition (' . $clause_1 . ')'; } else { $paradox_message = 'Condition (' . $mini_formula_2[0] . ')' . ' contradicts a previously-established condition (' . $clause_1 . ')'; } } else { $paradox_message = 'Condition not(' . $negated_clause_2 . ')' . ' contradicts a previously-established condition (' . $clause_1 . ')'; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParadoxicalCondition($paradox_message, new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } } } } } methods->getDeclaringMethodId(new \Psalm\Internal\MethodIdentifier($implementer_classlike_storage->name, \strtolower($guide_method_storage->cased_name ?: ''))); $cased_implementer_method_id = $implementer_classlike_storage->name . '::' . $implementer_method_storage->cased_name; $cased_guide_method_id = $guide_classlike_storage->name . '::' . $guide_method_storage->cased_name; self::checkForObviousMethodMismatches($guide_classlike_storage, $implementer_classlike_storage, $guide_method_storage, $implementer_method_storage, $guide_method_storage->visibility, $implementer_visibility, $cased_guide_method_id, $cased_implementer_method_id, $prevent_method_signature_mismatch, $prevent_abstract_override, $codebase->php_major_version >= 8, $code_location, $suppressed_issues); if ($guide_method_storage->signature_return_type && $prevent_method_signature_mismatch) { self::compareMethodSignatureReturnTypes($codebase, $guide_classlike_storage, $implementer_classlike_storage, $guide_method_storage, $implementer_method_storage, $guide_method_storage->signature_return_type, $cased_guide_method_id, $implementer_called_class_name, $cased_implementer_method_id, $code_location, $suppressed_issues); } if ($guide_method_storage->return_type && $implementer_method_storage->return_type && !$implementer_method_storage->inherited_return_type && ($guide_method_storage->signature_return_type !== $guide_method_storage->return_type || $implementer_method_storage->signature_return_type !== $implementer_method_storage->return_type) && $implementer_classlike_storage->user_defined && (!$guide_classlike_storage->stubbed || $guide_classlike_storage->template_types)) { self::compareMethodDocblockReturnTypes($codebase, $guide_classlike_storage, $implementer_classlike_storage, $implementer_method_storage, $guide_method_storage->return_type, $implementer_method_storage->return_type, $cased_guide_method_id, $implementer_called_class_name, $implementer_declaring_method_id, $code_location, $suppressed_issues); } foreach ($guide_method_storage->params as $i => $guide_param) { if (!isset($implementer_method_storage->params[$i])) { if (!$prevent_abstract_override && $i >= $guide_method_storage->required_param_count) { continue; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMismatch('Method ' . $cased_implementer_method_id . ' has fewer parameters than parent method ' . $cased_guide_method_id, $code_location))) { return \false; } return null; } self::compareMethodParams($codebase, $stmt, $implementer_classlike_storage, $guide_classlike_storage, $implementer_called_class_name, $guide_method_storage, $implementer_method_storage, $guide_param, $implementer_method_storage->params[$i], $i, $cased_guide_method_id, $cased_implementer_method_id, $prevent_method_signature_mismatch, $code_location, $suppressed_issues); } if ($guide_classlike_storage->user_defined && ($guide_classlike_storage->is_interface || $guide_classlike_storage->preserve_constructor_signature || $implementer_method_storage->cased_name !== '__construct') && $implementer_method_storage->required_param_count > $guide_method_storage->required_param_count) { if ($implementer_method_storage->cased_name !== '__construct') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMismatch('Method ' . $cased_implementer_method_id . ' has more required parameters than parent method ' . $cased_guide_method_id, $code_location))) { return \false; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ConstructorSignatureMismatch('Method ' . $cased_implementer_method_id . ' has more required parameters than parent method ' . $cased_guide_method_id, $code_location))) { return \false; } } return null; } return null; } /** * @param string[] $suppressed_issues */ private static function checkForObviousMethodMismatches(\Psalm\Storage\ClassLikeStorage $guide_classlike_storage, \Psalm\Storage\ClassLikeStorage $implementer_classlike_storage, \Psalm\Storage\MethodStorage $guide_method_storage, \Psalm\Storage\MethodStorage $implementer_method_storage, int $guide_visibility, int $implementer_visibility, string $cased_guide_method_id, string $cased_implementer_method_id, bool $prevent_method_signature_mismatch, bool $prevent_abstract_override, bool $trait_mismatches_are_fatal, \Psalm\CodeLocation $code_location, array $suppressed_issues) : void { if ($implementer_visibility > $guide_visibility) { if ($trait_mismatches_are_fatal || $guide_classlike_storage->is_trait === $implementer_classlike_storage->is_trait || !\in_array($guide_classlike_storage->name, $implementer_classlike_storage->used_traits) || $implementer_method_storage->defining_fqcln !== $implementer_classlike_storage->name || !$implementer_method_storage->abstract && !$guide_method_storage->abstract) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\OverriddenMethodAccess('Method ' . $cased_implementer_method_id . ' has different access level than ' . $cased_guide_method_id, $code_location))) { // fall through } } elseif (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TraitMethodSignatureMismatch('Method ' . $cased_implementer_method_id . ' has different access level than ' . $cased_guide_method_id, $code_location))) { // fall through } } if ($guide_method_storage->final && $prevent_method_signature_mismatch && $prevent_abstract_override) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMismatch('Method ' . $cased_guide_method_id . ' is declared final and cannot be overridden', $code_location))) { // fall through } } if ($prevent_abstract_override && !$guide_method_storage->abstract && $implementer_method_storage->abstract && !$guide_classlike_storage->abstract && !$guide_classlike_storage->is_interface) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMismatch('Method ' . $cased_implementer_method_id . ' cannot be abstract when inherited method ' . $cased_guide_method_id . ' is non-abstract', $code_location))) { // fall through } } if ($guide_method_storage->external_mutation_free && !$implementer_method_storage->external_mutation_free && !$guide_method_storage->mutation_free_inferred && $prevent_method_signature_mismatch) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingImmutableAnnotation($cased_guide_method_id . ' is marked immutable, but ' . $implementer_classlike_storage->name . '::' . ($guide_method_storage->cased_name ?: '') . ' is not marked immutable', $code_location), $suppressed_issues)) { // fall through } } } /** * @param string[] $suppressed_issues */ private static function compareMethodParams(\Psalm\Codebase $codebase, ?\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod $stmt, \Psalm\Storage\ClassLikeStorage $implementer_classlike_storage, \Psalm\Storage\ClassLikeStorage $guide_classlike_storage, string $implementer_called_class_name, \Psalm\Storage\MethodStorage $guide_method_storage, \Psalm\Storage\MethodStorage $implementer_method_storage, \Psalm\Storage\FunctionLikeParameter $guide_param, \Psalm\Storage\FunctionLikeParameter $implementer_param, int $i, string $cased_guide_method_id, string $cased_implementer_method_id, bool $prevent_method_signature_mismatch, \Psalm\CodeLocation $code_location, array $suppressed_issues) : void { if ($prevent_method_signature_mismatch) { if (!$guide_classlike_storage->user_defined && $guide_param->type) { $implementer_param_type = $implementer_param->signature_type; $guide_param_signature_type = $guide_param->type; $or_null_guide_param_signature_type = $guide_param->signature_type ? clone $guide_param->signature_type : null; if ($or_null_guide_param_signature_type) { $or_null_guide_param_signature_type->addType(new \Psalm\Type\Atomic\TNull()); } if ($cased_guide_method_id === 'Serializable::unserialize') { $guide_param_signature_type = null; $or_null_guide_param_signature_type = null; } if (!$guide_param->type->hasMixed() && !$guide_param->type->from_docblock && ($implementer_param_type || $guide_param_signature_type)) { $config = \Psalm\Config::getInstance(); if ($implementer_param_type && (!$guide_param_signature_type || \strtolower($implementer_param_type->getId()) !== \strtolower($guide_param_signature_type->getId())) && (!$or_null_guide_param_signature_type || \strtolower($implementer_param_type->getId()) !== \strtolower($or_null_guide_param_signature_type->getId()))) { if ($implementer_method_storage->cased_name === '__construct') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ConstructorSignatureMismatch('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has wrong type \'' . $implementer_param_type . '\', expecting \'' . $guide_param_signature_type . '\' as defined by ' . $cased_guide_method_id, $implementer_param->location && $config->isInProjectDirs($implementer_param->location->file_path) ? $implementer_param->location : $code_location))) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMismatch('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has wrong type \'' . $implementer_param_type . '\', expecting \'' . $guide_param_signature_type . '\' as defined by ' . $cased_guide_method_id, $implementer_param->location && $config->isInProjectDirs($implementer_param->location->file_path) ? $implementer_param->location : $code_location))) { // fall through } } return; } } } $config = \Psalm\Config::getInstance(); if ($guide_param->name !== $implementer_param->name && $guide_method_storage->allow_named_arg_calls && \count($implementer_method_storage->params) > 1 && $guide_classlike_storage->user_defined && $implementer_classlike_storage->user_defined && $implementer_param->location && $guide_method_storage->cased_name && \substr($guide_method_storage->cased_name, 0, 2) !== '__' && $config->isInProjectDirs($implementer_param->location->file_path)) { if ($config->allow_named_arg_calls || $guide_classlike_storage->location && !$config->isInProjectDirs($guide_classlike_storage->location->file_path)) { if ($codebase->alter_code) { $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); if ($stmt && isset($project_analyzer->getIssuesToFix()['ParamNameMismatch'])) { $param_replacer = new \Psalm\Internal\PhpVisitor\ParamReplacementVisitor($implementer_param->name, $guide_param->name); $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $traverser->addVisitor($param_replacer); $traverser->traverse([$stmt]); if ($replacements = $param_replacer->getReplacements()) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($implementer_param->location->file_path, $replacements); } } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParamNameMismatch('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has wrong name $' . $implementer_param->name . ', expecting $' . $guide_param->name . ' as defined by ' . $cased_guide_method_id, $implementer_param->location), $suppressed_issues)) { // fall through } } } } if ($guide_classlike_storage->user_defined && $implementer_param->signature_type) { self::compareMethodSignatureParams($codebase, $i, $guide_classlike_storage, $implementer_classlike_storage, $guide_method_storage, $implementer_method_storage, $guide_param, $implementer_param->signature_type, $cased_guide_method_id, $cased_implementer_method_id, $code_location, $suppressed_issues); } } if ($implementer_param->type && $guide_param->type && $implementer_param->type->getId() !== $guide_param->type->getId()) { self::compareMethodDocblockParams($codebase, $i, $guide_classlike_storage, $implementer_classlike_storage, $implementer_called_class_name, $guide_method_storage, $implementer_method_storage, $cased_guide_method_id, $cased_implementer_method_id, $guide_param->type, $implementer_param->type, $code_location, $suppressed_issues); } if ($guide_classlike_storage->user_defined && $implementer_param->by_ref !== $guide_param->by_ref) { $config = \Psalm\Config::getInstance(); if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMismatch('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' is' . ($implementer_param->by_ref ? '' : ' not') . ' passed by reference, but argument ' . ($i + 1) . ' of ' . $cased_guide_method_id . ' is' . ($guide_param->by_ref ? '' : ' not'), $implementer_param->location && $config->isInProjectDirs($implementer_param->location->file_path) ? $implementer_param->location : $code_location))) { // fall through } } } /** * @param string[] $suppressed_issues */ private static function compareMethodSignatureParams(\Psalm\Codebase $codebase, int $i, \Psalm\Storage\ClassLikeStorage $guide_classlike_storage, \Psalm\Storage\ClassLikeStorage $implementer_classlike_storage, \Psalm\Storage\MethodStorage $guide_method_storage, \Psalm\Storage\MethodStorage $implementer_method_storage, \Psalm\Storage\FunctionLikeParameter $guide_param, \Psalm\Type\Union $implementer_param_signature_type, string $cased_guide_method_id, string $cased_implementer_method_id, \Psalm\CodeLocation $code_location, array $suppressed_issues) : void { $guide_param_signature_type = $guide_param->signature_type ? \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $guide_param->signature_type, $guide_classlike_storage->is_trait && $guide_method_storage->abstract ? $implementer_classlike_storage->name : $guide_classlike_storage->name, $guide_classlike_storage->is_trait && $guide_method_storage->abstract ? $implementer_classlike_storage->name : $guide_classlike_storage->name, $guide_classlike_storage->is_trait && $guide_method_storage->abstract ? $implementer_classlike_storage->parent_class : $guide_classlike_storage->parent_class) : null; $implementer_param_signature_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $implementer_param_signature_type, $implementer_classlike_storage->name, $implementer_classlike_storage->name, $implementer_classlike_storage->parent_class); $is_contained_by = ($codebase->php_major_version === 7 && $codebase->php_minor_version === 4 || $codebase->php_major_version >= 8) && $guide_param_signature_type ? \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $guide_param_signature_type, $implementer_param_signature_type) : \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedByInPhp($guide_param_signature_type, $implementer_param_signature_type); if (!$is_contained_by) { $config = \Psalm\Config::getInstance(); if ($codebase->php_major_version >= 8 || $guide_classlike_storage->is_trait === $implementer_classlike_storage->is_trait || !\in_array($guide_classlike_storage->name, $implementer_classlike_storage->used_traits) || $implementer_method_storage->defining_fqcln !== $implementer_classlike_storage->name || !$implementer_method_storage->abstract && !$guide_method_storage->abstract) { if ($implementer_method_storage->cased_name === '__construct') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ConstructorSignatureMismatch('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has wrong type \'' . $implementer_param_signature_type . '\', expecting \'' . $guide_param_signature_type . '\' as defined by ' . $cased_guide_method_id, $implementer_method_storage->params[$i]->location && $config->isInProjectDirs($implementer_method_storage->params[$i]->location->file_path) ? $implementer_method_storage->params[$i]->location : $code_location))) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMismatch('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has wrong type \'' . $implementer_param_signature_type . '\', expecting \'' . $guide_param_signature_type . '\' as defined by ' . $cased_guide_method_id, $implementer_method_storage->params[$i]->location && $config->isInProjectDirs($implementer_method_storage->params[$i]->location->file_path) ? $implementer_method_storage->params[$i]->location : $code_location))) { // fall through } } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TraitMethodSignatureMismatch('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has wrong type \'' . $implementer_param_signature_type . '\', expecting \'' . $guide_param_signature_type . '\' as defined by ' . $cased_guide_method_id, $implementer_method_storage->params[$i]->location && $config->isInProjectDirs($implementer_method_storage->params[$i]->location->file_path) ? $implementer_method_storage->params[$i]->location : $code_location), $suppressed_issues)) { // fall through } } } } /** * @param string[] $suppressed_issues */ private static function compareMethodDocblockParams(\Psalm\Codebase $codebase, int $i, \Psalm\Storage\ClassLikeStorage $guide_classlike_storage, \Psalm\Storage\ClassLikeStorage $implementer_classlike_storage, string $implementer_called_class_name, \Psalm\Storage\MethodStorage $guide_method_storage, \Psalm\Storage\MethodStorage $implementer_method_storage, string $cased_guide_method_id, string $cased_implementer_method_id, \Psalm\Type\Union $guide_param_type, \Psalm\Type\Union $implementer_param_type, \Psalm\CodeLocation $code_location, array $suppressed_issues) : void { $implementer_method_storage_param_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $implementer_param_type, $implementer_classlike_storage->name, $implementer_called_class_name, $implementer_classlike_storage->parent_class); $guide_method_storage_param_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $guide_param_type, $guide_classlike_storage->is_trait && $guide_method_storage->abstract ? $implementer_classlike_storage->name : $guide_classlike_storage->name, $guide_classlike_storage->is_trait && $guide_method_storage->abstract ? $implementer_classlike_storage->name : $guide_classlike_storage->name, $guide_classlike_storage->is_trait && $guide_method_storage->abstract ? $implementer_classlike_storage->parent_class : $guide_classlike_storage->parent_class); $guide_class_name = $guide_classlike_storage->name; if ($implementer_classlike_storage->template_type_extends) { self::transformTemplates($implementer_classlike_storage->template_type_extends, $guide_class_name, $guide_method_storage_param_type, $codebase); } if ($implementer_classlike_storage->is_trait) { $implementer_called_class_storage = $codebase->classlike_storage_provider->get($implementer_called_class_name); if (isset($implementer_called_class_storage->template_type_extends[$implementer_classlike_storage->name])) { self::transformTemplates($implementer_called_class_storage->template_type_extends, $implementer_classlike_storage->name, $implementer_method_storage_param_type, $codebase); self::transformTemplates($implementer_called_class_storage->template_type_extends, $guide_class_name, $guide_method_storage_param_type, $codebase); } } foreach ($implementer_method_storage_param_type->getAtomicTypes() as $k => $t) { if ($t instanceof \Psalm\Type\Atomic\TTemplateParam && \strpos($t->defining_class, 'fn-') === 0) { $implementer_method_storage_param_type->removeType($k); foreach ($t->as->getAtomicTypes() as $as_t) { $implementer_method_storage_param_type->addType($as_t); } } } foreach ($guide_method_storage_param_type->getAtomicTypes() as $k => $t) { if ($t instanceof \Psalm\Type\Atomic\TTemplateParam && \strpos($t->defining_class, 'fn-') === 0) { $guide_method_storage_param_type->removeType($k); foreach ($t->as->getAtomicTypes() as $as_t) { $guide_method_storage_param_type->addType($as_t); } } } $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $guide_method_storage_param_type, $implementer_method_storage_param_type, !$guide_classlike_storage->user_defined, !$guide_classlike_storage->user_defined, $union_comparison_results)) { // is the declared return type more specific than the inferred one? if ($union_comparison_results->type_coerced) { if ($guide_classlike_storage->user_defined) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MoreSpecificImplementedParamType('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has the more specific type \'' . $implementer_method_storage_param_type->getId() . '\', expecting \'' . $guide_method_storage_param_type->getId() . '\' as defined by ' . $cased_guide_method_id, $implementer_method_storage->params[$i]->location ?: $code_location), $suppressed_issues)) { // fall through } } } else { if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $implementer_method_storage_param_type, $guide_method_storage_param_type, !$guide_classlike_storage->user_defined, !$guide_classlike_storage->user_defined)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MoreSpecificImplementedParamType('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has the more specific type \'' . $implementer_method_storage_param_type->getId() . '\', expecting \'' . $guide_method_storage_param_type->getId() . '\' as defined by ' . $cased_guide_method_id, $implementer_method_storage->params[$i]->location ?: $code_location), $suppressed_issues)) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImplementedParamTypeMismatch('Argument ' . ($i + 1) . ' of ' . $cased_implementer_method_id . ' has wrong type \'' . $implementer_method_storage_param_type->getId() . '\', expecting \'' . $guide_method_storage_param_type->getId() . '\' as defined by ' . $cased_guide_method_id, $implementer_method_storage->params[$i]->location ?: $code_location), $suppressed_issues)) { // fall through } } } } } /** * @param string[] $suppressed_issues */ private static function compareMethodSignatureReturnTypes(\Psalm\Codebase $codebase, \Psalm\Storage\ClassLikeStorage $guide_classlike_storage, \Psalm\Storage\ClassLikeStorage $implementer_classlike_storage, \Psalm\Storage\MethodStorage $guide_method_storage, \Psalm\Storage\MethodStorage $implementer_method_storage, \Psalm\Type\Union $guide_signature_return_type, string $cased_guide_method_id, string $implementer_called_class_name, string $cased_implementer_method_id, \Psalm\CodeLocation $code_location, array $suppressed_issues) : void { $guide_signature_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $guide_signature_return_type, $guide_classlike_storage->is_trait && $guide_method_storage->abstract ? $implementer_classlike_storage->name : $guide_classlike_storage->name, $guide_classlike_storage->is_trait && $guide_method_storage->abstract || $guide_classlike_storage->final ? $implementer_classlike_storage->name : $guide_classlike_storage->name, $guide_classlike_storage->is_trait && $guide_method_storage->abstract ? $implementer_classlike_storage->parent_class : $guide_classlike_storage->parent_class, \true, \true, $implementer_method_storage->final); $implementer_signature_return_type = $implementer_method_storage->signature_return_type ? \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $implementer_method_storage->signature_return_type, $implementer_classlike_storage->is_trait ? $implementer_called_class_name : $implementer_classlike_storage->name, $implementer_classlike_storage->is_trait ? $implementer_called_class_name : $implementer_classlike_storage->name, $implementer_classlike_storage->parent_class) : null; $is_contained_by = ($codebase->php_major_version === 7 && $codebase->php_minor_version === 4 || $codebase->php_major_version >= 8) && $implementer_signature_return_type ? \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $implementer_signature_return_type, $guide_signature_return_type) : \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedByInPhp($implementer_signature_return_type, $guide_signature_return_type); if (!$is_contained_by) { if ($codebase->php_major_version >= 8 || $guide_classlike_storage->is_trait === $implementer_classlike_storage->is_trait || !\in_array($guide_classlike_storage->name, $implementer_classlike_storage->used_traits) || $implementer_method_storage->defining_fqcln !== $implementer_classlike_storage->name || !$implementer_method_storage->abstract && !$guide_method_storage->abstract) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MethodSignatureMismatch('Method ' . $cased_implementer_method_id . ' with return type \'' . $implementer_signature_return_type . '\' is different to return type \'' . $guide_signature_return_type . '\' of inherited method ' . $cased_guide_method_id, $code_location), $suppressed_issues)) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TraitMethodSignatureMismatch('Method ' . $cased_implementer_method_id . ' with return type \'' . $implementer_signature_return_type . '\' is different to return type \'' . $guide_signature_return_type . '\' of inherited method ' . $cased_guide_method_id, $code_location), $suppressed_issues)) { // fall through } } } } /** * @param string[] $suppressed_issues */ private static function compareMethodDocblockReturnTypes(\Psalm\Codebase $codebase, \Psalm\Storage\ClassLikeStorage $guide_classlike_storage, \Psalm\Storage\ClassLikeStorage $implementer_classlike_storage, \Psalm\Storage\MethodStorage $implementer_method_storage, \Psalm\Type\Union $guide_return_type, \Psalm\Type\Union $implementer_return_type, string $cased_guide_method_id, string $implementer_called_class_name, ?\Psalm\Internal\MethodIdentifier $implementer_declaring_method_id, \Psalm\CodeLocation $code_location, array $suppressed_issues) : void { $implementer_method_storage_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $implementer_return_type, $implementer_classlike_storage->name, $implementer_called_class_name, $implementer_classlike_storage->parent_class); $guide_method_storage_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $guide_return_type, $guide_classlike_storage->is_trait ? $implementer_classlike_storage->name : $guide_classlike_storage->name, $guide_classlike_storage->is_trait || $implementer_method_storage->final ? $implementer_called_class_name : $guide_classlike_storage->name, $guide_classlike_storage->parent_class, \true, \true, $implementer_method_storage->final); $guide_class_name = $guide_classlike_storage->name; if ($implementer_classlike_storage->template_type_extends) { self::transformTemplates($implementer_classlike_storage->template_type_extends, $guide_class_name, $guide_method_storage_return_type, $codebase); } if ($implementer_classlike_storage->is_trait) { $implementer_called_class_storage = $codebase->classlike_storage_provider->get($implementer_called_class_name); if (isset($implementer_called_class_storage->template_type_extends[$implementer_classlike_storage->name])) { self::transformTemplates($implementer_called_class_storage->template_type_extends, $implementer_classlike_storage->name, $implementer_method_storage_return_type, $codebase); self::transformTemplates($implementer_called_class_storage->template_type_extends, $guide_class_name, $guide_method_storage_return_type, $codebase); } } // treat void as null when comparing against docblock implementer if ($implementer_method_storage_return_type->isVoid()) { $implementer_method_storage_return_type = \Psalm\Type::getNull(); } if ($guide_method_storage_return_type->isVoid()) { $guide_method_storage_return_type = \Psalm\Type::getNull(); } $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $implementer_method_storage_return_type, $guide_method_storage_return_type, \false, \false, $union_comparison_results)) { // is the declared return type more specific than the inferred one? if ($union_comparison_results->type_coerced) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\LessSpecificImplementedReturnType('The inherited return type \'' . $guide_method_storage_return_type->getId() . '\' for ' . $cased_guide_method_id . ' is more specific than the implemented ' . 'return type for ' . $implementer_declaring_method_id . ' \'' . $implementer_method_storage_return_type->getId() . '\'', $implementer_method_storage->return_type_location ?: $code_location), $suppressed_issues)) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImplementedReturnTypeMismatch('The inherited return type \'' . $guide_method_storage_return_type->getId() . '\' for ' . $cased_guide_method_id . ' is different to the implemented ' . 'return type for ' . $implementer_declaring_method_id . ' \'' . $implementer_method_storage_return_type->getId() . '\'', $implementer_method_storage->return_type_location ?: $code_location), $suppressed_issues)) { // fall through } } } } /** * @param array> $template_type_extends */ private static function transformTemplates(array $template_type_extends, string $base_class_name, \Psalm\Type\Union $templated_type, \Psalm\Codebase $codebase) : void { if (isset($template_type_extends[$base_class_name])) { $map = $template_type_extends[$base_class_name]; $template_types = []; foreach ($map as $key => $mapped_type) { if (\is_string($key)) { $new_bases = []; foreach ($mapped_type->getTemplateTypes() as $mapped_atomic_type) { if ($mapped_atomic_type->defining_class === $base_class_name) { continue; } $new_bases[] = $mapped_atomic_type->defining_class; } if ($new_bases) { $mapped_type = clone $mapped_type; foreach ($new_bases as $new_base_class_name) { self::transformTemplates($template_type_extends, $new_base_class_name, $mapped_type, $codebase); } } $template_types[$key][$base_class_name] = [$mapped_type]; } } $template_result = new \Psalm\Internal\Type\TemplateResult([], $template_types); $templated_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); } } } */ private $required_file_paths = []; /** * @var array */ private $parent_file_paths = []; /** * @var array */ private $suppressed_issues = []; /** * @var array> */ private $namespace_aliased_classes = []; /** * @var array> */ private $namespace_aliased_classes_flipped = []; /** * @var array> */ private $namespace_aliased_classes_flipped_replaceable = []; /** * @var array */ public $interface_analyzers_to_analyze = []; /** * @var array */ public $class_analyzers_to_analyze = []; /** * @var null|Context */ public $context; /** * @var ProjectAnalyzer */ public $project_analyzer; /** * @var Codebase */ public $codebase; /** * @var int */ private $first_statement_offset = -1; /** @var ?\Psalm\Internal\Provider\NodeDataProvider */ private $node_data; /** @var ?Type\Union */ private $return_type; public function __construct(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, string $file_path, string $file_name) { $this->source = $this; $this->file_path = $file_path; $this->file_name = $file_name; $this->project_analyzer = $project_analyzer; $this->codebase = $project_analyzer->getCodebase(); } public function analyze(?\Psalm\Context $file_context = null, bool $preserve_analyzers = \false, ?\Psalm\Context $global_context = null) : void { $codebase = $this->project_analyzer->getCodebase(); $file_storage = $codebase->file_storage_provider->get($this->file_path); if (!$file_storage->deep_scan && !$codebase->server_mode) { throw new \Psalm\Exception\UnpreparedAnalysisException('File ' . $this->file_path . ' has not been properly scanned'); } if ($file_storage->has_visitor_issues) { return; } if ($file_context) { $this->context = $file_context; } if (!$this->context) { $this->context = new \Psalm\Context(); } if ($codebase->config->useStrictTypesForFile($this->file_path)) { $this->context->strict_types = \true; } $this->context->is_global = \true; $this->context->defineGlobals(); $this->context->collect_exceptions = $codebase->config->check_for_throws_in_global_scope; try { $stmts = $codebase->getStatementsForFile($this->file_path); } catch (\_HumbugBoxd02f763d3c56\PhpParser\Error $e) { return; } foreach ($codebase->config->before_file_checks as $plugin_class) { $plugin_class::beforeAnalyzeFile($this, $this->context, $file_storage, $codebase); } if ($codebase->alter_code) { foreach ($stmts as $stmt) { if (!$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Declare_) { $this->first_statement_offset = (int) $stmt->getAttribute('startFilePos'); break; } } } $leftover_stmts = $this->populateCheckers($stmts); $this->node_data = new \Psalm\Internal\Provider\NodeDataProvider(); $statements_analyzer = new \Psalm\Internal\Analyzer\StatementsAnalyzer($this, $this->node_data); foreach ($file_storage->docblock_issues as $docblock_issue) { \Psalm\IssueBuffer::add($docblock_issue); } // if there are any leftover statements, evaluate them, // in turn causing the classes/interfaces be evaluated if ($leftover_stmts) { $statements_analyzer->analyze($leftover_stmts, $this->context, $global_context, \true); foreach ($leftover_stmts as $leftover_stmt) { if ($leftover_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_) { if ($leftover_stmt->expr) { $this->return_type = $statements_analyzer->node_data->getType($leftover_stmt->expr) ?: \Psalm\Type::getMixed(); } else { $this->return_type = \Psalm\Type::getVoid(); } break; } } } // check any leftover interfaces not already evaluated foreach ($this->interface_analyzers_to_analyze as $interface_analyzer) { $interface_analyzer->analyze(); } // check any leftover classes not already evaluated foreach ($this->class_analyzers_to_analyze as $class_analyzer) { $class_analyzer->analyze(null, $this->context); } if (!$preserve_analyzers) { $this->class_analyzers_to_analyze = []; $this->interface_analyzers_to_analyze = []; } if ($codebase->config->check_for_throws_in_global_scope) { $uncaught_throws = $statements_analyzer->getUncaughtThrows($this->context); foreach ($uncaught_throws as $possibly_thrown_exception => $codelocations) { foreach ($codelocations as $codelocation) { // issues are suppressed in ThrowAnalyzer, CallAnalyzer, etc. if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UncaughtThrowInGlobalScope($possibly_thrown_exception . ' is thrown but not caught in global scope', $codelocation))) { // fall through } } } } // validate type imports if ($file_storage->type_aliases) { foreach ($file_storage->type_aliases as $alias) { if ($alias instanceof \Psalm\Internal\Type\TypeAlias\LinkableTypeAlias) { $location = new \Psalm\CodeLocation\DocblockTypeLocation($this->getSource(), $alias->start_offset, $alias->end_offset, $alias->line_number); $fq_source_classlike = $alias->declaring_fq_classlike_name; if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($this->getSource(), $fq_source_classlike, $location, null, null, $this->suppressed_issues, \true, \false, \true, \true) === \false) { continue; } $referenced_class_storage = $codebase->classlike_storage_provider->get($fq_source_classlike); if (!isset($referenced_class_storage->type_aliases[$alias->alias_name])) { \Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidTypeImport('Type alias ' . $alias->alias_name . ' imported from ' . $fq_source_classlike . ' is not defined on the source class', $location)); } } } } foreach ($codebase->config->after_file_checks as $plugin_class) { $plugin_class::afterAnalyzeFile($this, $this->context, $file_storage, $codebase); } } /** * @param array $stmts * * @return list */ public function populateCheckers(array $stmts) : array { $leftover_stmts = []; foreach ($stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike) { $this->populateClassLikeAnalyzers($stmt); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { $namespace_name = $stmt->name ? \implode('\\', $stmt->name->parts) : ''; $namespace_analyzer = new \Psalm\Internal\Analyzer\NamespaceAnalyzer($stmt, $this); $namespace_analyzer->collectAnalyzableInformation(); $this->namespace_aliased_classes[$namespace_name] = $namespace_analyzer->getAliases()->uses; $this->namespace_aliased_classes_flipped[$namespace_name] = $namespace_analyzer->getAliasedClassesFlipped(); $this->namespace_aliased_classes_flipped_replaceable[$namespace_name] = $namespace_analyzer->getAliasedClassesFlippedReplaceable(); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_) { $this->visitUse($stmt); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { $this->visitGroupUse($stmt); } else { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_) { foreach ($stmt->stmts as $if_stmt) { if ($if_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike) { $this->populateClassLikeAnalyzers($if_stmt); } } } $leftover_stmts[] = $stmt; } } return $leftover_stmts; } private function populateClassLikeAnalyzers(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike $stmt) : void { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { if (!$stmt->name) { return; } // this can happen when stubbing if (!$this->codebase->classExists($stmt->name->name)) { return; } $class_analyzer = new \Psalm\Internal\Analyzer\ClassAnalyzer($stmt, $this, $stmt->name->name); $fq_class_name = $class_analyzer->getFQCLN(); $this->class_analyzers_to_analyze[\strtolower($fq_class_name)] = $class_analyzer; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_) { if (!$stmt->name) { return; } // this can happen when stubbing if (!$this->codebase->interfaceExists($stmt->name->name)) { return; } $class_analyzer = new \Psalm\Internal\Analyzer\InterfaceAnalyzer($stmt, $this, $stmt->name->name); $fq_class_name = $class_analyzer->getFQCLN(); $this->interface_analyzers_to_analyze[$fq_class_name] = $class_analyzer; } } public function addNamespacedClassAnalyzer(string $fq_class_name, \Psalm\Internal\Analyzer\ClassAnalyzer $class_analyzer) : void { $this->class_analyzers_to_analyze[\strtolower($fq_class_name)] = $class_analyzer; } public function addNamespacedInterfaceAnalyzer(string $fq_class_name, \Psalm\Internal\Analyzer\InterfaceAnalyzer $interface_analyzer) : void { $this->interface_analyzers_to_analyze[\strtolower($fq_class_name)] = $interface_analyzer; } public function getMethodMutations(\Psalm\Internal\MethodIdentifier $method_id, \Psalm\Context $this_context, bool $from_project_analyzer = \false) : void { $fq_class_name = $method_id->fq_class_name; $method_name = $method_id->method_name; $fq_class_name_lc = \strtolower($fq_class_name); if (isset($this->class_analyzers_to_analyze[$fq_class_name_lc])) { $class_analyzer_to_examine = $this->class_analyzers_to_analyze[$fq_class_name_lc]; } else { if (!$from_project_analyzer) { $this->project_analyzer->getMethodMutations($method_id, $this_context, $this->getRootFilePath(), $this->getRootFileName()); } return; } $call_context = new \Psalm\Context($this_context->self); $call_context->collect_mutations = $this_context->collect_mutations; $call_context->collect_initializations = $this_context->collect_initializations; $call_context->collect_nonprivate_initializations = $this_context->collect_nonprivate_initializations; $call_context->initialized_methods = $this_context->initialized_methods; $call_context->include_location = $this_context->include_location; $call_context->calling_method_id = $this_context->calling_method_id; foreach ($this_context->vars_possibly_in_scope as $var => $_) { if (\strpos($var, '$this->') === 0) { $call_context->vars_possibly_in_scope[$var] = \true; } } foreach ($this_context->vars_in_scope as $var => $type) { if (\strpos($var, '$this->') === 0) { $call_context->vars_in_scope[$var] = $type; } } if (!isset($this_context->vars_in_scope['$this'])) { throw new \UnexpectedValueException('Should exist'); } $call_context->vars_in_scope['$this'] = $this_context->vars_in_scope['$this']; $class_analyzer_to_examine->getMethodMutations($method_name, $call_context); foreach ($call_context->vars_possibly_in_scope as $var => $_) { $this_context->vars_possibly_in_scope[$var] = \true; } foreach ($call_context->vars_in_scope as $var => $type) { $this_context->vars_in_scope[$var] = $type; } } public function getFunctionLikeAnalyzer(\Psalm\Internal\MethodIdentifier $method_id) : ?\Psalm\Internal\Analyzer\MethodAnalyzer { $fq_class_name = $method_id->fq_class_name; $method_name = $method_id->method_name; $fq_class_name_lc = \strtolower($fq_class_name); if (!isset($this->class_analyzers_to_analyze[$fq_class_name_lc])) { return null; } $class_analyzer_to_examine = $this->class_analyzers_to_analyze[$fq_class_name_lc]; return $class_analyzer_to_examine->getFunctionLikeAnalyzer($method_name); } public function getNamespace() : ?string { return null; } /** * @return array */ public function getAliasedClassesFlipped(?string $namespace_name = null) : array { if ($namespace_name && isset($this->namespace_aliased_classes_flipped[$namespace_name])) { return $this->namespace_aliased_classes_flipped[$namespace_name]; } return $this->aliased_classes_flipped; } /** * @return array */ public function getAliasedClassesFlippedReplaceable(?string $namespace_name = null) : array { if ($namespace_name && isset($this->namespace_aliased_classes_flipped_replaceable[$namespace_name])) { return $this->namespace_aliased_classes_flipped_replaceable[$namespace_name]; } return $this->aliased_classes_flipped_replaceable; } public static function clearCache() : void { \Psalm\Internal\Type\TypeTokenizer::clearCache(); \Psalm\Internal\Codebase\Reflection::clearCache(); \Psalm\Internal\Codebase\Functions::clearCache(); \Psalm\IssueBuffer::clearCache(); \Psalm\Internal\FileManipulation\FileManipulationBuffer::clearCache(); \Psalm\Internal\Analyzer\FunctionLikeAnalyzer::clearCache(); \Psalm\Internal\Provider\ClassLikeStorageProvider::deleteAll(); \Psalm\Internal\Provider\FileStorageProvider::deleteAll(); \Psalm\Internal\Provider\FileReferenceProvider::clearCache(); \Psalm\Internal\Codebase\InternalCallMapHandler::clearCache(); } public function getFileName() : string { return $this->file_name; } public function getFilePath() : string { return $this->file_path; } public function getRootFileName() : string { return $this->root_file_name ?: $this->file_name; } public function getRootFilePath() : string { return $this->root_file_path ?: $this->file_path; } public function setRootFilePath(string $file_path, string $file_name) : void { $this->root_file_name = $file_name; $this->root_file_path = $file_path; } public function addRequiredFilePath(string $file_path) : void { $this->required_file_paths[$file_path] = \true; } public function addParentFilePath(string $file_path) : void { $this->parent_file_paths[$file_path] = \true; } public function hasParentFilePath(string $file_path) : bool { return $this->file_path === $file_path || isset($this->parent_file_paths[$file_path]); } public function hasAlreadyRequiredFilePath(string $file_path) : bool { return isset($this->required_file_paths[$file_path]); } /** * @return list */ public function getRequiredFilePaths() : array { return \array_keys($this->required_file_paths); } /** * @return list */ public function getParentFilePaths() : array { return \array_keys($this->parent_file_paths); } public function getRequireNesting() : int { return \count($this->parent_file_paths); } /** * @return array */ public function getSuppressedIssues() : array { return $this->suppressed_issues; } /** * @param array $new_issues */ public function addSuppressedIssues(array $new_issues) : void { if (isset($new_issues[0])) { $new_issues = \array_combine($new_issues, $new_issues); } $this->suppressed_issues = $new_issues + $this->suppressed_issues; } /** * @param array $new_issues */ public function removeSuppressedIssues(array $new_issues) : void { if (isset($new_issues[0])) { $new_issues = \array_combine($new_issues, $new_issues); } $this->suppressed_issues = \array_diff_key($this->suppressed_issues, $new_issues); } public function getFQCLN() : ?string { return null; } public function getParentFQCLN() : ?string { return null; } public function getClassName() : ?string { return null; } /** * @return array>|null */ public function getTemplateTypeMap() : ?array { return null; } public function isStatic() : bool { return \false; } /** * @psalm-mutation-free */ public function getFileAnalyzer() : \Psalm\Internal\Analyzer\FileAnalyzer { return $this; } /** * @psalm-mutation-free */ public function getProjectAnalyzer() : \Psalm\Internal\Analyzer\ProjectAnalyzer { return $this->project_analyzer; } public function getCodebase() : \Psalm\Codebase { return $this->codebase; } public function getFirstStatementOffset() : int { return $this->first_statement_offset; } public function getNodeTypeProvider() : \Psalm\NodeTypeProvider { if (!$this->node_data) { throw new \UnexpectedValueException('There should be a node type provider'); } return $this->node_data; } public function getReturnType() : ?\Psalm\Type\Union { return $this->return_type; } public function clearSourceBeforeDestruction() : void { /** @psalm-suppress PossiblyNullPropertyAssignmentValue */ $this->source = null; } } */ private $issues_to_fix = []; /** * @var bool */ public $dry_run = \false; /** * @var bool */ public $full_run = \false; /** * @var bool */ public $only_replace_php_types_with_non_docblock_types = \false; /** * @var ?int */ public $onchange_line_limit; /** * @var bool */ public $provide_completion = \false; /** * @var array */ private $project_files = []; /** * @var array */ private $extra_files = []; /** * @var array */ private $to_refactor = []; /** * @var ?ReportOptions */ public $stdout_report_options; /** * @var array */ public $generated_report_options; /** * @var array> */ private const SUPPORTED_ISSUES_TO_FIX = [\Psalm\Issue\InvalidFalsableReturnType::class, \Psalm\Issue\InvalidNullableReturnType::class, \Psalm\Issue\InvalidReturnType::class, \Psalm\Issue\LessSpecificReturnType::class, \Psalm\Issue\MismatchingDocblockParamType::class, \Psalm\Issue\MismatchingDocblockReturnType::class, \Psalm\Issue\MissingClosureReturnType::class, \Psalm\Issue\MissingParamType::class, \Psalm\Issue\MissingPropertyType::class, \Psalm\Issue\MissingReturnType::class, \Psalm\Issue\ParamNameMismatch::class, \Psalm\Issue\PossiblyUndefinedGlobalVariable::class, \Psalm\Issue\PossiblyUndefinedVariable::class, \Psalm\Issue\PossiblyUnusedMethod::class, \Psalm\Issue\PossiblyUnusedProperty::class, \Psalm\Issue\UnusedMethod::class, \Psalm\Issue\UnusedProperty::class, \Psalm\Issue\UnusedVariable::class, \Psalm\Issue\UnnecessaryVarAnnotation::class]; /** * When this is true, the language server will send the diagnostic code with a help link. * * @var bool */ public $language_server_use_extended_diagnostic_codes = \false; /** * If this is true then the language server will send log messages to the client with additional information. * * @var bool */ public $language_server_verbose = \false; /** * @param array $generated_report_options * @param string $reports */ public function __construct(\Psalm\Config $config, \Psalm\Internal\Provider\Providers $providers, ?\Psalm\Report\ReportOptions $stdout_report_options = null, array $generated_report_options = [], int $threads = 1, ?\Psalm\Progress\Progress $progress = null) { if ($progress === null) { $progress = new \Psalm\Progress\VoidProgress(); } $this->parser_cache_provider = $providers->parser_cache_provider; $this->project_cache_provider = $providers->project_cache_provider; $this->file_provider = $providers->file_provider; $this->classlike_storage_provider = $providers->classlike_storage_provider; $this->file_reference_provider = $providers->file_reference_provider; $this->progress = $progress; $this->threads = $threads; $this->config = $config; $this->clearCacheDirectoryIfConfigOrComposerLockfileChanged(); $this->codebase = new \Psalm\Codebase($config, $providers, $progress); $this->stdout_report_options = $stdout_report_options; $this->generated_report_options = $generated_report_options; $file_extensions = $this->config->getFileExtensions(); foreach ($this->config->getProjectDirectories() as $dir_name) { $file_paths = $this->file_provider->getFilesInDir($dir_name, $file_extensions); foreach ($file_paths as $file_path) { if ($this->config->isInProjectDirs($file_path)) { $this->addProjectFile($file_path); } } } foreach ($this->config->getExtraDirectories() as $dir_name) { $file_paths = $this->file_provider->getFilesInDir($dir_name, $file_extensions); foreach ($file_paths as $file_path) { if ($this->config->isInExtraDirs($file_path)) { $this->addExtraFile($file_path); } } } foreach ($this->config->getProjectFiles() as $file_path) { $this->addProjectFile($file_path); } self::$instance = $this; } private function clearCacheDirectoryIfConfigOrComposerLockfileChanged() : void { if ($this->project_cache_provider && $this->project_cache_provider->hasLockfileChanged()) { $this->progress->debug('Composer lockfile change detected, clearing cache' . "\n"); $cache_directory = $this->config->getCacheDirectory(); if ($cache_directory !== null) { \Psalm\Config::removeCacheDirectory($cache_directory); } if ($this->file_reference_provider->cache) { $this->file_reference_provider->cache->hasConfigChanged(); } $this->project_cache_provider->updateComposerLockHash(); } elseif ($this->file_reference_provider->cache && $this->file_reference_provider->cache->hasConfigChanged()) { $this->progress->debug('Config change detected, clearing cache' . "\n"); $cache_directory = $this->config->getCacheDirectory(); if ($cache_directory !== null) { \Psalm\Config::removeCacheDirectory($cache_directory); } if ($this->project_cache_provider) { $this->project_cache_provider->hasLockfileChanged(); } } } /** * @param array $report_file_paths * @return list */ public static function getFileReportOptions(array $report_file_paths, bool $show_info = \true) : array { $report_options = []; $mapping = ['checkstyle.xml' => \Psalm\Report::TYPE_CHECKSTYLE, 'sonarqube.json' => \Psalm\Report::TYPE_SONARQUBE, 'summary.json' => \Psalm\Report::TYPE_JSON_SUMMARY, 'junit.xml' => \Psalm\Report::TYPE_JUNIT, '.xml' => \Psalm\Report::TYPE_XML, '.json' => \Psalm\Report::TYPE_JSON, '.txt' => \Psalm\Report::TYPE_TEXT, '.emacs' => \Psalm\Report::TYPE_EMACS, '.pylint' => \Psalm\Report::TYPE_PYLINT, '.console' => \Psalm\Report::TYPE_CONSOLE]; foreach ($report_file_paths as $report_file_path) { foreach ($mapping as $extension => $type) { if (\substr($report_file_path, -\strlen($extension)) === $extension) { $o = new \Psalm\Report\ReportOptions(); $o->format = $type; $o->show_info = $show_info; $o->output_path = $report_file_path; $o->use_color = \false; $report_options[] = $o; continue 2; } } throw new \UnexpectedValueException('Unknown report format ' . $report_file_path); } return $report_options; } private function visitAutoloadFiles() : void { $start_time = \microtime(\true); $this->config->visitComposerAutoloadFiles($this, $this->progress); $now_time = \microtime(\true); $this->progress->debug('Visiting autoload files took ' . \number_format($now_time - $start_time, 3) . 's' . "\n"); } public function server(?string $address = '127.0.0.1:12345', bool $socket_server_mode = \false) : void { $this->visitAutoloadFiles(); $this->codebase->diff_methods = \true; $this->file_reference_provider->loadReferenceCache(); $this->codebase->enterServerMode(); if (\ini_get('pcre.jit') === '1' && \PHP_OS === 'Darwin' && \version_compare(\PHP_VERSION, '7.3.0') >= 0 && \version_compare(\PHP_VERSION, '7.4.0') < 0) { // do nothing } else { $cpu_count = self::getCpuCount(); // let's not go crazy $usable_cpus = $cpu_count - 2; if ($usable_cpus > 1) { $this->threads = $usable_cpus; } } $this->config->initializePlugins($this); foreach ($this->config->getProjectDirectories() as $dir_name) { $this->checkDirWithConfig($dir_name, $this->config); } @\cli_set_process_title('Psalm ' . PSALM_VERSION . ' - PHP Language Server'); if (!$socket_server_mode && $address) { // Connect to a TCP server $socket = \stream_socket_client('tcp://' . $address, $errno, $errstr); if ($socket === \false) { \fwrite(\STDERR, "Could not connect to language client. Error {$errno}\n{$errstr}"); exit(1); } \stream_set_blocking($socket, \false); new \Psalm\Internal\LanguageServer\LanguageServer(new \Psalm\Internal\LanguageServer\ProtocolStreamReader($socket), new \Psalm\Internal\LanguageServer\ProtocolStreamWriter($socket), $this); \_HumbugBoxd02f763d3c56\Amp\Loop::run(); } elseif ($socket_server_mode && $address) { // Run a TCP Server $tcpServer = \stream_socket_server('tcp://' . $address, $errno, $errstr); if ($tcpServer === \false) { \fwrite(\STDERR, "Could not listen on {$address}. Error {$errno}\n{$errstr}"); exit(1); } \fwrite(\STDOUT, "Server listening on {$address}\n"); $fork_available = \true; if (!\extension_loaded('pcntl')) { \fwrite(\STDERR, "PCNTL is not available. Only a single connection will be accepted\n"); $fork_available = \false; } $disabled_functions = \array_map('trim', \explode(',', \ini_get('disable_functions'))); if (\in_array('pcntl_fork', $disabled_functions)) { \fwrite(\STDERR, "pcntl_fork() is disabled by php configuration (disable_functions directive)." . " Only a single connection will be accepted\n"); $fork_available = \false; } while ($socket = \stream_socket_accept($tcpServer, -1)) { \fwrite(\STDOUT, "Connection accepted\n"); \stream_set_blocking($socket, \false); if ($fork_available) { // If PCNTL is available, fork a child process for the connection // An exit notification will only terminate the child process $pid = \pcntl_fork(); if ($pid === -1) { \fwrite(\STDERR, "Could not fork\n"); exit(1); } if ($pid === 0) { // Child process $reader = new \Psalm\Internal\LanguageServer\ProtocolStreamReader($socket); $reader->on('close', function () : void { \fwrite(\STDOUT, "Connection closed\n"); }); new \Psalm\Internal\LanguageServer\LanguageServer($reader, new \Psalm\Internal\LanguageServer\ProtocolStreamWriter($socket), $this); // Just for safety exit(0); } } else { // If PCNTL is not available, we only accept one connection. // An exit notification will terminate the server new \Psalm\Internal\LanguageServer\LanguageServer(new \Psalm\Internal\LanguageServer\ProtocolStreamReader($socket), new \Psalm\Internal\LanguageServer\ProtocolStreamWriter($socket), $this); \_HumbugBoxd02f763d3c56\Amp\Loop::run(); } } } else { // Use STDIO \stream_set_blocking(\STDIN, \false); new \Psalm\Internal\LanguageServer\LanguageServer(new \Psalm\Internal\LanguageServer\ProtocolStreamReader(\STDIN), new \Psalm\Internal\LanguageServer\ProtocolStreamWriter(\STDOUT), $this); \_HumbugBoxd02f763d3c56\Amp\Loop::run(); } } public static function getInstance() : \Psalm\Internal\Analyzer\ProjectAnalyzer { return self::$instance; } public function canReportIssues(string $file_path) : bool { return isset($this->project_files[$file_path]); } public function check(string $base_dir, bool $is_diff = \false) : void { $start_checks = (int) \microtime(\true); if (!$base_dir) { throw new \InvalidArgumentException('Cannot work with empty base_dir'); } $diff_files = null; $deleted_files = null; $this->full_run = \true; $reference_cache = $this->file_reference_provider->loadReferenceCache(\true); $this->codebase->diff_methods = $is_diff; if ($is_diff && $reference_cache && $this->project_cache_provider && $this->project_cache_provider->canDiffFiles()) { $deleted_files = $this->file_reference_provider->getDeletedReferencedFiles(); $diff_files = $deleted_files; foreach ($this->config->getProjectDirectories() as $dir_name) { $diff_files = \array_merge($diff_files, $this->getDiffFilesInDir($dir_name, $this->config)); } } $this->progress->startScanningFiles(); $diff_no_files = \false; if ($diff_files === null || $deleted_files === null || \count($diff_files) > 200) { $this->visitAutoloadFiles(); $this->codebase->scanner->addFilesToShallowScan($this->extra_files); $this->codebase->scanner->addFilesToDeepScan($this->project_files); $this->codebase->analyzer->addFilesToAnalyze($this->project_files); $this->config->initializePlugins($this); $this->codebase->scanFiles($this->threads); $this->codebase->infer_types_from_usage = \true; } else { $this->progress->debug(\count($diff_files) . ' changed files: ' . "\n"); $this->progress->debug(' ' . \implode("\n ", $diff_files) . "\n"); $this->codebase->analyzer->addFilesToShowResults($this->project_files); if ($diff_files) { $file_list = $this->getReferencedFilesFromDiff($diff_files); // strip out deleted files $file_list = \array_diff($file_list, $deleted_files); if ($file_list) { $this->visitAutoloadFiles(); $this->checkDiffFilesWithConfig($this->config, $file_list); $this->config->initializePlugins($this); $this->codebase->scanFiles($this->threads); } else { $diff_no_files = \true; } } else { $diff_no_files = \true; } } if (!$diff_no_files) { $this->config->visitStubFiles($this->codebase, $this->progress); $plugin_classes = $this->config->after_codebase_populated; if ($plugin_classes) { foreach ($plugin_classes as $plugin_fq_class_name) { $plugin_fq_class_name::afterCodebasePopulated($this->codebase); } } } $this->progress->startAnalyzingFiles(); $this->codebase->analyzer->analyzeFiles($this, $this->threads, $this->codebase->alter_code, \true); if ($this->project_cache_provider && $this->parser_cache_provider) { $removed_parser_files = $this->parser_cache_provider->deleteOldParserCaches($is_diff ? $this->project_cache_provider->getLastRun() : $start_checks); if ($removed_parser_files) { $this->progress->debug('Removed ' . $removed_parser_files . ' old parser caches' . "\n"); } if ($is_diff) { $this->parser_cache_provider->touchParserCaches($this->getAllFiles($this->config), $start_checks); } } } public function consolidateAnalyzedData() : void { $this->codebase->classlikes->consolidateAnalyzedData($this->codebase->methods, $this->progress, !!$this->codebase->find_unused_code); } public function trackTaintedInputs() : void { $this->codebase->taint_flow_graph = new \Psalm\Internal\Codebase\TaintFlowGraph(); } public function trackUnusedSuppressions() : void { $this->codebase->track_unused_suppressions = \true; } public function interpretRefactors() : void { if (!$this->codebase->alter_code) { throw new \UnexpectedValueException('Should not be checking references'); } // interpret wildcards foreach ($this->to_refactor as $source => $destination) { if (($source_pos = \strpos($source, '*')) && ($destination_pos = \strpos($destination, '*')) && $source_pos === \strlen($source) - 1 && $destination_pos === \strlen($destination) - 1) { foreach ($this->codebase->classlike_storage_provider->getAll() as $class_storage) { if (\substr($class_storage->name, 0, $source_pos) === \substr($source, 0, -1)) { $this->to_refactor[$class_storage->name] = \substr($destination, 0, -1) . \substr($class_storage->name, $source_pos); } } unset($this->to_refactor[$source]); } } foreach ($this->to_refactor as $source => $destination) { $source_parts = \explode('::', $source); $destination_parts = \explode('::', $destination); if (!$this->codebase->classlikes->hasFullyQualifiedClassName($source_parts[0])) { throw new \Psalm\Exception\RefactorException('Source class ' . $source_parts[0] . ' doesn’t exist'); } if (\count($source_parts) === 1 && \count($destination_parts) === 1) { if ($this->codebase->classlikes->hasFullyQualifiedClassName($destination_parts[0])) { throw new \Psalm\Exception\RefactorException('Destination class ' . $destination_parts[0] . ' already exists'); } $source_class_storage = $this->codebase->classlike_storage_provider->get($source_parts[0]); $destination_parts = \explode('\\', $destination, -1); $destination_ns = \implode('\\', $destination_parts); $this->codebase->classes_to_move[\strtolower($source)] = $destination; $destination_class_storage = $this->codebase->classlike_storage_provider->create($destination); $destination_class_storage->name = $destination; if ($source_class_storage->aliases) { $destination_class_storage->aliases = clone $source_class_storage->aliases; $destination_class_storage->aliases->namespace = $destination_ns; } $destination_class_storage->location = $source_class_storage->location; $destination_class_storage->stmt_location = $source_class_storage->stmt_location; $destination_class_storage->populated = \true; $this->codebase->class_transforms[\strtolower($source)] = $destination; continue; } $source_method_id = new \Psalm\Internal\MethodIdentifier($source_parts[0], \strtolower($source_parts[1])); if ($this->codebase->methods->methodExists($source_method_id)) { if ($this->codebase->methods->methodExists(new \Psalm\Internal\MethodIdentifier($destination_parts[0], \strtolower($destination_parts[1])))) { throw new \Psalm\Exception\RefactorException('Destination method ' . $destination . ' already exists'); } if (!$this->codebase->classlikes->classExists($destination_parts[0])) { throw new \Psalm\Exception\RefactorException('Destination class ' . $destination_parts[0] . ' doesn’t exist'); } if (\strtolower($source_parts[0]) !== \strtolower($destination_parts[0])) { $source_method_storage = $this->codebase->methods->getStorage($source_method_id); $destination_class_storage = $this->codebase->classlike_storage_provider->get($destination_parts[0]); if (!$source_method_storage->is_static && !isset($destination_class_storage->parent_classes[\strtolower($source_method_id->fq_class_name)])) { throw new \Psalm\Exception\RefactorException('Cannot move non-static method ' . $source . ' into unrelated class ' . $destination_parts[0]); } $this->codebase->methods_to_move[\strtolower($source)] = $destination; } else { $this->codebase->methods_to_rename[\strtolower($source)] = $destination_parts[1]; } $this->codebase->call_transforms[\strtolower($source) . '\\((.*\\))'] = $destination . '($1)'; continue; } if ($source_parts[1][0] === '$') { if ($destination_parts[1][0] !== '$') { throw new \Psalm\Exception\RefactorException('Destination property must be of the form Foo::$bar'); } if (!$this->codebase->properties->propertyExists($source, \true)) { throw new \Psalm\Exception\RefactorException('Property ' . $source . ' does not exist'); } if ($this->codebase->properties->propertyExists($destination, \true)) { throw new \Psalm\Exception\RefactorException('Destination property ' . $destination . ' already exists'); } if (!$this->codebase->classlikes->classExists($destination_parts[0])) { throw new \Psalm\Exception\RefactorException('Destination class ' . $destination_parts[0] . ' doesn’t exist'); } $source_id = \strtolower($source_parts[0]) . '::' . $source_parts[1]; if (\strtolower($source_parts[0]) !== \strtolower($destination_parts[0])) { $source_storage = $this->codebase->properties->getStorage($source); if (!$source_storage->is_static) { throw new \Psalm\Exception\RefactorException('Cannot move non-static property ' . $source); } $this->codebase->properties_to_move[$source_id] = $destination; } else { $this->codebase->properties_to_rename[$source_id] = \substr($destination_parts[1], 1); } $this->codebase->property_transforms[$source_id] = $destination; continue; } $source_class_constants = $this->codebase->classlikes->getConstantsForClass($source_parts[0], \ReflectionProperty::IS_PRIVATE); if (isset($source_class_constants[$source_parts[1]])) { if (!$this->codebase->classlikes->hasFullyQualifiedClassName($destination_parts[0])) { throw new \Psalm\Exception\RefactorException('Destination class ' . $destination_parts[0] . ' doesn’t exist'); } $destination_class_constants = $this->codebase->classlikes->getConstantsForClass($destination_parts[0], \ReflectionProperty::IS_PRIVATE); if (isset($destination_class_constants[$destination_parts[1]])) { throw new \Psalm\Exception\RefactorException('Destination constant ' . $destination . ' already exists'); } $source_id = \strtolower($source_parts[0]) . '::' . $source_parts[1]; if (\strtolower($source_parts[0]) !== \strtolower($destination_parts[0])) { $this->codebase->class_constants_to_move[$source_id] = $destination; } else { $this->codebase->class_constants_to_rename[$source_id] = $destination_parts[1]; } $this->codebase->class_constant_transforms[$source_id] = $destination; continue; } throw new \Psalm\Exception\RefactorException('Psalm cannot locate ' . $source); } } public function prepareMigration() : void { if (!$this->codebase->alter_code) { throw new \UnexpectedValueException('Should not be checking references'); } $this->codebase->classlikes->moveMethods($this->codebase->methods, $this->progress); $this->codebase->classlikes->moveProperties($this->codebase->properties, $this->progress); $this->codebase->classlikes->moveClassConstants($this->progress); } public function migrateCode() : void { if (!$this->codebase->alter_code) { throw new \UnexpectedValueException('Should not be checking references'); } $migration_manipulations = \Psalm\Internal\FileManipulation\FileManipulationBuffer::getMigrationManipulations($this->codebase->file_provider); if ($migration_manipulations) { foreach ($migration_manipulations as $file_path => $file_manipulations) { \usort($file_manipulations, function (\Psalm\FileManipulation $a, \Psalm\FileManipulation $b) : int { if ($a->start === $b->start) { if ($b->end === $a->end) { return $b->insertion_text > $a->insertion_text ? 1 : -1; } return $b->end > $a->end ? 1 : -1; } return $b->start > $a->start ? 1 : -1; }); $existing_contents = $this->codebase->file_provider->getContents($file_path); foreach ($file_manipulations as $manipulation) { $existing_contents = $manipulation->transform($existing_contents); } $this->codebase->file_provider->setContents($file_path, $existing_contents); } } if ($this->codebase->classes_to_move) { foreach ($this->codebase->classes_to_move as $source => $destination) { $source_class_storage = $this->codebase->classlike_storage_provider->get($source); if (!$source_class_storage->location) { continue; } $potential_file_path = $this->config->getPotentialComposerFilePathForClassLike($destination); if ($potential_file_path && !\file_exists($potential_file_path)) { $containing_dir = \dirname($potential_file_path); if (!\file_exists($containing_dir)) { \mkdir($containing_dir, 0777, \true); } \rename($source_class_storage->location->file_path, $potential_file_path); } } } } public function findReferencesTo(string $symbol) : void { if (!$this->stdout_report_options) { throw new \UnexpectedValueException('Not expecting to emit output'); } $locations = $this->codebase->findReferencesToSymbol($symbol); foreach ($locations as $location) { $snippet = $location->getSnippet(); $snippet_bounds = $location->getSnippetBounds(); $selection_bounds = $location->getSelectionBounds(); $selection_start = $selection_bounds[0] - $snippet_bounds[0]; $selection_length = $selection_bounds[1] - $selection_bounds[0]; echo $location->file_name . ':' . $location->getLineNumber() . "\n" . ($this->stdout_report_options->use_color ? \substr($snippet, 0, $selection_start) . "\33[97;42m" . \substr($snippet, $selection_start, $selection_length) . "\33[0m" . \substr($snippet, $selection_length + $selection_start) : $snippet) . "\n" . "\n"; } } public function checkDir(string $dir_name) : void { $this->file_reference_provider->loadReferenceCache(); $this->checkDirWithConfig($dir_name, $this->config, \true); $this->progress->startScanningFiles(); $this->config->initializePlugins($this); $this->codebase->scanFiles($this->threads); $this->config->visitStubFiles($this->codebase, $this->progress); $this->progress->startAnalyzingFiles(); $this->codebase->analyzer->analyzeFiles($this, $this->threads, $this->codebase->alter_code, $this->codebase->find_unused_code === 'always'); } private function checkDirWithConfig(string $dir_name, \Psalm\Config $config, bool $allow_non_project_files = \false) : void { $file_extensions = $config->getFileExtensions(); $file_paths = $this->file_provider->getFilesInDir($dir_name, $file_extensions); $files_to_scan = []; foreach ($file_paths as $file_path) { if ($allow_non_project_files || $config->isInProjectDirs($file_path)) { $files_to_scan[$file_path] = $file_path; } } $this->codebase->addFilesToAnalyze($files_to_scan); } /** * @return list */ private function getAllFiles(\Psalm\Config $config) : array { $file_extensions = $config->getFileExtensions(); $file_paths = []; foreach ($config->getProjectDirectories() as $dir_name) { $file_paths = \array_merge($file_paths, $this->file_provider->getFilesInDir($dir_name, $file_extensions)); } return $file_paths; } /** * @param string $dir_name * */ public function addProjectFile(string $file_path) : void { $this->project_files[$file_path] = $file_path; } public function addExtraFile(string $file_path) : void { $this->extra_files[$file_path] = $file_path; } /** * @return list */ protected function getDiffFilesInDir(string $dir_name, \Psalm\Config $config) : array { $file_extensions = $config->getFileExtensions(); if (!$this->parser_cache_provider || !$this->project_cache_provider) { throw new \UnexpectedValueException('Parser cache provider cannot be null here'); } $diff_files = []; $last_run = $this->project_cache_provider->getLastRun(); $file_paths = $this->file_provider->getFilesInDir($dir_name, $file_extensions); foreach ($file_paths as $file_path) { if ($config->isInProjectDirs($file_path)) { if ($this->file_provider->getModifiedTime($file_path) > $last_run && $this->parser_cache_provider->loadExistingFileContentsFromCache($file_path) !== $this->file_provider->getContents($file_path)) { $diff_files[] = $file_path; } } } return $diff_files; } /** * @param array $file_list * */ private function checkDiffFilesWithConfig(\Psalm\Config $config, array $file_list = []) : void { $files_to_scan = []; foreach ($file_list as $file_path) { if (!$this->file_provider->fileExists($file_path)) { continue; } if (!$config->isInProjectDirs($file_path)) { $this->progress->debug('skipping ' . $file_path . "\n"); continue; } $files_to_scan[$file_path] = $file_path; } $this->codebase->addFilesToAnalyze($files_to_scan); } public function checkFile(string $file_path) : void { $this->progress->debug('Checking ' . $file_path . "\n"); $this->config->hide_external_errors = $this->config->isInProjectDirs($file_path); $this->codebase->addFilesToAnalyze([$file_path => $file_path]); $this->file_reference_provider->loadReferenceCache(); $this->progress->startScanningFiles(); $this->config->initializePlugins($this); $this->codebase->scanFiles($this->threads); $this->config->visitStubFiles($this->codebase, $this->progress); $this->progress->startAnalyzingFiles(); $this->codebase->analyzer->analyzeFiles($this, $this->threads, $this->codebase->alter_code, $this->codebase->find_unused_code === 'always'); } /** * @param string[] $paths_to_check */ public function checkPaths(array $paths_to_check) : void { $this->visitAutoloadFiles(); foreach ($paths_to_check as $path) { $this->progress->debug('Checking ' . $path . "\n"); if (\is_dir($path)) { $this->checkDirWithConfig($path, $this->config, \true); } elseif (\is_file($path)) { $this->codebase->addFilesToAnalyze([$path => $path]); $this->config->hide_external_errors = $this->config->isInProjectDirs($path); } } $this->file_reference_provider->loadReferenceCache(); $this->progress->startScanningFiles(); $this->config->initializePlugins($this); $this->codebase->scanFiles($this->threads); $this->config->visitStubFiles($this->codebase, $this->progress); $this->progress->startAnalyzingFiles(); $this->codebase->analyzer->analyzeFiles($this, $this->threads, $this->codebase->alter_code, $this->codebase->find_unused_code === 'always'); if ($this->stdout_report_options && \in_array($this->stdout_report_options->format, [\Psalm\Report::TYPE_CONSOLE, \Psalm\Report::TYPE_PHP_STORM]) && $this->codebase->collect_references) { \fwrite(\STDERR, \PHP_EOL . 'To whom it may concern: Psalm cannot detect unused classes, methods and properties' . \PHP_EOL . 'when analyzing individual files and folders. Run on the full project to enable' . \PHP_EOL . 'complete unused code detection.' . \PHP_EOL); } } public function getConfig() : \Psalm\Config { return $this->config; } /** * @param array $diff_files * * @return array */ public function getReferencedFilesFromDiff(array $diff_files, bool $include_referencing_files = \true) : array { $all_inherited_files_to_check = $diff_files; while ($diff_files) { $diff_file = \array_shift($diff_files); $dependent_files = $this->file_reference_provider->getFilesInheritingFromFile($diff_file); $new_dependent_files = \array_diff($dependent_files, $all_inherited_files_to_check); $all_inherited_files_to_check = \array_merge($all_inherited_files_to_check, $new_dependent_files); $diff_files = \array_merge($diff_files, $new_dependent_files); } $all_files_to_check = $all_inherited_files_to_check; if ($include_referencing_files) { foreach ($all_inherited_files_to_check as $file_name) { $dependent_files = $this->file_reference_provider->getFilesReferencingFile($file_name); $all_files_to_check = \array_merge($dependent_files, $all_files_to_check); } } return \array_combine($all_files_to_check, $all_files_to_check); } public function fileExists(string $file_path) : bool { return $this->file_provider->fileExists($file_path); } public function alterCodeAfterCompletion(bool $dry_run = \false, bool $safe_types = \false) : void { $this->codebase->alter_code = \true; $this->codebase->infer_types_from_usage = \true; $this->show_issues = \false; $this->dry_run = $dry_run; $this->only_replace_php_types_with_non_docblock_types = $safe_types; } /** * @param array $to_refactor * */ public function refactorCodeAfterCompletion(array $to_refactor) : void { $this->to_refactor = $to_refactor; $this->codebase->alter_code = \true; $this->show_issues = \false; } public function setPhpVersion(string $version) : void { if (!\preg_match('/^(5\\.[456]|7\\.[01234]|8\\.[0])(\\..*)?$/', $version)) { throw new \UnexpectedValueException('Expecting a version number in the format x.y'); } [$php_major_version, $php_minor_version] = \explode('.', $version); $php_major_version = (int) $php_major_version; $php_minor_version = (int) $php_minor_version; if ($this->codebase->php_major_version !== $php_major_version || $this->codebase->php_minor_version !== $php_minor_version) { // reset lexer and parser when php version changes \Psalm\Internal\Provider\StatementsProvider::clearLexer(); \Psalm\Internal\Provider\StatementsProvider::clearParser(); } $this->codebase->php_major_version = $php_major_version; $this->codebase->php_minor_version = $php_minor_version; } /** * @param array $issues * @throws UnsupportedIssueToFixException * */ public function setIssuesToFix(array $issues) : void { $supported_issues_to_fix = static::getSupportedIssuesToFix(); $supported_issues_to_fix[] = 'MissingImmutableAnnotation'; $supported_issues_to_fix[] = 'MissingPureAnnotation'; $unsupportedIssues = \array_diff(\array_keys($issues), $supported_issues_to_fix); if (!empty($unsupportedIssues)) { throw new \Psalm\Exception\UnsupportedIssueToFixException('Psalm doesn\'t know how to fix issue(s): ' . \implode(', ', $unsupportedIssues) . \PHP_EOL . 'Supported issues to fix are: ' . \implode(',', $supported_issues_to_fix)); } $this->issues_to_fix = $issues; } public function setAllIssuesToFix() : void { $keyed_issues = \array_fill_keys(static::getSupportedIssuesToFix(), \true); $this->setIssuesToFix($keyed_issues); } /** * @return array */ public function getIssuesToFix() : array { return $this->issues_to_fix; } public function getCodebase() : \Psalm\Codebase { return $this->codebase; } public function getFileAnalyzerForClassLike(string $fq_class_name) : \Psalm\Internal\Analyzer\FileAnalyzer { $fq_class_name_lc = \strtolower($fq_class_name); $file_path = $this->codebase->scanner->getClassLikeFilePath($fq_class_name_lc); $file_analyzer = new \Psalm\Internal\Analyzer\FileAnalyzer($this, $file_path, $this->config->shortenFileName($file_path)); return $file_analyzer; } public function getMethodMutations(\Psalm\Internal\MethodIdentifier $original_method_id, \Psalm\Context $this_context, string $root_file_path, string $root_file_name) : void { $fq_class_name = $original_method_id->fq_class_name; $appearing_method_id = $this->codebase->methods->getAppearingMethodId($original_method_id); if (!$appearing_method_id) { // this can happen for some abstract classes implementing (but not fully) interfaces return; } $appearing_fq_class_name = $appearing_method_id->fq_class_name; $appearing_class_storage = $this->classlike_storage_provider->get($appearing_fq_class_name); if (!$appearing_class_storage->user_defined) { return; } $file_analyzer = $this->getFileAnalyzerForClassLike($fq_class_name); $file_analyzer->setRootFilePath($root_file_path, $root_file_name); if ($appearing_fq_class_name !== $fq_class_name) { $file_analyzer = $this->getFileAnalyzerForClassLike($appearing_fq_class_name); } $stmts = $this->codebase->getStatementsForFile($file_analyzer->getFilePath()); $file_analyzer->populateCheckers($stmts); if (!$this_context->self) { $this_context->self = $fq_class_name; $this_context->vars_in_scope['$this'] = \Psalm\Type::parseString($fq_class_name); } $file_analyzer->getMethodMutations($appearing_method_id, $this_context, \true); $file_analyzer->class_analyzers_to_analyze = []; $file_analyzer->interface_analyzers_to_analyze = []; $file_analyzer->clearSourceBeforeDestruction(); } public function getFunctionLikeAnalyzer(\Psalm\Internal\MethodIdentifier $method_id, string $file_path) : ?\Psalm\Internal\Analyzer\FunctionLikeAnalyzer { $file_analyzer = new \Psalm\Internal\Analyzer\FileAnalyzer($this, $file_path, $this->config->shortenFileName($file_path)); $stmts = $this->codebase->getStatementsForFile($file_analyzer->getFilePath()); $file_analyzer->populateCheckers($stmts); $function_analyzer = $file_analyzer->getFunctionLikeAnalyzer($method_id); $file_analyzer->class_analyzers_to_analyze = []; $file_analyzer->interface_analyzers_to_analyze = []; return $function_analyzer; } /** * Adapted from https://gist.github.com/divinity76/01ef9ca99c111565a72d3a8a6e42f7fb * returns number of cpu cores * Copyleft 2018, license: WTFPL * @throws \RuntimeException * @throws \LogicException * @psalm-suppress ForbiddenCode */ public static function getCpuCount() : int { if (\defined('PHP_WINDOWS_VERSION_MAJOR')) { /* $str = trim((string) shell_exec('wmic cpu get NumberOfCores 2>&1')); if (!preg_match('/(\d+)/', $str, $matches)) { throw new \RuntimeException('wmic failed to get number of cpu cores on windows!'); } return ((int) $matches [1]); */ return 1; } if (\ini_get('pcre.jit') === '1' && \PHP_OS === 'Darwin' && \version_compare(\PHP_VERSION, '7.3.0') >= 0 && \version_compare(\PHP_VERSION, '7.4.0') < 0) { return 1; } if (!\extension_loaded('pcntl')) { return 1; } $has_nproc = \trim((string) @\shell_exec('command -v nproc')); if ($has_nproc) { $ret = @\shell_exec('nproc'); if (\is_string($ret)) { $ret = \trim($ret); $tmp = \filter_var($ret, \FILTER_VALIDATE_INT); if (\is_int($tmp)) { return $tmp; } } } $ret = @\shell_exec('sysctl -n hw.ncpu'); if (\is_string($ret)) { $ret = \trim($ret); $tmp = \filter_var($ret, \FILTER_VALIDATE_INT); if (\is_int($tmp)) { return $tmp; } } if (\is_readable('/proc/cpuinfo')) { $cpuinfo = \file_get_contents('/proc/cpuinfo'); $count = \substr_count($cpuinfo, 'processor'); if ($count > 0) { return $count; } } throw new \LogicException('failed to detect number of CPUs!'); } /** * @return array * * @psalm-pure */ public static function getSupportedIssuesToFix() : array { return \array_map( /** @param class-string $issue_class */ function (string $issue_class) : string { $parts = \explode('\\', $issue_class); return \end($parts); }, self::SUPPORTED_ISSUES_TO_FIX ); } } inside_call; $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { $context->inside_call = $was_inside_call; return \false; } if ($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr)) { $yield_from_type = null; foreach ($stmt_expr_type->getAtomicTypes() as $atomic_type) { if ($yield_from_type === null) { if ($atomic_type instanceof \Psalm\Type\Atomic\TGenericObject && \strtolower($atomic_type->value) === 'generator' && isset($atomic_type->type_params[3])) { $yield_from_type = clone $atomic_type->type_params[3]; } elseif ($atomic_type instanceof \Psalm\Type\Atomic\TArray) { $yield_from_type = clone $atomic_type->type_params[1]; } elseif ($atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $yield_from_type = $atomic_type->getGenericValueType(); } } else { $yield_from_type = \Psalm\Type::getMixed(); } } // this should be whatever the generator above returns, but *not* the return type $statements_analyzer->node_data->setType($stmt, $yield_from_type ?: \Psalm\Type::getMixed()); } $context->inside_call = $was_inside_call; return \true; } } expr, $context) === \false) { return \false; } if (!($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr))) { $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TString()])); } elseif ($stmt_expr_type->isMixed()) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } else { $acceptable_types = []; $unacceptable_type = null; $has_valid_operand = \false; foreach ($stmt_expr_type->getAtomicTypes() as $type_string => $type_part) { if ($type_part instanceof \Psalm\Type\Atomic\TInt || $type_part instanceof \Psalm\Type\Atomic\TString) { if ($type_part instanceof \Psalm\Type\Atomic\TLiteralInt) { $type_part->value = ~$type_part->value; } elseif ($type_part instanceof \Psalm\Type\Atomic\TLiteralString) { $type_part->value = ~$type_part->value; } $acceptable_types[] = $type_part; $has_valid_operand = \true; } elseif ($type_part instanceof \Psalm\Type\Atomic\TFloat) { $type_part = $type_part instanceof \Psalm\Type\Atomic\TLiteralFloat ? new \Psalm\Type\Atomic\TLiteralInt(~$type_part->value) : new \Psalm\Type\Atomic\TInt(); $stmt_expr_type->removeType($type_string); $stmt_expr_type->addType($type_part); $acceptable_types[] = $type_part; $has_valid_operand = \true; } elseif (!$unacceptable_type) { $unacceptable_type = $type_part; } } if ($unacceptable_type || !$acceptable_types) { $message = 'Cannot negate a non-numeric non-string type ' . $unacceptable_type; if ($has_valid_operand) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidOperand($message, new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidOperand($message, new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } else { $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union($acceptable_types)); } } return \true; } } expr) { $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph) { $call_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $echo_param_sink = \Psalm\Internal\DataFlow\TaintSink::getForMethodArgument('exit', 'exit', 0, null, $call_location); $echo_param_sink->taints = [\Psalm\Type\TaintKind::INPUT_HTML, \Psalm\Type\TaintKind::USER_SECRET, \Psalm\Type\TaintKind::SYSTEM_SECRET]; $statements_analyzer->data_flow_graph->addSink($echo_param_sink); } if ($expr_type = $statements_analyzer->node_data->getType($stmt->expr)) { $exit_param = new \Psalm\Storage\FunctionLikeParameter('var', \false); if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentAnalyzer::verifyType($statements_analyzer, $expr_type, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TString()]), null, 'exit', 0, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr), $stmt->expr, $context, $exit_param, \false, null, \true, \true, new \Psalm\CodeLocation($statements_analyzer, $stmt)) === \false) { return \false; } } $context->inside_call = \false; } return \true; } } $existing_class_constants */ public static function infer(\Psalm\Codebase $codebase, \Psalm\Internal\Provider\NodeDataProvider $nodes, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, \Psalm\Aliases $aliases, \Psalm\FileSource $file_source = null, ?array $existing_class_constants = null, ?string $fq_classlike_name = null) : ?\Psalm\Type\Union { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { $left = self::infer($codebase, $nodes, $stmt->left, $aliases, $file_source, $existing_class_constants, $fq_classlike_name); $right = self::infer($codebase, $nodes, $stmt->right, $aliases, $file_source, $existing_class_constants, $fq_classlike_name); if ($left && $right) { if ($left->isSingleStringLiteral() && $right->isSingleStringLiteral()) { $result = $left->getSingleStringLiteral()->value . $right->getSingleStringLiteral()->value; return \Psalm\Type::getString($result); } if ($left->isString()) { $left_string_types = $left->getAtomicTypes(); $left_string_type = \reset($left_string_types); if ($left_string_type instanceof \Psalm\Type\Atomic\TNonEmptyString) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyString()]); } } if ($right->isString()) { $right_string_types = $right->getAtomicTypes(); $right_string_type = \reset($right_string_types); if ($right_string_type instanceof \Psalm\Type\Atomic\TNonEmptyString) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyString()]); } } } return \Psalm\Type::getString(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual) { return \Psalm\Type::getBool(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce) { return null; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Spaceship) { return \Psalm\Type::getInt(); } $stmt_left_type = self::infer($codebase, $nodes, $stmt->left, $aliases, $file_source, $existing_class_constants, $fq_classlike_name); $stmt_right_type = self::infer($codebase, $nodes, $stmt->right, $aliases, $file_source, $existing_class_constants, $fq_classlike_name); if (!$stmt_left_type || !$stmt_right_type) { return null; } $nodes->setType($stmt->left, $stmt_left_type); $nodes->setType($stmt->right, $stmt_right_type); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Pow) { \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\NonDivArithmeticOpAnalyzer::analyze($file_source instanceof \Psalm\StatementsSource ? $file_source : null, $nodes, $stmt->left, $stmt->right, $stmt, $result_type); if ($result_type) { return $result_type; } return null; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div && ($stmt_left_type->hasInt() || $stmt_left_type->hasFloat()) && ($stmt_right_type->hasInt() || $stmt_right_type->hasFloat())) { return \Psalm\Type::combineUnionTypes(\Psalm\Type::getFloat(), \Psalm\Type::getInt()); } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { if (\strtolower($stmt->name->parts[0]) === 'false') { return \Psalm\Type::getFalse(); } elseif (\strtolower($stmt->name->parts[0]) === 'true') { return \Psalm\Type::getTrue(); } elseif (\strtolower($stmt->name->parts[0]) === 'null') { return \Psalm\Type::getNull(); } elseif ($stmt->name->parts[0] === '__NAMESPACE__') { return \Psalm\Type::getString($aliases->namespace); } return null; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Dir || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\File) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyString()]); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Line) { return \Psalm\Type::getInt(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Class_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Method || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Trait_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Function_) { return \Psalm\Type::getString(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Namespace_) { return \Psalm\Type::getString($aliases->namespace); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch) { if ($stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $fq_classlike_name && $stmt->class->parts !== ['static'] && $stmt->class->parts !== ['parent']) { if (isset($existing_class_constants[$stmt->name->name]) && $existing_class_constants[$stmt->name->name]->type) { if ($stmt->class->parts === ['self']) { return clone $existing_class_constants[$stmt->name->name]->type; } } if ($stmt->class->parts === ['self']) { $const_fq_class_name = $fq_classlike_name; } else { $const_fq_class_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($stmt->class, $aliases); } if (\strtolower($const_fq_class_name) === \strtolower($fq_classlike_name) && isset($existing_class_constants[$stmt->name->name]) && $existing_class_constants[$stmt->name->name]->type) { return clone $existing_class_constants[$stmt->name->name]->type; } if (\strtolower($stmt->name->name) === 'class') { return \Psalm\Type::getLiteralClassString($const_fq_class_name); } if ($existing_class_constants === null && $file_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { try { $foreign_class_constant = $codebase->classlikes->getClassConstantType($const_fq_class_name, $stmt->name->name, \ReflectionProperty::IS_PRIVATE, $file_source); if ($foreign_class_constant) { return clone $foreign_class_constant; } return null; } catch (\InvalidArgumentException $e) { return null; } catch (\Psalm\Exception\CircularReferenceException $e) { return null; } } } if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($stmt->name->name) === 'class') { return \Psalm\Type::getClassString(); } return null; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { return \Psalm\Type::getString($stmt->value); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { return \Psalm\Type::getInt(\false, $stmt->value); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber) { return \Psalm\Type::getFloat($stmt->value); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_) { if (\count($stmt->items) === 0) { return \Psalm\Type::getEmptyArray(); } $item_key_type = null; $item_value_type = null; $property_types = []; $class_strings = []; $can_create_objectlike = \true; $is_list = \true; foreach ($stmt->items as $int_offset => $item) { if ($item === null) { continue; } $single_item_key_type = null; if ($item->key) { $single_item_key_type = self::infer($codebase, $nodes, $item->key, $aliases, $file_source, $existing_class_constants, $fq_classlike_name); if ($single_item_key_type) { if ($item_key_type) { $item_key_type = \Psalm\Type::combineUnionTypes($single_item_key_type, $item_key_type, null, \false, \true, 30); } else { $item_key_type = $single_item_key_type; } } } else { $item_key_type = \Psalm\Type::getInt(); } $single_item_value_type = self::infer($codebase, $nodes, $item->value, $aliases, $file_source, $existing_class_constants, $fq_classlike_name); if (!$single_item_value_type) { return null; } if ($item->key instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $item->key instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || !$item->key) { if (\count($property_types) <= 50) { $property_types[$item->key ? $item->key->value : $int_offset] = $single_item_value_type; } else { $can_create_objectlike = \false; } if ($item->key && (!$item->key instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || $item->key->value !== $int_offset)) { $is_list = \false; } } else { $is_list = \false; $dim_type = $single_item_key_type; if (!$dim_type) { return null; } $dim_atomic_types = $dim_type->getAtomicTypes(); if (\count($dim_atomic_types) > 1 || $dim_type->hasMixed() || \count($property_types) > 50) { $can_create_objectlike = \false; } else { $atomic_type = \array_shift($dim_atomic_types); if ($atomic_type instanceof \Psalm\Type\Atomic\TLiteralInt || $atomic_type instanceof \Psalm\Type\Atomic\TLiteralString) { if ($atomic_type instanceof \Psalm\Type\Atomic\TLiteralClassString) { $class_strings[$atomic_type->value] = \true; } $property_types[$atomic_type->value] = $single_item_value_type; } else { $can_create_objectlike = \false; } } } if ($item_value_type) { $item_value_type = \Psalm\Type::combineUnionTypes($single_item_value_type, $item_value_type, null, \false, \true, 30); } else { $item_value_type = $single_item_value_type; } } // if this array looks like an object-like array, let's return that instead if ($item_value_type && $item_key_type && ($item_key_type->hasString() || $item_key_type->hasInt()) && $can_create_objectlike && $property_types) { $objectlike = new \Psalm\Type\Atomic\TKeyedArray($property_types, $class_strings); $objectlike->sealed = \true; $objectlike->is_list = $is_list; return new \Psalm\Type\Union([$objectlike]); } if (!$item_key_type || !$item_value_type) { return null; } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyArray([$item_key_type, $item_value_type])]); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Int_) { return \Psalm\Type::getInt(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double) { return \Psalm\Type::getFloat(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Bool_) { return \Psalm\Type::getBool(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\String_) { return \Psalm\Type::getString(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Object_) { return \Psalm\Type::getObject(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Array_) { return \Psalm\Type::getArray(); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus) { $type_to_invert = self::infer($codebase, $nodes, $stmt->expr, $aliases, $file_source, $existing_class_constants, $fq_classlike_name); if (!$type_to_invert) { return null; } foreach ($type_to_invert->getAtomicTypes() as $type_part) { if ($type_part instanceof \Psalm\Type\Atomic\TLiteralInt && $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus) { $type_part->value = -$type_part->value; } elseif ($type_part instanceof \Psalm\Type\Atomic\TLiteralFloat && $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus) { $type_part->value = -$type_part->value; } } return $type_to_invert; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { if ($stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $stmt->dim) { $array_type = self::infer($codebase, $nodes, $stmt->var, $aliases, $file_source, $existing_class_constants, $fq_classlike_name); $dim_type = self::infer($codebase, $nodes, $stmt->dim, $aliases, $file_source, $existing_class_constants, $fq_classlike_name); if ($array_type !== null && $dim_type !== null) { if ($dim_type->isSingleStringLiteral()) { $dim_value = $dim_type->getSingleStringLiteral()->value; } elseif ($dim_type->isSingleIntLiteral()) { $dim_value = $dim_type->getSingleIntLiteral()->value; } else { return null; } foreach ($array_type->getAtomicTypes() as $array_atomic_type) { if ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if (isset($array_atomic_type->properties[$dim_value])) { return clone $array_atomic_type->properties[$dim_value]; } return null; } } } } } return null; } } expr, $context) === \false) { return \false; } if (!($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr))) { $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TFloat()])); } elseif ($stmt_expr_type->isMixed()) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } else { $acceptable_types = []; foreach ($stmt_expr_type->getAtomicTypes() as $type_part) { if ($type_part instanceof \Psalm\Type\Atomic\TInt || $type_part instanceof \Psalm\Type\Atomic\TFloat) { if ($type_part instanceof \Psalm\Type\Atomic\TLiteralInt && $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus) { $type_part->value = -$type_part->value; } elseif ($type_part instanceof \Psalm\Type\Atomic\TLiteralFloat && $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus) { $type_part->value = -$type_part->value; } $acceptable_types[] = $type_part; } elseif ($type_part instanceof \Psalm\Type\Atomic\TString) { $acceptable_types[] = new \Psalm\Type\Atomic\TInt(); $acceptable_types[] = new \Psalm\Type\Atomic\TFloat(); } else { $acceptable_types[] = new \Psalm\Type\Atomic\TInt(); } } $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union($acceptable_types)); } return \true; } } vars as $isset_var) { if ($isset_var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && $isset_var->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $isset_var->var->name === 'this' && $isset_var->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $var_id = '$this->' . $isset_var->name->name; if (!isset($context->vars_in_scope[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::getMixed(); $context->vars_possibly_in_scope[$var_id] = \true; } } self::analyzeIssetVar($statements_analyzer, $isset_var, $context); } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getBool()); } public static function analyzeIssetVar(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, \Psalm\Context $context) : bool { $context->inside_isset = \true; $result = \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt, $context); $context->inside_isset = \false; return $result; } } getDocComment(); $var_comments = []; $var_comment_type = null; $codebase = $statements_analyzer->getCodebase(); if ($doc_comment) { try { $var_comments = \Psalm\Internal\Analyzer\CommentAnalyzer::getTypeFromComment($doc_comment, $statements_analyzer, $statements_analyzer->getAliases()); } catch (\Psalm\Exception\DocblockParseException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)))) { // fall through } } foreach ($var_comments as $var_comment) { if (!$var_comment->type) { continue; } $comment_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $var_comment->type, $context->self, $context->self ? new \Psalm\Type\Atomic\TNamedObject($context->self) : null, $statements_analyzer->getParentFQCLN()); $type_location = null; if ($var_comment->type_start && $var_comment->type_end && $var_comment->line_number) { $type_location = new \Psalm\CodeLocation\DocblockTypeLocation($statements_analyzer, $var_comment->type_start, $var_comment->type_end, $var_comment->line_number); } if (!$var_comment->var_id) { $var_comment_type = $comment_type; continue; } if ($codebase->find_unused_variables && $type_location && isset($context->vars_in_scope[$var_comment->var_id]) && $context->vars_in_scope[$var_comment->var_id]->getId() === $comment_type->getId()) { $project_analyzer = $statements_analyzer->getProjectAnalyzer(); if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['UnnecessaryVarAnnotation'])) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::addVarAnnotationToRemove($type_location); } elseif (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnnecessaryVarAnnotation('The @var annotation for ' . $var_comment->var_id . ' is unnecessary', $type_location), [], \true)) { // fall through } } if (isset($context->vars_in_scope[$var_comment->var_id])) { $comment_type->parent_nodes = $context->vars_in_scope[$var_comment->var_id]->parent_nodes; } $context->vars_in_scope[$var_comment->var_id] = $comment_type; } } if ($stmt->key) { $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->key, $context) === \false) { return \false; } $context->inside_call = \false; } if ($stmt->value) { $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->value, $context) === \false) { return \false; } $context->inside_call = \false; if ($var_comment_type) { $expression_type = clone $var_comment_type; } elseif ($stmt_var_type = $statements_analyzer->node_data->getType($stmt->value)) { $expression_type = clone $stmt_var_type; } else { $expression_type = \Psalm\Type::getMixed(); } } else { $expression_type = \Psalm\Type::getEmpty(); } $yield_type = null; foreach ($expression_type->getAtomicTypes() as $expression_atomic_type) { if ($expression_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $classlike_storage = $codebase->classlike_storage_provider->get($expression_atomic_type->value); if ($classlike_storage->yield) { if ($expression_atomic_type instanceof \Psalm\Type\Atomic\TGenericObject) { $yield_candidate_type = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\AtomicPropertyFetchAnalyzer::localizePropertyType($codebase, clone $classlike_storage->yield, $expression_atomic_type, $classlike_storage, $classlike_storage); if ($yield_type) { $yield_type = \Psalm\Type::combineUnionTypes($yield_type, $yield_candidate_type, $codebase); } else { $yield_type = $yield_candidate_type; } } else { $yield_type = \Psalm\Type::getMixed(); } } } } if ($yield_type) { $expression_type->substitute($expression_type, $yield_type); } $statements_analyzer->node_data->setType($stmt, $expression_type); $source = $statements_analyzer->getSource(); if ($source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && !$source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) { $source->examineParamTypes($statements_analyzer, $context, $codebase, $stmt); $storage = $source->getFunctionLikeStorage($statements_analyzer); if ($storage->return_type && !$yield_type) { foreach ($storage->return_type->getAtomicTypes() as $atomic_return_type) { if ($atomic_return_type instanceof \Psalm\Type\Atomic\TNamedObject && $atomic_return_type->value === 'Generator') { if ($atomic_return_type instanceof \Psalm\Type\Atomic\TGenericObject) { if (!$atomic_return_type->type_params[2]->isVoid()) { $statements_analyzer->node_data->setType($stmt, clone $atomic_return_type->type_params[2]); } } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::combineUnionTypes(\Psalm\Type::getMixed(), $expression_type)); } } } } } return \true; } } getCodebase(); if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph) { $call_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $print_param_sink = \Psalm\Internal\DataFlow\TaintSink::getForMethodArgument('print', 'print', 0, null, $call_location); $print_param_sink->taints = [\Psalm\Type\TaintKind::INPUT_HTML, \Psalm\Type\TaintKind::USER_SECRET, \Psalm\Type\TaintKind::SYSTEM_SECRET]; $statements_analyzer->data_flow_graph->addSink($print_param_sink); } if ($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr)) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentAnalyzer::verifyType($statements_analyzer, $stmt_expr_type, \Psalm\Type::getString(), null, 'print', 0, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr), $stmt->expr, $context, new \Psalm\Storage\FunctionLikeParameter('var', \false), \false, null, \true, \true, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)) === \false) { return \false; } } if (isset($codebase->config->forbidden_functions['print'])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ForbiddenCode('You have forbidden the use of print', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // continue } } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getInt(\false, 1)); return \true; } } getCodebase(); $codebase_methods = $codebase->methods; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr); if ($stmt_expr_type) { $clone_type = $stmt_expr_type; $immutable_cloned = \false; $invalid_clones = []; $mixed_clone = \false; $possibly_valid = \false; $atomic_types = $clone_type->getAtomicTypes(); while ($atomic_types) { $clone_type_part = \array_pop($atomic_types); if ($clone_type_part instanceof \Psalm\Type\Atomic\TMixed) { $mixed_clone = \true; } elseif ($clone_type_part instanceof \Psalm\Type\Atomic\TObject) { $possibly_valid = \true; } elseif ($clone_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { if (!$codebase->classlikes->classOrInterfaceExists($clone_type_part->value)) { $invalid_clones[] = $clone_type_part->getId(); } else { $clone_method_id = new \Psalm\Internal\MethodIdentifier($clone_type_part->value, '__clone'); $does_method_exist = $codebase_methods->methodExists($clone_method_id, $context->calling_method_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)); $is_method_visible = \Psalm\Internal\Analyzer\MethodAnalyzer::isMethodVisible($clone_method_id, $context, $statements_analyzer->getSource()); if ($does_method_exist && !$is_method_visible) { $invalid_clones[] = $clone_type_part->getId(); } else { $possibly_valid = \true; $immutable_cloned = \true; } } } elseif ($clone_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $atomic_types = \array_merge($atomic_types, $clone_type_part->as->getAtomicTypes()); } else { if ($clone_type_part instanceof \Psalm\Type\Atomic\TFalse && $clone_type->ignore_falsable_issues) { continue; } if ($clone_type_part instanceof \Psalm\Type\Atomic\TNull && $clone_type->ignore_nullable_issues) { continue; } $invalid_clones[] = $clone_type_part->getId(); } } if ($mixed_clone) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedClone('Cannot clone mixed', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($invalid_clones) { if ($possibly_valid) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidClone('Cannot clone ' . $invalid_clones[0], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidClone('Cannot clone ' . $invalid_clones[0], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } return \true; } $statements_analyzer->node_data->setType($stmt, $stmt_expr_type); if ($immutable_cloned) { $stmt_expr_type = clone $stmt_expr_type; $statements_analyzer->node_data->setType($stmt, $stmt_expr_type); $stmt_expr_type->reference_free = \true; $stmt_expr_type->allow_mutations = \true; } } return \true; } } getCodebase(); $if_scope = new \Psalm\Internal\Scope\IfScope(); try { $if_conditional_scope = \Psalm\Internal\Analyzer\Statements\Block\IfAnalyzer::analyzeIfConditional($statements_analyzer, $stmt->cond, $context, $codebase, $if_scope, $context->branch_point ?: (int) $stmt->getAttribute('startFilePos')); $if_context = $if_conditional_scope->if_context; $cond_referenced_var_ids = $if_conditional_scope->cond_referenced_var_ids; $cond_assigned_var_ids = $if_conditional_scope->cond_assigned_var_ids; } catch (\Psalm\Exception\ScopeAnalysisException $e) { return \false; } $codebase = $statements_analyzer->getCodebase(); $cond_id = \spl_object_id($stmt->cond); $if_clauses = \Psalm\Type\Algebra::getFormula($cond_id, $cond_id, $stmt->cond, $context->self, $statements_analyzer, $codebase); $mixed_var_ids = []; foreach ($context->vars_in_scope as $var_id => $type) { if ($type->hasMixed()) { $mixed_var_ids[] = $var_id; } } foreach ($context->vars_possibly_in_scope as $var_id => $_) { if (!isset($context->vars_in_scope[$var_id])) { $mixed_var_ids[] = $var_id; } } $if_clauses = \array_values(\array_map( /** * @return \Psalm\Internal\Clause */ function (\Psalm\Internal\Clause $c) use($mixed_var_ids, $cond_id) : \Psalm\Internal\Clause { $keys = \array_keys($c->possibilities); $mixed_var_ids = \array_diff($mixed_var_ids, $keys); foreach ($keys as $key) { foreach ($mixed_var_ids as $mixed_var_id) { if (\preg_match('/^' . \preg_quote($mixed_var_id, '/') . '(\\[|-)/', $key)) { return new \Psalm\Internal\Clause([], $cond_id, $cond_id, \true); } } } return $c; }, $if_clauses )); // this will see whether any of the clauses in set A conflict with the clauses in set B \Psalm\Internal\Analyzer\AlgebraAnalyzer::checkForParadox($context->clauses, $if_clauses, $statements_analyzer, $stmt->cond, $cond_assigned_var_ids); $ternary_clauses = \array_merge($context->clauses, $if_clauses); if ($if_context->reconciled_expression_clauses) { $reconciled_expression_clauses = $if_context->reconciled_expression_clauses; $ternary_clauses = \array_values(\array_filter($ternary_clauses, function ($c) use($reconciled_expression_clauses) : bool { return !\in_array($c->hash, $reconciled_expression_clauses); })); } $ternary_clauses = \Psalm\Type\Algebra::simplifyCNF($ternary_clauses); $negated_clauses = \Psalm\Type\Algebra::negateFormula($if_clauses); $negated_if_types = \Psalm\Type\Algebra::getTruthsFromFormula(\Psalm\Type\Algebra::simplifyCNF(\array_merge($context->clauses, $negated_clauses))); $active_if_types = []; $reconcilable_if_types = \Psalm\Type\Algebra::getTruthsFromFormula($ternary_clauses, $cond_id, $cond_referenced_var_ids, $active_if_types); $changed_var_ids = []; if ($reconcilable_if_types) { $if_vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($reconcilable_if_types, $active_if_types, $if_context->vars_in_scope, $changed_var_ids, $cond_referenced_var_ids, $statements_analyzer, $statements_analyzer->getTemplateTypeMap() ?: [], $if_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->cond)); $if_context->vars_in_scope = $if_vars_in_scope_reconciled; } $t_else_context = clone $context; if ($stmt->if) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->if, $if_context) === \false) { return \false; } foreach ($if_context->vars_in_scope as $var_id => $type) { if (isset($context->vars_in_scope[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->vars_in_scope[$var_id], $type); } } $context->referenced_var_ids = \array_merge($context->referenced_var_ids, $if_context->referenced_var_ids); } $t_else_context->clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($t_else_context->clauses, $negated_clauses)); if ($negated_if_types) { $changed_var_ids = []; $t_else_vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($negated_if_types, $negated_if_types, $t_else_context->vars_in_scope, $changed_var_ids, $cond_referenced_var_ids, $statements_analyzer, $statements_analyzer->getTemplateTypeMap() ?: [], $t_else_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->else)); $t_else_context->vars_in_scope = $t_else_vars_in_scope_reconciled; $t_else_context->clauses = \Psalm\Context::removeReconciledClauses($t_else_context->clauses, $changed_var_ids)[0]; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->else, $t_else_context) === \false) { return \false; } foreach ($t_else_context->vars_in_scope as $var_id => $type) { if (isset($context->vars_in_scope[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->vars_in_scope[$var_id], $type); } elseif (isset($if_context->vars_in_scope[$var_id]) && isset($if_context->assigned_var_ids[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($if_context->vars_in_scope[$var_id], $type); } } $context->vars_possibly_in_scope = \array_merge($context->vars_possibly_in_scope, $if_context->vars_possibly_in_scope, $t_else_context->vars_possibly_in_scope); $context->referenced_var_ids = \array_merge($context->referenced_var_ids, $t_else_context->referenced_var_ids); $lhs_type = null; if ($stmt->if) { if ($stmt_if_type = $statements_analyzer->node_data->getType($stmt->if)) { $lhs_type = $stmt_if_type; } } elseif ($stmt_cond_type = $statements_analyzer->node_data->getType($stmt->cond)) { $if_return_type_reconciled = \Psalm\Internal\Type\AssertionReconciler::reconcile('!falsy', clone $stmt_cond_type, '', $statements_analyzer, $context->inside_loop, [], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues()); $lhs_type = $if_return_type_reconciled; } if ($lhs_type && ($stmt_else_type = $statements_analyzer->node_data->getType($stmt->else))) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::combineUnionTypes($lhs_type, $stmt_else_type)); } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } return \true; } } getCodebase() : null; $left_type = $nodes->getType($left); $right_type = $nodes->getType($right); $config = \Psalm\Config::getInstance(); if ($left_type && $left_type->isEmpty()) { $left_type = $right_type; } elseif ($right_type && $right_type->isEmpty()) { $right_type = $left_type; } if ($left_type && $right_type) { if ($left_type->isNull()) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullOperand('Left operand cannot be null', new \Psalm\CodeLocation($statements_source, $left)), $statements_source->getSuppressedIssues())) { // fall through } return; } if ($left_type->isNullable() && !$left_type->ignore_nullable_issues) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullOperand('Left operand cannot be nullable, got ' . $left_type, new \Psalm\CodeLocation($statements_source, $left)), $statements_source->getSuppressedIssues())) { // fall through } } if ($right_type->isNull()) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullOperand('Right operand cannot be null', new \Psalm\CodeLocation($statements_source, $right)), $statements_source->getSuppressedIssues())) { // fall through } return; } if ($right_type->isNullable() && !$right_type->ignore_nullable_issues) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullOperand('Right operand cannot be nullable, got ' . $right_type, new \Psalm\CodeLocation($statements_source, $right)), $statements_source->getSuppressedIssues())) { // fall through } } if ($left_type->isFalse()) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\FalseOperand('Left operand cannot be false', new \Psalm\CodeLocation($statements_source, $left)), $statements_source->getSuppressedIssues())) { // fall through } return; } if ($left_type->isFalsable() && !$left_type->ignore_falsable_issues) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyFalseOperand('Left operand cannot be falsable, got ' . $left_type, new \Psalm\CodeLocation($statements_source, $left)), $statements_source->getSuppressedIssues())) { // fall through } } if ($right_type->isFalse()) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\FalseOperand('Right operand cannot be false', new \Psalm\CodeLocation($statements_source, $right)), $statements_source->getSuppressedIssues())) { // fall through } return; } if ($right_type->isFalsable() && !$right_type->ignore_falsable_issues) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyFalseOperand('Right operand cannot be falsable, got ' . $right_type, new \Psalm\CodeLocation($statements_source, $right)), $statements_source->getSuppressedIssues())) { // fall through } } $invalid_left_messages = []; $invalid_right_messages = []; $has_valid_left_operand = \false; $has_valid_right_operand = \false; $has_string_increment = \false; foreach ($left_type->getAtomicTypes() as $left_type_part) { foreach ($right_type->getAtomicTypes() as $right_type_part) { $candidate_result_type = self::analyzeNonDivOperands($statements_source, $codebase, $config, $context, $left, $right, $parent, $left_type_part, $right_type_part, $invalid_left_messages, $invalid_right_messages, $has_valid_left_operand, $has_valid_right_operand, $has_string_increment, $result_type); if ($candidate_result_type) { $result_type = $candidate_result_type; return; } } } if ($invalid_left_messages && $statements_source) { $first_left_message = $invalid_left_messages[0]; if ($has_valid_left_operand) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidOperand($first_left_message, new \Psalm\CodeLocation($statements_source, $left)), $statements_source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidOperand($first_left_message, new \Psalm\CodeLocation($statements_source, $left)), $statements_source->getSuppressedIssues())) { // fall through } } } if ($invalid_right_messages && $statements_source) { $first_right_message = $invalid_right_messages[0]; if ($has_valid_right_operand) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidOperand($first_right_message, new \Psalm\CodeLocation($statements_source, $right)), $statements_source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidOperand($first_right_message, new \Psalm\CodeLocation($statements_source, $right)), $statements_source->getSuppressedIssues())) { // fall through } } } if ($has_string_increment && $statements_source) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\StringIncrement('Possibly unintended string increment', new \Psalm\CodeLocation($statements_source, $left)), $statements_source->getSuppressedIssues())) { // fall through } } } } /** * @param string[] &$invalid_left_messages * @param string[] &$invalid_right_messages */ private static function analyzeNonDivOperands(?\Psalm\StatementsSource $statements_source, ?\Psalm\Codebase $codebase, \Psalm\Config $config, ?\Psalm\Context $context, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $left, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $right, \_HumbugBoxd02f763d3c56\PhpParser\Node $parent, \Psalm\Type\Atomic $left_type_part, \Psalm\Type\Atomic $right_type_part, array &$invalid_left_messages, array &$invalid_right_messages, bool &$has_valid_left_operand, bool &$has_valid_right_operand, bool &$has_string_increment, \Psalm\Type\Union &$result_type = null) : ?\Psalm\Type\Union { if ($left_type_part instanceof \Psalm\Type\Atomic\TLiteralInt && $right_type_part instanceof \Psalm\Type\Atomic\TLiteralInt && ($left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar || $left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) && ($right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar || $right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch)) { // time for some arithmetic! $calculated_type = null; if ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus) { $calculated_type = \Psalm\Type::getInt(\false, $left_type_part->value + $right_type_part->value); } elseif ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus) { $calculated_type = \Psalm\Type::getInt(\false, $left_type_part->value - $right_type_part->value); } elseif ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod) { $calculated_type = \Psalm\Type::getInt(\false, $left_type_part->value % $right_type_part->value); } elseif ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul) { $calculated_type = \Psalm\Type::getInt(\false, $left_type_part->value * $right_type_part->value); } elseif ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Pow) { $calculated_type = \Psalm\Type::getInt(\false, $left_type_part->value ^ $right_type_part->value); } elseif ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr) { $calculated_type = \Psalm\Type::getInt(\false, $left_type_part->value | $right_type_part->value); } elseif ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd) { $calculated_type = \Psalm\Type::getInt(\false, $left_type_part->value & $right_type_part->value); } if ($calculated_type) { if ($result_type) { $result_type = \Psalm\Type::combineUnionTypes($calculated_type, $result_type); } else { $result_type = $calculated_type; } $has_valid_left_operand = \true; $has_valid_right_operand = \true; return null; } } if ($left_type_part instanceof \Psalm\Type\Atomic\TNull || $right_type_part instanceof \Psalm\Type\Atomic\TNull) { // null case is handled above return null; } if ($left_type_part instanceof \Psalm\Type\Atomic\TFalse || $right_type_part instanceof \Psalm\Type\Atomic\TFalse) { // null case is handled above return null; } if ($left_type_part instanceof \Psalm\Type\Atomic\TString && $right_type_part instanceof \Psalm\Type\Atomic\TInt && $parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc) { $has_string_increment = \true; if (!$result_type) { $result_type = \Psalm\Type::getString(); } else { $result_type = \Psalm\Type::combineUnionTypes(\Psalm\Type::getString(), $result_type); } $has_valid_left_operand = \true; $has_valid_right_operand = \true; return null; } if ($left_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $right_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $combined_type = \Psalm\Type::combineUnionTypes($left_type_part->as, $right_type_part->as); $combined_atomic_types = \array_values($combined_type->getAtomicTypes()); if (\count($combined_atomic_types) <= 2) { $left_type_part = $combined_atomic_types[0]; $right_type_part = $combined_atomic_types[1] ?? $combined_atomic_types[0]; } } if ($left_type_part instanceof \Psalm\Type\Atomic\TMixed || $right_type_part instanceof \Psalm\Type\Atomic\TMixed || $left_type_part instanceof \Psalm\Type\Atomic\TTemplateParam || $right_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($statements_source && $codebase && $context) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_source->getFilePath() === $statements_source->getRootFilePath() && (!($source = $statements_source->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_source->getFilePath()); } } if ($left_type_part instanceof \Psalm\Type\Atomic\TMixed || $left_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedOperand('Left operand cannot be mixed', new \Psalm\CodeLocation($statements_source, $left)), $statements_source->getSuppressedIssues())) { // fall through } } else { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedOperand('Right operand cannot be mixed', new \Psalm\CodeLocation($statements_source, $right)), $statements_source->getSuppressedIssues())) { // fall through } } if ($left_type_part instanceof \Psalm\Type\Atomic\TMixed && $left_type_part->from_loop_isset && $parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Plus && !$right_type_part instanceof \Psalm\Type\Atomic\TMixed) { $result_type_member = new \Psalm\Type\Union([$right_type_part]); if (!$result_type) { $result_type = $result_type_member; } else { $result_type = \Psalm\Type::combineUnionTypes($result_type_member, $result_type); } return null; } $from_loop_isset = (!$left_type_part instanceof \Psalm\Type\Atomic\TMixed || $left_type_part->from_loop_isset) && (!$right_type_part instanceof \Psalm\Type\Atomic\TMixed || $right_type_part->from_loop_isset); $result_type = \Psalm\Type::getMixed($from_loop_isset); return $result_type; } if ($statements_source && $codebase && $context) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_source->getFilePath() === $statements_source->getRootFilePath() && (!($parent_source = $statements_source->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_source->getFilePath()); } } if ($left_type_part instanceof \Psalm\Type\Atomic\TArray || $right_type_part instanceof \Psalm\Type\Atomic\TArray || $left_type_part instanceof \Psalm\Type\Atomic\TKeyedArray || $right_type_part instanceof \Psalm\Type\Atomic\TKeyedArray || $left_type_part instanceof \Psalm\Type\Atomic\TList || $right_type_part instanceof \Psalm\Type\Atomic\TList) { if (!$right_type_part instanceof \Psalm\Type\Atomic\TArray && !$right_type_part instanceof \Psalm\Type\Atomic\TKeyedArray && !$right_type_part instanceof \Psalm\Type\Atomic\TList || !$left_type_part instanceof \Psalm\Type\Atomic\TArray && !$left_type_part instanceof \Psalm\Type\Atomic\TKeyedArray && !$left_type_part instanceof \Psalm\Type\Atomic\TList) { if (!$left_type_part instanceof \Psalm\Type\Atomic\TArray && !$left_type_part instanceof \Psalm\Type\Atomic\TKeyedArray && !$left_type_part instanceof \Psalm\Type\Atomic\TList) { $invalid_left_messages[] = 'Cannot add an array to a non-array ' . $left_type_part; } else { $invalid_right_messages[] = 'Cannot add an array to a non-array ' . $right_type_part; } if ($left_type_part instanceof \Psalm\Type\Atomic\TArray || $left_type_part instanceof \Psalm\Type\Atomic\TKeyedArray || $left_type_part instanceof \Psalm\Type\Atomic\TList) { $has_valid_left_operand = \true; } elseif ($right_type_part instanceof \Psalm\Type\Atomic\TArray || $right_type_part instanceof \Psalm\Type\Atomic\TKeyedArray || $right_type_part instanceof \Psalm\Type\Atomic\TList) { $has_valid_right_operand = \true; } $result_type = \Psalm\Type::getArray(); return null; } $has_valid_right_operand = \true; $has_valid_left_operand = \true; if ($left_type_part instanceof \Psalm\Type\Atomic\TKeyedArray && $right_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $definitely_existing_mixed_right_properties = \array_diff_key($right_type_part->properties, $left_type_part->properties); $properties = $left_type_part->properties; foreach ($right_type_part->properties as $key => $type) { if (!isset($properties[$key])) { $properties[$key] = $type; } elseif ($properties[$key]->possibly_undefined) { $properties[$key] = \Psalm\Type::combineUnionTypes($properties[$key], $type, $codebase); $properties[$key]->possibly_undefined = $type->possibly_undefined; } } if (!$left_type_part->sealed) { foreach ($definitely_existing_mixed_right_properties as $key => $type) { $properties[$key] = \Psalm\Type::combineUnionTypes(\Psalm\Type::getMixed(), $type); } } $result_type_member = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TKeyedArray($properties)]); } else { $result_type_member = \Psalm\Internal\Type\TypeCombination::combineTypes([$left_type_part, $right_type_part], $codebase, \true); } if (!$result_type) { $result_type = $result_type_member; } else { $result_type = \Psalm\Type::combineUnionTypes($result_type_member, $result_type, $codebase, \true); } if ($left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch && $context && $statements_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { \Psalm\Internal\Analyzer\Statements\Expression\Assignment\ArrayAssignmentAnalyzer::updateArrayType($statements_source, $left, $right, $result_type, $context); } return null; } if ($left_type_part instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($left_type_part->value) === 'gmp' || $right_type_part instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($right_type_part->value) === 'gmp') { if ($left_type_part instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($left_type_part->value) === 'gmp' && ($right_type_part instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($right_type_part->value) === 'gmp' || ($right_type_part->isNumericType() || $right_type_part instanceof \Psalm\Type\Atomic\TMixed)) || $right_type_part instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($right_type_part->value) === 'gmp' && ($left_type_part instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($left_type_part->value) === 'gmp' || ($left_type_part->isNumericType() || $left_type_part instanceof \Psalm\Type\Atomic\TMixed))) { if (!$result_type) { $result_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject('GMP')]); } else { $result_type = \Psalm\Type::combineUnionTypes(new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject('GMP')]), $result_type); } } else { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidOperand('Cannot add GMP to non-numeric type', new \Psalm\CodeLocation($statements_source, $parent)), $statements_source->getSuppressedIssues())) { // fall through } } return null; } if ($left_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { if (\preg_match('/^\\-?\\d+$/', $left_type_part->value)) { $left_type_part = new \Psalm\Type\Atomic\TLiteralInt((int) $left_type_part->value); } elseif (\preg_match('/^\\-?\\d?\\.\\d+$/', $left_type_part->value)) { $left_type_part = new \Psalm\Type\Atomic\TLiteralFloat((float) $left_type_part->value); } } if ($right_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { if (\preg_match('/^\\-?\\d+$/', $right_type_part->value)) { $right_type_part = new \Psalm\Type\Atomic\TLiteralInt((int) $right_type_part->value); } elseif (\preg_match('/^\\-?\\d?\\.\\d+$/', $right_type_part->value)) { $right_type_part = new \Psalm\Type\Atomic\TLiteralFloat((float) $right_type_part->value); } } if ($left_type_part->isNumericType() || $right_type_part->isNumericType()) { if (($left_type_part instanceof \Psalm\Type\Atomic\TNumeric || $right_type_part instanceof \Psalm\Type\Atomic\TNumeric) && ($left_type_part->isNumericType() && $right_type_part->isNumericType())) { if ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod) { $result_type = \Psalm\Type::getInt(); } elseif (!$result_type) { $result_type = \Psalm\Type::getNumeric(); } else { $result_type = \Psalm\Type::combineUnionTypes(\Psalm\Type::getNumeric(), $result_type); } $has_valid_right_operand = \true; $has_valid_left_operand = \true; return null; } if ($left_type_part instanceof \Psalm\Type\Atomic\TInt && $right_type_part instanceof \Psalm\Type\Atomic\TInt) { $left_is_positive = $left_type_part instanceof \Psalm\Type\Atomic\TPositiveInt || $left_type_part instanceof \Psalm\Type\Atomic\TLiteralInt && $left_type_part->value > 0; $right_is_positive = $right_type_part instanceof \Psalm\Type\Atomic\TPositiveInt || $right_type_part instanceof \Psalm\Type\Atomic\TLiteralInt && $right_type_part->value > 0; if ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus) { $always_positive = \false; } elseif ($left_is_positive && $right_is_positive) { $always_positive = \true; } elseif ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus && ($left_type_part instanceof \Psalm\Type\Atomic\TLiteralInt && $left_type_part->value === 0) && $right_is_positive) { $always_positive = \true; } elseif ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus && ($right_type_part instanceof \Psalm\Type\Atomic\TLiteralInt && $right_type_part->value === 0) && $left_is_positive) { $always_positive = \true; } else { $always_positive = \false; } if ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod) { $result_type = $always_positive ? new \Psalm\Type\Union([new \Psalm\Type\Atomic\TPositiveInt(), new \Psalm\Type\Atomic\TLiteralInt(0)]) : \Psalm\Type::getInt(); } elseif (!$result_type) { $result_type = $always_positive ? \Psalm\Type::getPositiveInt(\true) : \Psalm\Type::getInt(\true); } else { $result_type = \Psalm\Type::combineUnionTypes($always_positive ? \Psalm\Type::getPositiveInt(\true) : \Psalm\Type::getInt(\true), $result_type); } $has_valid_right_operand = \true; $has_valid_left_operand = \true; return null; } if ($left_type_part instanceof \Psalm\Type\Atomic\TFloat && $right_type_part instanceof \Psalm\Type\Atomic\TFloat) { if ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod) { $result_type = \Psalm\Type::getInt(); } elseif (!$result_type) { $result_type = \Psalm\Type::getFloat(); } else { $result_type = \Psalm\Type::combineUnionTypes(\Psalm\Type::getFloat(), $result_type); } $has_valid_right_operand = \true; $has_valid_left_operand = \true; return null; } if ($left_type_part instanceof \Psalm\Type\Atomic\TFloat && $right_type_part instanceof \Psalm\Type\Atomic\TInt || $left_type_part instanceof \Psalm\Type\Atomic\TInt && $right_type_part instanceof \Psalm\Type\Atomic\TFloat) { if ($config->strict_binary_operands) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidOperand('Cannot add ints to floats', new \Psalm\CodeLocation($statements_source, $parent)), $statements_source->getSuppressedIssues())) { // fall through } } if ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod) { $result_type = \Psalm\Type::getInt(); } elseif (!$result_type) { $result_type = \Psalm\Type::getFloat(); } else { $result_type = \Psalm\Type::combineUnionTypes(\Psalm\Type::getFloat(), $result_type); } $has_valid_right_operand = \true; $has_valid_left_operand = \true; return null; } if ($left_type_part->isNumericType() && $right_type_part->isNumericType()) { if ($config->strict_binary_operands) { if ($statements_source && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidOperand('Cannot add numeric types together, please cast explicitly', new \Psalm\CodeLocation($statements_source, $parent)), $statements_source->getSuppressedIssues())) { // fall through } } if ($parent instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod) { $result_type = \Psalm\Type::getInt(); } else { $result_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TFloat()]); } $has_valid_right_operand = \true; $has_valid_left_operand = \true; return null; } if (!$left_type_part->isNumericType()) { $invalid_left_messages[] = 'Cannot perform a numeric operation with a non-numeric type ' . $left_type_part; $has_valid_right_operand = \true; } else { $invalid_right_messages[] = 'Cannot perform a numeric operation with a non-numeric type ' . $right_type_part; $has_valid_left_operand = \true; } } else { $invalid_left_messages[] = 'Cannot perform a numeric operation with non-numeric types ' . $left_type_part . ' and ' . $right_type_part; } return null; } } getCodebase(); $stmt_id = \spl_object_id($stmt); $if_clauses = \Psalm\Type\Algebra::getFormula($stmt_id, $stmt_id, $stmt, $context->self, $statements_analyzer, $codebase); $mixed_var_ids = []; foreach ($context->vars_in_scope as $var_id => $type) { if ($type->hasMixed()) { $mixed_var_ids[] = $var_id; } } foreach ($context->vars_possibly_in_scope as $var_id => $_) { if (!isset($context->vars_in_scope[$var_id])) { $mixed_var_ids[] = $var_id; } } $if_clauses = \array_values(\array_map(function (\Psalm\Internal\Clause $c) use($mixed_var_ids, $stmt_id) : \Psalm\Internal\Clause { $keys = \array_keys($c->possibilities); $mixed_var_ids = \array_diff($mixed_var_ids, $keys); foreach ($keys as $key) { foreach ($mixed_var_ids as $mixed_var_id) { if (\preg_match('/^' . \preg_quote($mixed_var_id, '/') . '(\\[|-)/', $key)) { return new \Psalm\Internal\Clause([], $stmt_id, $stmt_id, \true); } } } return $c; }, $if_clauses)); $ternary_clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($context->clauses, $if_clauses)); $negated_clauses = \Psalm\Type\Algebra::negateFormula($if_clauses); $negated_if_types = \Psalm\Type\Algebra::getTruthsFromFormula($negated_clauses); $reconcilable_if_types = \Psalm\Type\Algebra::getTruthsFromFormula($ternary_clauses); $changed_var_ids = []; if ($reconcilable_if_types) { $t_if_vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($reconcilable_if_types, [], $t_if_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, [], $t_if_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->left)); foreach ($context->vars_in_scope as $var_id => $_) { if (isset($t_if_vars_in_scope_reconciled[$var_id])) { $t_if_context->vars_in_scope[$var_id] = $t_if_vars_in_scope_reconciled[$var_id]; } } } if (!self::hasArrayDimFetch($stmt->left)) { // check first if the variable was good \Psalm\IssueBuffer::startRecording(); \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->left, clone $context); \Psalm\IssueBuffer::clearRecordingLevel(); \Psalm\IssueBuffer::stopRecording(); $naive_type = $statements_analyzer->node_data->getType($stmt->left); if ($naive_type && !$naive_type->possibly_undefined && !$naive_type->hasMixed() && !$naive_type->isNullable()) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($stmt->left, $context->self); if (!$var_id || $var_id !== '$_SESSION' && $var_id !== '$_SERVER' && !isset($changed_var_ids[$var_id])) { if ($naive_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($naive_type->getId() . ' does not contain null', new \Psalm\CodeLocation($statements_analyzer, $stmt->left), $naive_type->getId() . ' null'), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType($naive_type->getId() . ' is always defined and non-null', new \Psalm\CodeLocation($statements_analyzer, $stmt->left), null), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } } $t_if_context->inside_isset = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->left, $t_if_context) === \false) { return \false; } $t_if_context->inside_isset = \false; foreach ($t_if_context->vars_in_scope as $var_id => $type) { if (isset($context->vars_in_scope[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->vars_in_scope[$var_id], $type, $codebase); } else { $context->vars_in_scope[$var_id] = $type; } } $context->referenced_var_ids = \array_merge($context->referenced_var_ids, $t_if_context->referenced_var_ids); $t_else_context = clone $context; if ($negated_if_types) { $t_else_vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($negated_if_types, [], $t_else_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, [], $t_else_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->right)); $t_else_context->vars_in_scope = $t_else_vars_in_scope_reconciled; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->right, $t_else_context) === \false) { return \false; } $context->referenced_var_ids = \array_merge($context->referenced_var_ids, $t_else_context->referenced_var_ids); $lhs_type = null; $stmt_left_type = $statements_analyzer->node_data->getType($stmt->left); if ($stmt_left_type) { $if_return_type_reconciled = \Psalm\Internal\Type\AssertionReconciler::reconcile('isset', clone $stmt_left_type, '', $statements_analyzer, $context->inside_loop, [], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues()); $lhs_type = clone $if_return_type_reconciled; } $stmt_right_type = null; if (!$lhs_type || !($stmt_right_type = $statements_analyzer->node_data->getType($stmt->right))) { $stmt_type = \Psalm\Type::getMixed(); $statements_analyzer->node_data->setType($stmt, $stmt_type); } else { $stmt_type = \Psalm\Type::combineUnionTypes($lhs_type, $stmt_right_type, $codebase); $statements_analyzer->node_data->setType($stmt, $stmt_type); } return \true; } private static function hasArrayDimFetch(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr) : bool { if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { return \true; } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch || $expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall) { return self::hasArrayDimFetch($expr->var); } return \false; } } left, ['stmts' => [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression($stmt->right)]], $stmt->getAttributes()); return \Psalm\Internal\Analyzer\Statements\Block\IfAnalyzer::analyze($statements_analyzer, $fake_if_stmt, $context) !== \false; } $pre_referenced_var_ids = $context->referenced_var_ids; $pre_assigned_var_ids = $context->assigned_var_ids; $left_context = clone $context; $left_context->referenced_var_ids = []; $left_context->assigned_var_ids = []; /** @var list */ $left_context->reconciled_expression_clauses = []; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->left, $left_context) === \false) { return \false; } $codebase = $statements_analyzer->getCodebase(); $left_cond_id = \spl_object_id($stmt->left); $left_clauses = \Psalm\Type\Algebra::getFormula($left_cond_id, $left_cond_id, $stmt->left, $context->self, $statements_analyzer, $codebase); foreach ($left_context->vars_in_scope as $var_id => $type) { if (isset($left_context->assigned_var_ids[$var_id])) { $context->vars_in_scope[$var_id] = $type; } } /** @var array */ $left_referenced_var_ids = $left_context->referenced_var_ids; $context->referenced_var_ids = \array_merge($pre_referenced_var_ids, $left_referenced_var_ids); $left_assigned_var_ids = \array_diff_key($left_context->assigned_var_ids, $pre_assigned_var_ids); $left_referenced_var_ids = \array_diff_key($left_referenced_var_ids, $left_assigned_var_ids); $context_clauses = \array_merge($left_context->clauses, $left_clauses); if ($left_context->reconciled_expression_clauses) { $reconciled_expression_clauses = $left_context->reconciled_expression_clauses; $context_clauses = \array_values(\array_filter($context_clauses, function ($c) use($reconciled_expression_clauses) : bool { return !\in_array($c->hash, $reconciled_expression_clauses); })); if (\count($context_clauses) === 1 && $context_clauses[0]->wedge && !$context_clauses[0]->possibilities) { $context_clauses = []; } } $simplified_clauses = \Psalm\Type\Algebra::simplifyCNF($context_clauses); $active_left_assertions = []; $left_type_assertions = \Psalm\Type\Algebra::getTruthsFromFormula($simplified_clauses, $left_cond_id, $left_referenced_var_ids, $active_left_assertions); $changed_var_ids = []; $right_context = clone $left_context; if ($left_type_assertions) { // while in an and, we allow scope to boil over to support // statements of the form if ($x && $x->foo()) $right_vars_in_scope = \Psalm\Type\Reconciler::reconcileKeyedTypes($left_type_assertions, $active_left_assertions, $context->vars_in_scope, $changed_var_ids, $left_referenced_var_ids, $statements_analyzer, [], $context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->left), $context->inside_negation); $right_context->vars_in_scope = $right_vars_in_scope; if ($context->if_scope) { $context->if_scope->if_cond_changed_var_ids += $changed_var_ids; } } $partitioned_clauses = \Psalm\Context::removeReconciledClauses($left_clauses, $changed_var_ids); $right_context->clauses = $partitioned_clauses[0]; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->right, $right_context) === \false) { return \false; } $context->referenced_var_ids = \array_merge($right_context->referenced_var_ids, $left_context->referenced_var_ids); if ($context->inside_conditional) { $context->updateChecks($right_context); $context->vars_possibly_in_scope = \array_merge($right_context->vars_possibly_in_scope, $left_context->vars_possibly_in_scope); $context->assigned_var_ids = \array_merge($left_context->assigned_var_ids, $right_context->assigned_var_ids); } if ($context->if_context && !$context->inside_negation) { $context->vars_in_scope = $right_context->vars_in_scope; $if_context = $context->if_context; foreach ($right_context->vars_in_scope as $var_id => $type) { if (!isset($if_context->vars_in_scope[$var_id])) { $if_context->vars_in_scope[$var_id] = $type; } elseif (isset($context->vars_in_scope[$var_id])) { $if_context->vars_in_scope[$var_id] = $context->vars_in_scope[$var_id]; } } $if_context->referenced_var_ids = \array_merge($context->referenced_var_ids, $if_context->referenced_var_ids); $if_context->assigned_var_ids = \array_merge($context->assigned_var_ids, $if_context->assigned_var_ids); $if_context->reconciled_expression_clauses = \array_merge($if_context->reconciled_expression_clauses, \array_map(function ($c) { return $c->hash; }, $partitioned_clauses[1])); $if_context->vars_possibly_in_scope = \array_merge($context->vars_possibly_in_scope, $if_context->vars_possibly_in_scope); $if_context->updateChecks($context); } else { $context->vars_in_scope = $left_context->vars_in_scope; } return \true; } } getCodebase(); $left_type = $statements_analyzer->node_data->getType($left); $right_type = $statements_analyzer->node_data->getType($right); $config = \Psalm\Config::getInstance(); if ($left_type && $right_type) { $result_type = \Psalm\Type::getString(); if ($left_type->hasMixed() || $right_type->hasMixed()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if ($left_type->hasMixed()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedOperand('Left operand cannot be mixed', new \Psalm\CodeLocation($statements_analyzer->getSource(), $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedOperand('Right operand cannot be mixed', new \Psalm\CodeLocation($statements_analyzer->getSource(), $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } } return; } if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } if ($left_type->isNull()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullOperand('Cannot concatenate with a ' . $left_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } if ($right_type->isNull()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullOperand('Cannot concatenate with a ' . $right_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } if ($left_type->isFalse()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\FalseOperand('Cannot concatenate with a ' . $left_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } if ($right_type->isFalse()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\FalseOperand('Cannot concatenate with a ' . $right_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } if ($left_type->isNullable() && !$left_type->ignore_nullable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullOperand('Cannot concatenate with a possibly null ' . $left_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($right_type->isNullable() && !$right_type->ignore_nullable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullOperand('Cannot concatenate with a possibly null ' . $right_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($left_type->isFalsable() && !$left_type->ignore_falsable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyFalseOperand('Cannot concatenate with a possibly false ' . $left_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($right_type->isFalsable() && !$right_type->ignore_falsable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyFalseOperand('Cannot concatenate with a possibly false ' . $right_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $left_type_match = \true; $right_type_match = \true; $has_valid_left_operand = \false; $has_valid_right_operand = \false; $left_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $right_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); foreach ($left_type->getAtomicTypes() as $left_type_part) { if ($left_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedOperand('Left operand cannot be mixed', new \Psalm\CodeLocation($statements_analyzer->getSource(), $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } if ($left_type_part instanceof \Psalm\Type\Atomic\TNull || $left_type_part instanceof \Psalm\Type\Atomic\TFalse) { continue; } $left_type_part_match = \Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $left_type_part, new \Psalm\Type\Atomic\TString(), \false, \false, $left_comparison_result); $left_type_match = $left_type_match && $left_type_part_match; $has_valid_left_operand = $has_valid_left_operand || $left_type_part_match; if ($left_comparison_result->to_string_cast && $config->strict_binary_operands) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImplicitToStringCast('Left side of concat op expects string, ' . '\'' . $left_type . '\' provided with a __toString method', new \Psalm\CodeLocation($statements_analyzer->getSource(), $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } } foreach ($left_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $to_string_method_id = new \Psalm\Internal\MethodIdentifier($atomic_type->value, '__tostring'); if ($codebase->methods->methodExists($to_string_method_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $left) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath())) { try { $storage = $codebase->methods->getStorage($to_string_method_id); } catch (\UnexpectedValueException $e) { continue; } if ($context->mutation_free && !$storage->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call a possibly-mutating method ' . $atomic_type->value . '::__toString from a pure context', new \Psalm\CodeLocation($statements_analyzer, $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } } } } } foreach ($right_type->getAtomicTypes() as $right_type_part) { if ($right_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedOperand('Right operand cannot be a template param', new \Psalm\CodeLocation($statements_analyzer->getSource(), $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } if ($right_type_part instanceof \Psalm\Type\Atomic\TNull || $right_type_part instanceof \Psalm\Type\Atomic\TFalse) { continue; } $right_type_part_match = \Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $right_type_part, new \Psalm\Type\Atomic\TString(), \false, \false, $right_comparison_result); $right_type_match = $right_type_match && $right_type_part_match; $has_valid_right_operand = $has_valid_right_operand || $right_type_part_match; if ($right_comparison_result->to_string_cast && $config->strict_binary_operands) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImplicitToStringCast('Right side of concat op expects string, ' . '\'' . $right_type . '\' provided with a __toString method', new \Psalm\CodeLocation($statements_analyzer->getSource(), $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } } foreach ($right_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $to_string_method_id = new \Psalm\Internal\MethodIdentifier($atomic_type->value, '__tostring'); if ($codebase->methods->methodExists($to_string_method_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $right) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath())) { try { $storage = $codebase->methods->getStorage($to_string_method_id); } catch (\UnexpectedValueException $e) { continue; } if ($context->mutation_free && !$storage->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call a possibly-mutating method ' . $atomic_type->value . '::__toString from a pure context', new \Psalm\CodeLocation($statements_analyzer, $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } } } } } if (!$left_type_match && (!$left_comparison_result->scalar_type_match_found || $config->strict_binary_operands)) { if ($has_valid_left_operand) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidOperand('Cannot concatenate with a ' . $left_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidOperand('Cannot concatenate with a ' . $left_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $left)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if (!$right_type_match && (!$right_comparison_result->scalar_type_match_found || $config->strict_binary_operands)) { if ($has_valid_right_operand) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidOperand('Cannot concatenate with a ' . $right_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidOperand('Cannot concatenate with a ' . $right_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $right)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } // When concatenating two known string literals (with only one possibility), // put the concatenated string into $result_type if ($left_type && $right_type && $left_type->isSingleStringLiteral() && $right_type->isSingleStringLiteral()) { $literal = $left_type->getSingleStringLiteral()->value . $right_type->getSingleStringLiteral()->value; if (\strlen($literal) <= 1000) { // Limit these to 10000 bytes to avoid extremely large union types from repeated concatenations, etc $result_type = \Psalm\Type::getString($literal); } } else { if ($left_type && $right_type) { $left_type_literal_value = $left_type->isSingleStringLiteral() ? $left_type->getSingleStringLiteral()->value : null; $right_type_literal_value = $right_type->isSingleStringLiteral() ? $right_type->getSingleStringLiteral()->value : null; if (($left_type->getId() === 'lowercase-string' || $left_type->getId() === 'non-empty-lowercase-string' || $left_type->isInt() || $left_type_literal_value !== null && \strtolower($left_type_literal_value) === $left_type_literal_value) && ($right_type->getId() === 'lowercase-string' || $right_type->getId() === 'non-empty-lowercase-string' || $right_type->isInt() || $right_type_literal_value !== null && \strtolower($right_type_literal_value) === $right_type_literal_value)) { if ($left_type->getId() === 'non-empty-lowercase-string' || $left_type->isInt() || $left_type_literal_value !== null && \strtolower($left_type_literal_value) === $left_type_literal_value || $right_type->getId() === 'non-empty-lowercase-string' || $right_type->isInt() || $right_type_literal_value !== null && \strtolower($right_type_literal_value) === $right_type_literal_value) { $result_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyLowercaseString()]); } else { $result_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLowercaseString()]); } } elseif ($left_type->getId() === 'non-empty-string' || $right_type->getId() === 'non-empty-string' || $left_type_literal_value || $right_type_literal_value) { $result_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyString()]); } } } } } node_data->getType($stmt->left); $stmt_right_type = $statements_analyzer->node_data->getType($stmt->right); if (!$stmt_left_type || !$stmt_right_type) { return; } if (($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd) && $stmt_left_type->hasString() && $stmt_right_type->hasString()) { $stmt_type = \Psalm\Type::getString(); $statements_analyzer->node_data->setType($stmt, $stmt_type); return; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mod || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Pow || ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseAnd || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftLeft || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\ShiftRight)) { \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\NonDivArithmeticOpAnalyzer::analyze($statements_analyzer, $statements_analyzer->node_data, $stmt->left, $stmt->right, $stmt, $result_type, $context); if (!$result_type) { $result_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TFloat()]); } $statements_analyzer->node_data->setType($stmt, $result_type); \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->left, $stmt->right, 'nondivop'); return; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseXor) { if ($stmt_left_type->hasBool() || $stmt_right_type->hasBool()) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getInt()); } \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->left, $stmt->right, 'xor'); return; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor) { if ($stmt_left_type->hasBool() || $stmt_right_type->hasBool()) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getBool()); } \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->left, $stmt->right, 'xor'); return; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div) { \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\NonDivArithmeticOpAnalyzer::analyze($statements_analyzer, $statements_analyzer->node_data, $stmt->left, $stmt->right, $stmt, $result_type, $context); if (!$result_type) { $result_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TFloat()]); } elseif ($result_type->hasInt()) { $result_type->addType(new \Psalm\Type\Atomic\TFloat()); } $statements_analyzer->node_data->setType($stmt, $result_type); \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->left, $stmt->right, 'div'); return; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr) { \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\NonDivArithmeticOpAnalyzer::analyze($statements_analyzer, $statements_analyzer->node_data, $stmt->left, $stmt->right, $stmt, $result_type, $context); \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->left, $stmt->right, 'or'); } } } left, $stmt->left->getAttributes()), ['stmts' => [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression($stmt->right)]], $stmt->getAttributes()); return \Psalm\Internal\Analyzer\Statements\Block\IfAnalyzer::analyze($statements_analyzer, $fake_if_stmt, $context) !== \false; } $codebase = $statements_analyzer->getCodebase(); $mic_drop_context = null; if (!$stmt->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr || !$stmt->left->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr || !$stmt->left->left->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr) { $if_scope = new \Psalm\Internal\Scope\IfScope(); try { $if_conditional_scope = \Psalm\Internal\Analyzer\Statements\Block\IfAnalyzer::analyzeIfConditional($statements_analyzer, $stmt->left, $context, $codebase, $if_scope, $context->branch_point ?: (int) $stmt->getAttribute('startFilePos')); $left_context = $if_conditional_scope->if_context; $left_referenced_var_ids = $if_conditional_scope->cond_referenced_var_ids; $left_assigned_var_ids = $if_conditional_scope->cond_assigned_var_ids; if ($stmt->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr) { $mic_drop_context = clone $context; } } catch (\Psalm\Exception\ScopeAnalysisException $e) { return \false; } } else { $pre_referenced_var_ids = $context->referenced_var_ids; $context->referenced_var_ids = []; $pre_assigned_var_ids = $context->assigned_var_ids; $mic_drop_context = clone $context; $left_context = clone $context; $left_context->parent_context = $context; $left_context->if_context = null; $left_context->assigned_var_ids = []; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->left, $left_context) === \false) { return \false; } foreach ($left_context->vars_in_scope as $var_id => $type) { if (!isset($context->vars_in_scope[$var_id])) { if (isset($left_context->assigned_var_ids[$var_id])) { $context->vars_in_scope[$var_id] = clone $type; } } else { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->vars_in_scope[$var_id], $type, $codebase); } } $left_referenced_var_ids = $left_context->referenced_var_ids; $left_context->referenced_var_ids = \array_merge($pre_referenced_var_ids, $left_referenced_var_ids); $left_assigned_var_ids = \array_diff_key($left_context->assigned_var_ids, $pre_assigned_var_ids); $left_context->assigned_var_ids = \array_merge($pre_assigned_var_ids, $left_context->assigned_var_ids); $left_referenced_var_ids = \array_diff_key($left_referenced_var_ids, $left_assigned_var_ids); } $left_cond_id = \spl_object_id($stmt->left); $left_clauses = \Psalm\Type\Algebra::getFormula($left_cond_id, $left_cond_id, $stmt->left, $context->self, $statements_analyzer, $codebase); try { $negated_left_clauses = \Psalm\Type\Algebra::negateFormula($left_clauses); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { try { $negated_left_clauses = \Psalm\Type\Algebra::getFormula($left_cond_id, $left_cond_id, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($stmt->left), $context->self, $statements_analyzer, $codebase, \false); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { return \false; } } if ($left_context->reconciled_expression_clauses) { $reconciled_expression_clauses = $left_context->reconciled_expression_clauses; $negated_left_clauses = \array_values(\array_filter($negated_left_clauses, function ($c) use($reconciled_expression_clauses) : bool { return !\in_array($c->hash, $reconciled_expression_clauses); })); if (\count($negated_left_clauses) === 1 && $negated_left_clauses[0]->wedge && !$negated_left_clauses[0]->possibilities) { $negated_left_clauses = []; } } $clauses_for_right_analysis = \Psalm\Type\Algebra::simplifyCNF(\array_merge($context->clauses, $negated_left_clauses)); $active_negated_type_assertions = []; $negated_type_assertions = \Psalm\Type\Algebra::getTruthsFromFormula($clauses_for_right_analysis, $left_cond_id, $left_referenced_var_ids, $active_negated_type_assertions); $changed_var_ids = []; $right_context = clone $context; if ($stmt->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr && $left_assigned_var_ids && $mic_drop_context) { \Psalm\Internal\Analyzer\Statements\Block\IfAnalyzer::addConditionallyAssignedVarsToContext($statements_analyzer, $stmt->left, $mic_drop_context, $right_context, $left_assigned_var_ids); } if ($negated_type_assertions) { // while in an or, we allow scope to boil over to support // statements of the form if ($x === null || $x->foo()) $right_vars_in_scope = \Psalm\Type\Reconciler::reconcileKeyedTypes($negated_type_assertions, $active_negated_type_assertions, $right_context->vars_in_scope, $changed_var_ids, $left_referenced_var_ids, $statements_analyzer, [], $left_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->left), !$context->inside_negation); $right_context->vars_in_scope = $right_vars_in_scope; } $right_context->clauses = $clauses_for_right_analysis; if ($changed_var_ids) { $partitioned_clauses = \Psalm\Context::removeReconciledClauses($right_context->clauses, $changed_var_ids); $right_context->clauses = $partitioned_clauses[0]; $right_context->reconciled_expression_clauses = \array_merge($context->reconciled_expression_clauses, \array_map(function ($c) { return $c->hash; }, $partitioned_clauses[1])); $partitioned_clauses = \Psalm\Context::removeReconciledClauses($context->clauses, $changed_var_ids); $context->clauses = $partitioned_clauses[0]; $context->reconciled_expression_clauses = \array_merge($context->reconciled_expression_clauses, \array_map(function ($c) { return $c->hash; }, $partitioned_clauses[1])); } $right_context->if_context = null; $pre_referenced_var_ids = $right_context->referenced_var_ids; $right_context->referenced_var_ids = []; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->right, $right_context) === \false) { return \false; } $right_referenced_var_ids = $right_context->referenced_var_ids; $right_context->referenced_var_ids = \array_merge($pre_referenced_var_ids, $right_referenced_var_ids); $right_cond_id = \spl_object_id($stmt->right); $right_clauses = \Psalm\Type\Algebra::getFormula($right_cond_id, $right_cond_id, $stmt->right, $context->self, $statements_analyzer, $codebase); $combined_right_clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($clauses_for_right_analysis, $right_clauses)); $active_right_type_assertions = []; $right_type_assertions = \Psalm\Type\Algebra::getTruthsFromFormula($combined_right_clauses, $right_cond_id, $right_referenced_var_ids, $active_right_type_assertions); if ($right_type_assertions) { $right_changed_var_ids = []; \Psalm\Type\Reconciler::reconcileKeyedTypes($right_type_assertions, $active_right_type_assertions, $right_context->vars_in_scope, $right_changed_var_ids, $right_referenced_var_ids, $statements_analyzer, [], $left_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->right), $context->inside_negation); } if (!$stmt->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_) { foreach ($right_context->vars_in_scope as $var_id => $type) { if (isset($context->vars_in_scope[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->vars_in_scope[$var_id], $type, $codebase); } } } elseif ($stmt->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($stmt->left->var, $context->self); if ($var_id && isset($left_context->vars_in_scope[$var_id])) { $left_inferred_reconciled = \Psalm\Internal\Type\AssertionReconciler::reconcile('!falsy', clone $left_context->vars_in_scope[$var_id], '', $statements_analyzer, $context->inside_loop, [], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->left), $statements_analyzer->getSuppressedIssues()); $context->vars_in_scope[$var_id] = $left_inferred_reconciled; } } if ($context->inside_conditional) { $context->updateChecks($right_context); } $context->referenced_var_ids = \array_merge($right_context->referenced_var_ids, $context->referenced_var_ids); $context->assigned_var_ids = \array_merge($context->assigned_var_ids, $right_context->assigned_var_ids); if ($context->if_context) { $if_context = $context->if_context; foreach ($right_context->vars_in_scope as $var_id => $type) { if (isset($if_context->vars_in_scope[$var_id])) { $if_context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($type, $if_context->vars_in_scope[$var_id], $codebase); } elseif (isset($left_context->vars_in_scope[$var_id])) { $if_context->vars_in_scope[$var_id] = $left_context->vars_in_scope[$var_id]; } } $if_context->referenced_var_ids = \array_merge($context->referenced_var_ids, $if_context->referenced_var_ids); $if_context->assigned_var_ids = \array_merge($context->assigned_var_ids, $if_context->assigned_var_ids); $if_context->updateChecks($context); } $context->vars_possibly_in_scope = \array_merge($right_context->vars_possibly_in_scope, $context->vars_possibly_in_scope); return \true; } } getFQCLN(), $statements_analyzer); // gets a variable id that *may* contain array keys $array_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($assign_var, $statements_analyzer->getFQCLN(), $statements_analyzer); $var_comments = []; $comment_type = null; $comment_type_location = null; $was_in_assignment = $context->inside_assignment; $context->inside_assignment = \true; $codebase = $statements_analyzer->getCodebase(); $base_assign_value = $assign_value; while ($base_assign_value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { $base_assign_value = $base_assign_value->expr; } if ($base_assign_value !== $assign_value) { \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $base_assign_value, $context); $assign_value_type = $statements_analyzer->node_data->getType($base_assign_value) ?: $assign_value_type; } $removed_taints = []; if ($doc_comment) { $file_path = $statements_analyzer->getRootFilePath(); $file_storage_provider = $codebase->file_storage_provider; $file_storage = $file_storage_provider->get($file_path); $template_type_map = $statements_analyzer->getTemplateTypeMap(); try { $var_comments = \Psalm\Internal\Analyzer\CommentAnalyzer::getTypeFromComment($doc_comment, $statements_analyzer->getSource(), $statements_analyzer->getAliases(), $template_type_map, $file_storage->type_aliases); } catch (\Psalm\Exception\IncorrectDocblockException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingDocblockType((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)))) { // fall through } } catch (\Psalm\Exception\DocblockParseException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)))) { // fall through } } foreach ($var_comments as $var_comment) { if ($var_comment->removed_taints) { $removed_taints = $var_comment->removed_taints; } self::assignTypeFromVarDocblock($statements_analyzer, $assign_var, $var_comment, $context, $var_id, $comment_type, $comment_type_location, $not_ignored_docblock_var_ids); } } if ($array_var_id) { unset($context->referenced_var_ids[$array_var_id]); $context->assigned_var_ids[$array_var_id] = \true; $context->possibly_assigned_var_ids[$array_var_id] = \true; } if ($assign_value) { if ($var_id && $assign_value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure) { foreach ($assign_value->uses as $closure_use) { if ($closure_use->byRef && \is_string($closure_use->var->name) && $var_id === '$' . $closure_use->var->name) { $context->vars_in_scope[$var_id] = \Psalm\Type::getClosure(); $context->vars_possibly_in_scope[$var_id] = \true; } } } $was_inside_use = $context->inside_use; $root_expr = $assign_var; while ($root_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { $root_expr = $root_expr->var; } // if we don't know where this data is going, treat as a dead-end usage if (!$root_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || \is_string($root_expr->name) && \in_array('$' . $root_expr->name, \Psalm\Internal\Analyzer\Statements\Expression\Fetch\VariableFetchAnalyzer::SUPER_GLOBALS, \true)) { $context->inside_use = \true; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $assign_value, $context) === \false) { if ($var_id) { if ($array_var_id) { $context->removeDescendents($array_var_id, null, $assign_value_type); } // if we're not exiting immediately, make everything mixed $context->vars_in_scope[$var_id] = $comment_type ?: \Psalm\Type::getMixed(); } return \false; } $context->inside_use = $was_inside_use; } if ($comment_type && $comment_type_location) { $temp_assign_value_type = $assign_value_type ? $assign_value_type : ($assign_value ? $statements_analyzer->node_data->getType($assign_value) : null); if ($codebase->find_unused_variables && $temp_assign_value_type && $array_var_id && (!$not_ignored_docblock_var_ids || isset($not_ignored_docblock_var_ids[$array_var_id])) && $temp_assign_value_type->getId() === $comment_type->getId() && !$comment_type->isMixed()) { if ($codebase->alter_code && isset($statements_analyzer->getProjectAnalyzer()->getIssuesToFix()['UnnecessaryVarAnnotation'])) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::addVarAnnotationToRemove($comment_type_location); } elseif (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnnecessaryVarAnnotation('The @var ' . $comment_type . ' annotation for ' . $array_var_id . ' is unnecessary', $comment_type_location))) { // fall through } } $parent_nodes = $temp_assign_value_type->parent_nodes ?? []; $assign_value_type = $comment_type; $assign_value_type->parent_nodes = $parent_nodes; } elseif (!$assign_value_type) { if ($assign_value) { $assign_value_type = $statements_analyzer->node_data->getType($assign_value); } if ($assign_value_type) { $assign_value_type = clone $assign_value_type; } else { $assign_value_type = \Psalm\Type::getMixed(); } } if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph && !$assign_value_type->parent_nodes) { if ($array_var_id) { $assignment_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($array_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)); } else { $assignment_node = new \Psalm\Internal\DataFlow\DataFlowNode('unknown-origin', 'unknown origin', null); } $assign_value_type->parent_nodes = [$assignment_node->id => $assignment_node]; } if ($array_var_id && isset($context->vars_in_scope[$array_var_id])) { if ($context->vars_in_scope[$array_var_id]->by_ref) { if ($context->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureByReferenceAssignment('Variable ' . $array_var_id . ' cannot be assigned to as it is passed by reference', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)))) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_impure = \true; $statements_analyzer->getSource()->inferred_has_mutation = \true; } $assign_value_type->by_ref = \true; } // removes dependent vars from $context $context->removeDescendents($array_var_id, $context->vars_in_scope[$array_var_id], $assign_value_type, $statements_analyzer); } else { $root_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getRootVarId($assign_var, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($root_var_id && isset($context->vars_in_scope[$root_var_id])) { $context->removeVarFromConflictingClauses($root_var_id, $context->vars_in_scope[$root_var_id], $statements_analyzer); } } $codebase = $statements_analyzer->getCodebase(); if ($assign_value_type->hasMixed()) { $root_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getRootVarId($assign_var, $statements_analyzer->getFQCLN(), $statements_analyzer); if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if (!$assign_var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && !\strpos($root_var_id ?? '', '->') && !$comment_type && \substr($var_id ?? '', 0, 2) !== '$_') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedAssignment($var_id ? 'Unable to determine the type that ' . $var_id . ' is being assigned to' : 'Unable to determine the type of this assignment', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } else { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } if ($var_id && isset($context->byref_constraints[$var_id]) && ($outer_constraint_type = $context->byref_constraints[$var_id]->type)) { if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $assign_value_type, $outer_constraint_type, $assign_value_type->ignore_nullable_issues, $assign_value_type->ignore_falsable_issues)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ReferenceConstraintViolation('Variable ' . $var_id . ' is limited to values of type ' . $context->byref_constraints[$var_id]->type . ' because it is passed by reference, ' . $assign_value_type->getId() . ' type found', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } if ($var_id === '$this' && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidScope('Cannot re-assign ' . $var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)), $statements_analyzer->getSuppressedIssues())) { return \false; } if (isset($context->protected_var_ids[$var_id]) && $assign_value_type->hasLiteralInt()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\LoopInvalidation('Variable ' . $var_id . ' has already been assigned in a for/foreach loop', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($assign_var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { if (\is_string($assign_var->name)) { if ($var_id) { $context->vars_in_scope[$var_id] = $assign_value_type; $context->vars_possibly_in_scope[$var_id] = \true; $location = new \Psalm\CodeLocation($statements_analyzer, $assign_var); if (!$statements_analyzer->hasVariable($var_id)) { $statements_analyzer->registerVariable($var_id, $location, $context->branch_point); } elseif (!$context->inside_isset) { $statements_analyzer->registerVariableAssignment($var_id, $location); } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $location = new \Psalm\CodeLocation($statements_analyzer, $assign_var); $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $assign_var, $location->raw_file_start . '-' . $location->raw_file_end . ':' . $assign_value_type->getId()); } if (isset($context->byref_constraints[$var_id])) { $assign_value_type->by_ref = \true; } if ($assign_value_type->by_ref) { if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph && $assign_value_type->parent_nodes) { $location = new \Psalm\CodeLocation($statements_analyzer, $assign_var); $byref_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_id, $location); foreach ($assign_value_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'variable-use'); $statements_analyzer->data_flow_graph->addPath($byref_node, $parent_node, 'byref-assignment'); } } } } } else { $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $assign_var->name, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph && $assign_value_type->parent_nodes) { foreach ($assign_value_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'variable-use'); } } } } elseif ($assign_var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\List_ || $assign_var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_) { if (!$assign_value_type->hasArray() && !$assign_value_type->isMixed() && !$assign_value_type->hasArrayAccessInterface($codebase)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArrayOffset('Cannot destructure non-array of type ' . $assign_value_type->getId(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $can_be_empty = \true; foreach ($assign_var->items as $offset => $assign_var_item) { // $assign_var_item can be null e.g. list($a, ) = ['a', 'b'] if (!$assign_var_item) { continue; } $var = $assign_var_item->value; if ($assign_value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ && $statements_analyzer->node_data->getType($assign_var_item->value)) { self::analyze($statements_analyzer, $var, $assign_var_item->value, null, $context, $doc_comment); continue; } $offset_value = null; if (!$assign_var_item->key) { $offset_value = $offset; } elseif ($assign_var_item->key instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $offset_value = $assign_var_item->key->value; } $list_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($var, $statements_analyzer->getFQCLN(), $statements_analyzer); $new_assign_type = null; $assigned = \false; $has_null = \false; foreach ($assign_value_type->getAtomicTypes() as $assign_value_atomic_type) { if ($assign_value_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray && !$assign_var_item->key) { // if object-like has int offsets if ($offset_value !== null && isset($assign_value_atomic_type->properties[$offset_value])) { $value_type = $assign_value_atomic_type->properties[$offset_value]; if ($value_type->possibly_undefined) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedArrayOffset('Possibly undefined array key', new \Psalm\CodeLocation($statements_analyzer->getSource(), $var)), $statements_analyzer->getSuppressedIssues())) { // fall through } $value_type = clone $value_type; $value_type->possibly_undefined = \false; } if ($statements_analyzer->data_flow_graph && $assign_value) { $assign_value_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($assign_value, $statements_analyzer->getFQCLN(), $statements_analyzer); $keyed_array_var_id = null; if ($assign_value_id) { $keyed_array_var_id = $assign_value_id . '[\'' . $offset_value . '\']'; } \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::taintArrayFetch($statements_analyzer, $assign_value, $keyed_array_var_id, $value_type, \Psalm\Type::getString((string) $offset_value)); } self::analyze($statements_analyzer, $var, null, $value_type, $context, $doc_comment); $assigned = \true; continue; } if ($assign_value_atomic_type->sealed) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArrayOffset('Cannot access value with offset ' . $offset, new \Psalm\CodeLocation($statements_analyzer->getSource(), $var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if ($assign_value_atomic_type instanceof \Psalm\Type\Atomic\TMixed) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArrayAccess('Cannot access array value on mixed variable ' . $array_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($assign_value_atomic_type instanceof \Psalm\Type\Atomic\TNull) { $has_null = \true; if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullArrayAccess('Cannot access array value on null variable ' . $array_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $var)), $statements_analyzer->getSuppressedIssues())) { // do nothing } } elseif (!$assign_value_atomic_type instanceof \Psalm\Type\Atomic\TArray && !$assign_value_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray && !$assign_value_atomic_type instanceof \Psalm\Type\Atomic\TList && !$assign_value_type->hasArrayAccessInterface($codebase)) { if ($assign_value_type->hasArray()) { if ($assign_value_atomic_type instanceof \Psalm\Type\Atomic\TFalse && $assign_value_type->ignore_falsable_issues || $assign_value_atomic_type instanceof \Psalm\Type\Atomic\TNull && $assign_value_type->ignore_nullable_issues) { // do nothing } elseif (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidArrayAccess('Cannot access array value on non-array variable ' . $array_var_id . ' of type ' . $assign_value_atomic_type->getId(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $var)), $statements_analyzer->getSuppressedIssues())) { // do nothing } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArrayAccess('Cannot access array value on non-array variable ' . $array_var_id . ' of type ' . $assign_value_atomic_type->getId(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $var)), $statements_analyzer->getSuppressedIssues())) { // do nothing } } } if ($var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\List_ || $var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_) { if ($assign_value_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $assign_value_atomic_type = $assign_value_atomic_type->getGenericArrayType(); } if ($assign_value_atomic_type instanceof \Psalm\Type\Atomic\TList) { $assign_value_atomic_type = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $assign_value_atomic_type->type_param]); } $array_value_type = $assign_value_atomic_type instanceof \Psalm\Type\Atomic\TArray ? clone $assign_value_atomic_type->type_params[1] : \Psalm\Type::getMixed(); self::analyze($statements_analyzer, $var, null, $array_value_type, $context, $doc_comment); continue; } if ($list_var_id) { $context->vars_possibly_in_scope[$list_var_id] = \true; $context->assigned_var_ids[$list_var_id] = \true; $context->possibly_assigned_var_ids[$list_var_id] = \true; $already_in_scope = isset($context->vars_in_scope[$list_var_id]); if (\strpos($list_var_id, '-') === \false && \strpos($list_var_id, '[') === \false) { $location = new \Psalm\CodeLocation($statements_analyzer, $var); if (!$statements_analyzer->hasVariable($list_var_id)) { $statements_analyzer->registerVariable($list_var_id, $location, $context->branch_point); } else { $statements_analyzer->registerVariableAssignment($list_var_id, $location); } if (isset($context->byref_constraints[$list_var_id])) { // something } } if ($assign_value_atomic_type instanceof \Psalm\Type\Atomic\TArray) { $new_assign_type = clone $assign_value_atomic_type->type_params[1]; if ($statements_analyzer->data_flow_graph && $assign_value) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::taintArrayFetch($statements_analyzer, $assign_value, null, $new_assign_type, \Psalm\Type::getArrayKey()); } $can_be_empty = !$assign_value_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyArray; } elseif ($assign_value_atomic_type instanceof \Psalm\Type\Atomic\TList) { $new_assign_type = clone $assign_value_atomic_type->type_param; if ($statements_analyzer->data_flow_graph && $assign_value) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::taintArrayFetch($statements_analyzer, $assign_value, null, $new_assign_type, \Psalm\Type::getArrayKey()); } $can_be_empty = !$assign_value_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyList; } elseif ($assign_value_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($assign_var_item->key && ($assign_var_item->key instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $assign_var_item->key instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) && isset($assign_value_atomic_type->properties[$assign_var_item->key->value])) { $new_assign_type = clone $assign_value_atomic_type->properties[$assign_var_item->key->value]; if ($new_assign_type->possibly_undefined) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedArrayOffset('Possibly undefined array key', new \Psalm\CodeLocation($statements_analyzer->getSource(), $var)), $statements_analyzer->getSuppressedIssues())) { // fall through } $new_assign_type->possibly_undefined = \false; } } if ($statements_analyzer->data_flow_graph && $assign_value && $new_assign_type) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::taintArrayFetch($statements_analyzer, $assign_value, null, $new_assign_type, \Psalm\Type::getArrayKey()); } $can_be_empty = !$assign_value_atomic_type->sealed; } elseif ($assign_value_atomic_type->hasArrayAccessInterface($codebase)) { \Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer::getKeyValueParamsForTraversableObject($assign_value_atomic_type, $codebase, $array_access_key_type, $array_access_value_type); $new_assign_type = $array_access_value_type; } if ($already_in_scope) { // removes dependennt vars from $context $context->removeDescendents($list_var_id, $context->vars_in_scope[$list_var_id], $new_assign_type, $statements_analyzer); } } } if (!$assigned) { foreach ($var_comments as $var_comment) { if (!$var_comment->type) { continue; } try { if ($var_comment->var_id === $list_var_id) { $var_comment_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $var_comment->type, $context->self, $context->self, $statements_analyzer->getParentFQCLN()); $var_comment_type->setFromDocblock(); $new_assign_type = $var_comment_type; break; } } catch (\UnexpectedValueException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)))) { // fall through } } } if ($list_var_id) { $context->vars_in_scope[$list_var_id] = $new_assign_type ?: \Psalm\Type::getMixed(); if ($context->error_suppressing && ($offset || $can_be_empty) || $has_null) { $context->vars_in_scope[$list_var_id]->addType(new \Psalm\Type\Atomic\TNull()); } if ($statements_analyzer->data_flow_graph) { $data_flow_graph = $statements_analyzer->data_flow_graph; $var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $var); if (!$context->vars_in_scope[$list_var_id]->parent_nodes) { $assignment_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($list_var_id, $var_location); $context->vars_in_scope[$list_var_id]->parent_nodes = [$assignment_node->id => $assignment_node]; } else { if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $context->vars_in_scope[$list_var_id]->parent_nodes = []; } else { $new_parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($list_var_id, $var_location); $statements_analyzer->data_flow_graph->addNode($new_parent_node); foreach ($context->vars_in_scope[$list_var_id]->parent_nodes as $parent_node) { $data_flow_graph->addPath($parent_node, $new_parent_node, '=', [], $removed_taints); } $context->vars_in_scope[$list_var_id]->parent_nodes = [$new_parent_node->id => $new_parent_node]; } } } } } } } elseif ($assign_var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { \Psalm\Internal\Analyzer\Statements\Expression\Assignment\ArrayAssignmentAnalyzer::analyze($statements_analyzer, $assign_var, $context, $assign_value, $assign_value_type); } elseif ($assign_var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch) { if (!$assign_var->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $was_inside_use = $context->inside_use; $context->inside_use = \true; // this can happen when the user actually means to type $this->, but there's // a variable on the next line if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $assign_var->var, $context) === \false) { return \false; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $assign_var->name, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; } if ($assign_var->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $prop_name = $assign_var->name->name; } elseif (($assign_var_name_type = $statements_analyzer->node_data->getType($assign_var->name)) && $assign_var_name_type->isSingleStringLiteral()) { $prop_name = $assign_var_name_type->getSingleStringLiteral()->value; } else { $prop_name = null; } if ($prop_name) { \Psalm\Internal\Analyzer\Statements\Expression\Assignment\InstancePropertyAssignmentAnalyzer::analyze($statements_analyzer, $assign_var, $prop_name, $assign_value, $assign_value_type, $context); } else { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $assign_var->var, $context) === \false) { return \false; } if (($assign_var_type = $statements_analyzer->node_data->getType($assign_var->var)) && !$context->ignore_variable_property) { $stmt_var_type = $assign_var_type; if ($stmt_var_type->hasObjectType()) { foreach ($stmt_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TNamedObject) { $codebase->analyzer->addMixedMemberName(\strtolower($type->value) . '::$', $context->calling_method_id ?: $statements_analyzer->getFileName()); } } } } } if ($var_id) { $context->vars_possibly_in_scope[$var_id] = \true; } $property_var_pure_compatible = $statements_analyzer->node_data->isPureCompatible($assign_var->var); // prevents writing to any properties in a mutation-free context if (!$property_var_pure_compatible && !$context->collect_mutations && !$context->collect_initializations) { if ($context->mutation_free || $context->external_mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpurePropertyAssignment('Cannot assign to a property from a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $assign_var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { if (!$assign_var->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || $assign_var->var->name !== 'this') { $statements_analyzer->getSource()->inferred_has_mutation = \true; } $statements_analyzer->getSource()->inferred_impure = \true; } } } elseif ($assign_var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch && $assign_var->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $assign_var, $context) === \false) { return \false; } if ($context->check_classes) { \Psalm\Internal\Analyzer\Statements\Expression\Assignment\StaticPropertyAssignmentAnalyzer::analyze($statements_analyzer, $assign_var, $assign_value, $assign_value_type, $context); } if ($var_id) { $context->vars_possibly_in_scope[$var_id] = \true; } } if ($var_id && isset($context->vars_in_scope[$var_id])) { if ($context->vars_in_scope[$var_id]->isVoid()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\AssignmentToVoid('Cannot assign ' . $var_id . ' to type void', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)), $statements_analyzer->getSuppressedIssues())) { // fall through } $context->vars_in_scope[$var_id] = \Psalm\Type::getNull(); if (!$was_in_assignment) { $context->inside_assignment = \false; } return $context->vars_in_scope[$var_id]; } if ($context->vars_in_scope[$var_id]->isNever()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NoValue('This function or method call never returns output', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var)), $statements_analyzer->getSuppressedIssues())) { return \false; } $context->vars_in_scope[$var_id] = \Psalm\Type::getEmpty(); if (!$was_in_assignment) { $context->inside_assignment = \false; } return $context->vars_in_scope[$var_id]; } if ($statements_analyzer->data_flow_graph) { $data_flow_graph = $statements_analyzer->data_flow_graph; if ($context->vars_in_scope[$var_id]->parent_nodes) { if ($data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $context->vars_in_scope[$var_id]->parent_nodes = []; } else { $var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $assign_var); $new_parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_id, $var_location); $data_flow_graph->addNode($new_parent_node); foreach ($context->vars_in_scope[$var_id]->parent_nodes as $parent_node) { $data_flow_graph->addPath($parent_node, $new_parent_node, '=', [], $removed_taints); } $context->vars_in_scope[$var_id]->parent_nodes = [$new_parent_node->id => $new_parent_node]; } } } } if (!$was_in_assignment) { $context->inside_assignment = \false; } return $assign_value_type; } public static function assignTypeFromVarDocblock(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node $stmt, \Psalm\Internal\Scanner\VarDocblockComment $var_comment, \Psalm\Context $context, ?string $var_id = null, ?\Psalm\Type\Union &$comment_type = null, ?\Psalm\CodeLocation\DocblockTypeLocation &$comment_type_location = null, array $not_ignored_docblock_var_ids = []) : void { if (!$var_comment->type) { return; } $codebase = $statements_analyzer->getCodebase(); try { $var_comment_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $var_comment->type, $context->self, $context->self, $statements_analyzer->getParentFQCLN()); $var_comment_type->setFromDocblock(); $var_comment_type->check($statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues(), [], \false, \false, \false, $context->calling_method_id); $type_location = null; if ($var_comment->type_start && $var_comment->type_end && $var_comment->line_number) { $type_location = new \Psalm\CodeLocation\DocblockTypeLocation($statements_analyzer, $var_comment->type_start, $var_comment->type_end, $var_comment->line_number); if ($codebase->alter_code) { $codebase->classlikes->handleDocblockTypeInMigration($codebase, $statements_analyzer, $var_comment_type, $type_location, $context->calling_method_id); } } if (!$var_comment->var_id || $var_comment->var_id === $var_id) { $comment_type = $var_comment_type; $comment_type_location = $type_location; return; } $project_analyzer = $statements_analyzer->getProjectAnalyzer(); if ($codebase->find_unused_variables && $type_location && (!$not_ignored_docblock_var_ids || isset($not_ignored_docblock_var_ids[$var_comment->var_id])) && isset($context->vars_in_scope[$var_comment->var_id]) && $context->vars_in_scope[$var_comment->var_id]->getId() === $var_comment_type->getId() && !$var_comment_type->isMixed()) { if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['UnnecessaryVarAnnotation'])) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::addVarAnnotationToRemove($type_location); } elseif (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnnecessaryVarAnnotation('The @var ' . $var_comment_type . ' annotation for ' . $var_comment->var_id . ' is unnecessary', $type_location), $statements_analyzer->getSuppressedIssues(), \true)) { // fall through } } $parent_nodes = $context->vars_in_scope[$var_comment->var_id]->parent_nodes ?? []; $var_comment_type->parent_nodes = $parent_nodes; $context->vars_in_scope[$var_comment->var_id] = $var_comment_type; } catch (\UnexpectedValueException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)))) { // fall through } } } public static function analyzeAssignmentOperation(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp $stmt, \Psalm\Context $context) : bool { $array_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->var, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Coalesce) { $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_coalesce_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce($stmt->var, $stmt->expr, $stmt->getAttributes()); $fake_coalesce_type = \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::analyze($statements_analyzer, $stmt->var, $fake_coalesce_expr, null, $context, $stmt->getDocComment()); $statements_analyzer->node_data = $old_data_provider; if ($fake_coalesce_type) { if ($array_var_id) { $context->vars_in_scope[$array_var_id] = $fake_coalesce_type; } $statements_analyzer->node_data->setType($stmt, $fake_coalesce_type); } return \true; } $was_in_assignment = $context->inside_assignment; $context->inside_assignment = \true; $root_expr = $stmt->var; while ($root_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { $root_expr = $root_expr->var; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === \false) { return \false; } $was_inside_use = $context->inside_use; // if we don't know where this data is going, treat as a dead-end usage if (!$root_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || \is_string($root_expr->name) && \in_array('$' . $root_expr->name, \Psalm\Internal\Analyzer\Statements\Expression\Fetch\VariableFetchAnalyzer::SUPER_GLOBALS, \true)) { $context->inside_use = \true; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; if ($array_var_id && $stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && ($stmt_var_var_type = $statements_analyzer->node_data->getType($stmt->var->var)) && !$stmt_var_var_type->reference_free) { if ($context->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpurePropertyAssignment('Cannot assign to a property from a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $stmt->var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } } elseif (!$context->collect_mutations && !$context->collect_initializations && $stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch) { $lhs_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->var->var, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($context->mutation_free) { if (isset($context->vars_in_scope[$lhs_var_id]) && !$context->vars_in_scope[$lhs_var_id]->allow_mutations) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpurePropertyAssignment('Cannot assign to a property from a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } } $codebase = $statements_analyzer->getCodebase(); if ($array_var_id) { $context->assigned_var_ids[$array_var_id] = \true; $context->possibly_assigned_var_ids[$array_var_id] = \true; if ($codebase->find_unused_variables && $stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { $location = new \Psalm\CodeLocation($statements_analyzer, $stmt->var); $statements_analyzer->registerVariableAssignment($array_var_id, $location); } } $stmt_var_type = $statements_analyzer->node_data->getType($stmt->var); $stmt_var_type = $stmt_var_type ? clone $stmt_var_type : null; $stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr); $result_type = null; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Plus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Minus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mod || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mul || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Pow) { \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\NonDivArithmeticOpAnalyzer::analyze($statements_analyzer, $statements_analyzer->node_data, $stmt->var, $stmt->expr, $stmt, $result_type, $context); if ($stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { $result_type = $result_type ?: \Psalm\Type::getMixed($context->inside_loop); \Psalm\Internal\Analyzer\Statements\Expression\Assignment\ArrayAssignmentAnalyzer::analyze($statements_analyzer, $stmt->var, $context, $stmt->expr, $result_type); } else { $result_type = $result_type ? clone $result_type : new \Psalm\Type\Union([new \Psalm\Type\Atomic\TInt(), new \Psalm\Type\Atomic\TFloat()]); } if ($array_var_id) { $context->vars_in_scope[$array_var_id] = $result_type; } $statements_analyzer->node_data->setType($stmt, $result_type); \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->var, $stmt->expr, 'nondivop'); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Div) { if ($stmt_var_type && $stmt_expr_type && $stmt_var_type->hasDefinitelyNumericType() && $stmt_expr_type->hasDefinitelyNumericType() && $array_var_id) { $context->vars_in_scope[$array_var_id] = \Psalm\Type::combineUnionTypes(\Psalm\Type::getFloat(), \Psalm\Type::getInt()); $statements_analyzer->node_data->setType($stmt, clone $context->vars_in_scope[$array_var_id]); } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->var, $stmt->expr, 'div'); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Concat) { \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\ConcatAnalyzer::analyze($statements_analyzer, $stmt->var, $stmt->expr, $context, $result_type); if ($result_type && $array_var_id) { $context->vars_in_scope[$array_var_id] = $result_type; $statements_analyzer->node_data->setType($stmt, clone $context->vars_in_scope[$array_var_id]); \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->var, $stmt->expr, 'concatop'); } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseXor || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\BitwiseAnd || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftLeft || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\ShiftRight) { \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\NonDivArithmeticOpAnalyzer::analyze($statements_analyzer, $statements_analyzer->node_data, $stmt->var, $stmt->expr, $stmt, $result_type, $context); if ($result_type && $array_var_id) { $context->vars_in_scope[$array_var_id] = clone $result_type; $statements_analyzer->node_data->setType($stmt, $context->vars_in_scope[$array_var_id]); } \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->var, $stmt->expr, 'bitwiseop'); } if ($statements_analyzer->data_flow_graph && $array_var_id && isset($context->vars_in_scope[$array_var_id]) && ($stmt_type = $statements_analyzer->node_data->getType($stmt))) { $data_flow_graph = $statements_analyzer->data_flow_graph; if ($stmt_type->parent_nodes) { if ($data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $stmt_type->parent_nodes = []; } else { $var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var); $new_parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($array_var_id, $var_location); $data_flow_graph->addNode($new_parent_node); foreach ($stmt_type->parent_nodes as $parent_node) { $data_flow_graph->addPath($parent_node, $new_parent_node, '='); } $context->vars_in_scope[$array_var_id]->parent_nodes = [$new_parent_node->id => $new_parent_node]; } } } if ($array_var_id && isset($context->vars_in_scope[$array_var_id])) { if ($result_type && $context->vars_in_scope[$array_var_id]->by_ref) { $result_type->by_ref = \true; } // removes dependent vars from $context $context->removeDescendents($array_var_id, $context->vars_in_scope[$array_var_id], $result_type, $statements_analyzer); } else { $root_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getRootVarId($stmt->var, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($root_var_id && isset($context->vars_in_scope[$root_var_id])) { $context->removeVarFromConflictingClauses($root_var_id, $context->vars_in_scope[$root_var_id], $statements_analyzer); } } if (!($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Plus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Minus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mod || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Mul || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp\Pow) && $stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { \Psalm\Internal\Analyzer\Statements\Expression\Assignment\ArrayAssignmentAnalyzer::analyze($statements_analyzer, $stmt->var, $context, null, $result_type ?: \Psalm\Type::getEmpty()); } if (!$was_in_assignment) { $context->inside_assignment = \false; } return \true; } public static function analyzeAssignmentRef(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef $stmt, \Psalm\Context $context) : bool { $assignment_type = self::analyze($statements_analyzer, $stmt->var, $stmt->expr, null, $context, $stmt->getDocComment()); if ($assignment_type === \false) { return \false; } $assignment_type->by_ref = \true; $lhs_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->var, $statements_analyzer->getFQCLN(), $statements_analyzer); $rhs_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->expr, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($lhs_var_id) { $context->vars_in_scope[$lhs_var_id] = $assignment_type; $context->hasVariable($lhs_var_id); $context->byref_constraints[$lhs_var_id] = new \Psalm\Internal\ReferenceConstraint(); if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph) { foreach ($context->vars_in_scope[$lhs_var_id]->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'variable-use'); } } } if ($rhs_var_id) { if (!isset($context->vars_in_scope[$rhs_var_id])) { $context->vars_in_scope[$rhs_var_id] = \Psalm\Type::getMixed(); } $context->byref_constraints[$rhs_var_id] = new \Psalm\Internal\ReferenceConstraint(); } if ($statements_analyzer->data_flow_graph && $lhs_var_id && $rhs_var_id && isset($context->vars_in_scope[$rhs_var_id])) { $rhs_type = $context->vars_in_scope[$rhs_var_id]; $data_flow_graph = $statements_analyzer->data_flow_graph; $lhs_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var); $lhs_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($lhs_var_id, $lhs_location); foreach ($rhs_type->parent_nodes as $byref_destination_node) { $data_flow_graph->addPath($lhs_node, $byref_destination_node, '='); } } return \true; } public static function assignByRefParam(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, \Psalm\Type\Union $by_ref_type, \Psalm\Type\Union $by_ref_out_type, \Psalm\Context $context, bool $constrain_type = \true, bool $prevent_null = \false) : void { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $prop_name = $stmt->name->name; \Psalm\Internal\Analyzer\Statements\Expression\Assignment\InstancePropertyAssignmentAnalyzer::analyze($statements_analyzer, $stmt, $prop_name, null, $by_ref_out_type, $context); return; } $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($stmt, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($var_id) { $var_not_in_scope = \false; if (!$by_ref_type->hasMixed() && $constrain_type) { $context->byref_constraints[$var_id] = new \Psalm\Internal\ReferenceConstraint($by_ref_type); } if (!$context->hasVariable($var_id)) { $context->vars_possibly_in_scope[$var_id] = \true; if (!$statements_analyzer->hasVariable($var_id)) { if ($constrain_type && $prevent_null && !$by_ref_type->isMixed() && !$by_ref_type->isNullable() && !\strpos($var_id, '->') && !\strpos($var_id, '::')) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullReference('Not expecting null argument passed by reference', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $context->hasVariable($var_id); } else { $var_not_in_scope = \true; } } elseif ($var_id === '$this') { // don't allow changing $this return; } else { $existing_type = $context->vars_in_scope[$var_id]; // removes dependent vars from $context $context->removeDescendents($var_id, $existing_type, $by_ref_type, $statements_analyzer); $by_ref_out_type = clone $by_ref_out_type; if ($existing_type->parent_nodes) { $by_ref_out_type->parent_nodes += $existing_type->parent_nodes; } if ($existing_type->getId() !== 'array') { $context->vars_in_scope[$var_id] = $by_ref_out_type; if (!($stmt_type = $statements_analyzer->node_data->getType($stmt)) || $stmt_type->isEmpty()) { $statements_analyzer->node_data->setType($stmt, clone $by_ref_type); } return; } } $context->assigned_var_ids[$var_id] = \true; $context->vars_in_scope[$var_id] = $by_ref_out_type; $stmt_type = $statements_analyzer->node_data->getType($stmt); if (!$stmt_type || $stmt_type->isEmpty()) { $statements_analyzer->node_data->setType($stmt, clone $by_ref_type); } if ($var_not_in_scope && $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { $statements_analyzer->registerPossiblyUndefinedVariable($var_id, $stmt); } } } } expr, $context); $expr_type = $statements_analyzer->node_data->getType($stmt->expr); if ($expr_type) { if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && $expr_type->parent_nodes && !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $arg_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr); $eval_param_sink = \Psalm\Internal\DataFlow\TaintSink::getForMethodArgument('eval', 'eval', 0, $arg_location, $arg_location); $eval_param_sink->taints = [\Psalm\Type\TaintKind::INPUT_TEXT]; $statements_analyzer->data_flow_graph->addSink($eval_param_sink); foreach ($expr_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $eval_param_sink, 'arg'); } } } $context->check_classes = \false; $context->check_variables = \false; } } inside_assignment; $context->inside_assignment = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === \false) { if (!$was_inside_assignment) { $context->inside_assignment = \false; } return \false; } if (!$was_inside_assignment) { $context->inside_assignment = \false; } $stmt_var_type = $statements_analyzer->node_data->getType($stmt->var); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec) { $statements_analyzer->node_data->setType($stmt, $stmt_var_type ?: \Psalm\Type::getMixed()); } if (($stmt_var_type = $statements_analyzer->node_data->getType($stmt->var)) && $stmt_var_type->hasString() && ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc)) { $return_type = null; $fake_right_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(1, $stmt->getAttributes()); $statements_analyzer->node_data->setType($fake_right_expr, \Psalm\Type::getInt()); \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\NonDivArithmeticOpAnalyzer::analyze($statements_analyzer, $statements_analyzer->node_data, $stmt->var, $fake_right_expr, $stmt, $return_type, $context); $stmt_type = clone $stmt_var_type; $statements_analyzer->node_data->setType($stmt, $stmt_type); \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::addDataFlow($statements_analyzer, $stmt, $stmt->var, $fake_right_expr, 'inc'); $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->var, null); $codebase = $statements_analyzer->getCodebase(); if ($var_id && isset($context->vars_in_scope[$var_id])) { $context->vars_in_scope[$var_id] = $stmt_type; if ($codebase->find_unused_variables && $stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { $context->assigned_var_ids[$var_id] = \true; $context->possibly_assigned_var_ids[$var_id] = \true; } // removes dependent vars from $context $context->removeDescendents($var_id, $context->vars_in_scope[$var_id], $return_type, $statements_analyzer); } } else { $fake_right_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(1, $stmt->getAttributes()); $operation = $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus($stmt->var, $fake_right_expr, $stmt->var->getAttributes()) : new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus($stmt->var, $fake_right_expr, $stmt->var->getAttributes()); $fake_assignment = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign($stmt->var, $operation, $stmt->getAttributes()); $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $fake_assignment, $context) === \false) { return \false; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec) { $old_node_data->setType($stmt, $statements_analyzer->node_data->getType($operation) ?: \Psalm\Type::getMixed()); } $statements_analyzer->node_data = $old_node_data; } return \true; } } getCodebase(); $config = $codebase->config; if (!$config->allow_includes) { throw new \Psalm\Exception\FileIncludeException('File includes are not allowed per your Psalm config - check the allowFileIncludes flag.'); } $was_inside_call = $context->inside_call; $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } if (!$was_inside_call) { $context->inside_call = \false; } $stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr); if ($stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $stmt_expr_type && $stmt_expr_type->isSingleStringLiteral()) { if ($stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $path_to_file = $stmt->expr->value; } else { $path_to_file = $stmt_expr_type->getSingleStringLiteral()->value; } $path_to_file = \str_replace('/', \DIRECTORY_SEPARATOR, $path_to_file); // attempts to resolve using get_include_path dirs $include_path = self::resolveIncludePath($path_to_file, \dirname($statements_analyzer->getFilePath())); $path_to_file = $include_path ? $include_path : $path_to_file; if (\DIRECTORY_SEPARATOR === '/') { $is_path_relative = $path_to_file[0] !== \DIRECTORY_SEPARATOR; } else { $is_path_relative = !\preg_match('~^[A-Z]:\\\\~i', $path_to_file); } if ($is_path_relative) { $path_to_file = $config->base_dir . \DIRECTORY_SEPARATOR . $path_to_file; } } else { $path_to_file = self::getPathTo($stmt->expr, $statements_analyzer->node_data, $statements_analyzer, $statements_analyzer->getFileName(), $config); } if ($stmt_expr_type && $statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && $stmt_expr_type->parent_nodes && !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $arg_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr); $include_param_sink = \Psalm\Internal\DataFlow\TaintSink::getForMethodArgument('include', 'include', 0, $arg_location); $include_param_sink->taints = [\Psalm\Type\TaintKind::INPUT_TEXT]; $statements_analyzer->data_flow_graph->addSink($include_param_sink); foreach ($stmt_expr_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $include_param_sink, 'arg'); } } if ($path_to_file) { $path_to_file = self::normalizeFilePath($path_to_file); // if the file is already included, we can't check much more if (\in_array(\realpath($path_to_file), \get_included_files(), \true)) { return \true; } $current_file_analyzer = $statements_analyzer->getFileAnalyzer(); if ($current_file_analyzer->project_analyzer->fileExists($path_to_file)) { if ($statements_analyzer->hasParentFilePath($path_to_file) || !$codebase->file_storage_provider->has($path_to_file) || $statements_analyzer->hasAlreadyRequiredFilePath($path_to_file) && !$codebase->file_storage_provider->get($path_to_file)->has_extra_statements) { return \true; } $current_file_analyzer->addRequiredFilePath($path_to_file); $file_name = $config->shortenFileName($path_to_file); $nesting = $statements_analyzer->getRequireNesting() + 1; $current_file_analyzer->project_analyzer->progress->debug(\str_repeat(' ', $nesting) . 'checking ' . $file_name . \PHP_EOL); $include_file_analyzer = new \Psalm\Internal\Analyzer\FileAnalyzer($current_file_analyzer->project_analyzer, $path_to_file, $file_name); $include_file_analyzer->setRootFilePath($current_file_analyzer->getRootFilePath(), $current_file_analyzer->getRootFileName()); $include_file_analyzer->addParentFilePath($current_file_analyzer->getFilePath()); $include_file_analyzer->addRequiredFilePath($current_file_analyzer->getFilePath()); foreach ($current_file_analyzer->getRequiredFilePaths() as $required_file_path) { $include_file_analyzer->addRequiredFilePath($required_file_path); } foreach ($current_file_analyzer->getParentFilePaths() as $parent_file_path) { $include_file_analyzer->addParentFilePath($parent_file_path); } try { $include_file_analyzer->analyze($context, \false, $global_context); } catch (\Psalm\Exception\UnpreparedAnalysisException $e) { if ($config->skip_checks_on_unresolvable_includes) { $context->check_classes = \false; $context->check_variables = \false; $context->check_functions = \false; } } $included_return_type = $include_file_analyzer->getReturnType(); if ($included_return_type) { $statements_analyzer->node_data->setType($stmt, $included_return_type); } $context->has_returned = \false; foreach ($include_file_analyzer->getRequiredFilePaths() as $required_file_path) { $current_file_analyzer->addRequiredFilePath($required_file_path); } $include_file_analyzer->clearSourceBeforeDestruction(); return \true; } $source = $statements_analyzer->getSource(); if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingFile('Cannot find file ' . $path_to_file . ' to include', new \Psalm\CodeLocation($source, $stmt)), $source->getSuppressedIssues())) { // fall through } } else { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->expr, null); if (!$var_id || !isset($context->phantom_files[$var_id])) { $source = $statements_analyzer->getSource(); if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnresolvableInclude('Cannot resolve the given expression to a file path', new \Psalm\CodeLocation($source, $stmt)), $source->getSuppressedIssues())) { // fall through } } } if ($config->skip_checks_on_unresolvable_includes) { $context->check_classes = \false; $context->check_variables = \false; $context->check_functions = \false; } return \true; } /** * @psalm-suppress MixedAssignment */ public static function getPathTo(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, ?\Psalm\Internal\Provider\NodeDataProvider $type_provider, ?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $file_name, \Psalm\Config $config) : ?string { if (\DIRECTORY_SEPARATOR === '/') { $is_path_relative = $file_name[0] !== \DIRECTORY_SEPARATOR; } else { $is_path_relative = !\preg_match('~^[A-Z]:\\\\~i', $file_name); } if ($is_path_relative) { $file_name = $config->base_dir . \DIRECTORY_SEPARATOR . $file_name; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if (\DIRECTORY_SEPARATOR !== '/') { return \str_replace('/', \DIRECTORY_SEPARATOR, $stmt->value); } return $stmt->value; } $stmt_type = $type_provider ? $type_provider->getType($stmt) : null; if ($stmt_type && $stmt_type->isSingleStringLiteral()) { if (\DIRECTORY_SEPARATOR !== '/') { return \str_replace('/', \DIRECTORY_SEPARATOR, $stmt_type->getSingleStringLiteral()->value); } return $stmt_type->getSingleStringLiteral()->value; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { if ($stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $stmt->var->name === 'GLOBALS' && $stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if (isset($GLOBALS[$stmt->dim->value]) && \is_string($GLOBALS[$stmt->dim->value])) { /** @var string */ return $GLOBALS[$stmt->dim->value]; } } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { $left_string = self::getPathTo($stmt->left, $type_provider, $statements_analyzer, $file_name, $config); $right_string = self::getPathTo($stmt->right, $type_provider, $statements_analyzer, $file_name, $config); if ($left_string && $right_string) { return $left_string . $right_string; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name->parts === ['dirname']) { if ($stmt->args) { $dir_level = 1; if (isset($stmt->args[1])) { if ($stmt->args[1]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $dir_level = $stmt->args[1]->value->value; } else { return null; } } $evaled_path = self::getPathTo($stmt->args[0]->value, $type_provider, $statements_analyzer, $file_name, $config); if (!$evaled_path) { return null; } return \dirname($evaled_path, $dir_level); } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { $const_name = \implode('', $stmt->name->parts); if (\defined($const_name)) { $constant_value = \constant($const_name); if (\is_string($constant_value)) { return $constant_value; } } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Dir) { return \dirname($file_name); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\File) { return $file_name; } return null; } public static function resolveIncludePath(string $file_name, string $current_directory) : ?string { if (!$current_directory) { return $file_name; } $paths = \PATH_SEPARATOR === ':' ? \preg_split('#(?parts as $part) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $part, $context) === \false) { return \false; } $part_type = $statements_analyzer->node_data->getType($part); if ($part_type) { $casted_part_type = \Psalm\Internal\Analyzer\Statements\Expression\CastAnalyzer::castStringAttempt($statements_analyzer, $context, $part_type, $part); if ($statements_analyzer->data_flow_graph && !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $var_location = new \Psalm\CodeLocation($statements_analyzer, $part); $new_parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment('concat', $var_location); $statements_analyzer->data_flow_graph->addNode($new_parent_node); $stmt_type->parent_nodes[$new_parent_node->id] = $new_parent_node; if ($casted_part_type->parent_nodes) { foreach ($casted_part_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $new_parent_node, 'concat'); } } } } } $statements_analyzer->node_data->setType($stmt, $stmt_type); return \true; } } getFQCLN(); $project_analyzer = $source->getFileAnalyzer()->project_analyzer; $codebase = $source->getCodebase(); if ($context->collect_mutations && $context->self && ($context->self === $fq_class_name || $codebase->classExtends($context->self, $fq_class_name))) { $method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, \strtolower($method_name)); if ((string) $method_id !== $source->getId()) { if ($context->collect_initializations) { if (isset($context->initialized_methods[(string) $method_id])) { return; } if ($context->initialized_methods === null) { $context->initialized_methods = []; } $context->initialized_methods[(string) $method_id] = \true; } $project_analyzer->getMethodMutations($method_id, $context, $source->getRootFilePath(), $source->getRootFileName()); } } elseif ($context->collect_initializations && $context->self && ($context->self === $fq_class_name || $codebase->classlikes->classExtends($context->self, $fq_class_name)) && $source->getMethodName() !== $method_name) { $method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, \strtolower($method_name)); $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if (isset($context->vars_in_scope['$this'])) { foreach ($context->vars_in_scope['$this']->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { if ($fq_class_name === $atomic_type->value) { $alt_declaring_method_id = $declaring_method_id; } else { $fq_class_name = $atomic_type->value; $method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, \strtolower($method_name)); $alt_declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); } if ($alt_declaring_method_id) { $declaring_method_id = $alt_declaring_method_id; break; } if (!$atomic_type->extra_types) { continue; } foreach ($atomic_type->extra_types as $intersection_type) { if ($intersection_type instanceof \Psalm\Type\Atomic\TNamedObject) { $fq_class_name = $intersection_type->value; $method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, \strtolower($method_name)); $alt_declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if ($alt_declaring_method_id) { $declaring_method_id = $alt_declaring_method_id; break 2; } } } } } } if (!$declaring_method_id) { // can happen for __call return; } if (isset($context->initialized_methods[(string) $declaring_method_id])) { return; } if ($context->initialized_methods === null) { $context->initialized_methods = []; } $context->initialized_methods[(string) $declaring_method_id] = \true; $method_storage = $codebase->methods->getStorage($declaring_method_id); $class_analyzer = $source->getSource(); $is_final = $method_storage->final; if ($method_name !== $declaring_method_id->method_name) { $appearing_method_id = $codebase->methods->getAppearingMethodId($method_id); if ($appearing_method_id) { $appearing_class_storage = $codebase->classlike_storage_provider->get($appearing_method_id->fq_class_name); if (isset($appearing_class_storage->trait_final_map[\strtolower($method_name)])) { $is_final = \true; } } } if ($class_analyzer instanceof \Psalm\Internal\Analyzer\ClassLikeAnalyzer && !$method_storage->is_static && ($context->collect_nonprivate_initializations || $method_storage->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE || $is_final)) { $local_vars_in_scope = []; $local_vars_possibly_in_scope = []; foreach ($context->vars_in_scope as $var => $_) { if (\strpos($var, '$this->') !== 0 && $var !== '$this') { $local_vars_in_scope[$var] = $context->vars_in_scope[$var]; } } foreach ($context->vars_possibly_in_scope as $var => $_) { if (\strpos($var, '$this->') !== 0 && $var !== '$this') { $local_vars_possibly_in_scope[$var] = $context->vars_possibly_in_scope[$var]; } } $old_calling_method_id = $context->calling_method_id; if ($fq_class_name === $source->getFQCLN()) { $class_analyzer->getMethodMutations($declaring_method_id->method_name, $context); } else { $declaring_fq_class_name = $declaring_method_id->fq_class_name; $old_self = $context->self; $context->self = $declaring_fq_class_name; $project_analyzer->getMethodMutations($declaring_method_id, $context, $source->getRootFilePath(), $source->getRootFileName()); $context->self = $old_self; } $context->calling_method_id = $old_calling_method_id; foreach ($local_vars_in_scope as $var => $type) { $context->vars_in_scope[$var] = $type; } foreach ($local_vars_possibly_in_scope as $var => $_) { $context->vars_possibly_in_scope[$var] = \true; } } } } /** * @param array $args */ public static function checkMethodArgs(?\Psalm\Internal\MethodIdentifier $method_id, array $args, ?\Psalm\Internal\Type\TemplateResult $class_template_result, \Psalm\Context $context, \Psalm\CodeLocation $code_location, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer) : bool { $codebase = $statements_analyzer->getCodebase(); if (!$method_id) { return \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $args, null, null, \true, $context, $class_template_result) !== \false; } $method_params = $codebase->methods->getMethodParams($method_id, $statements_analyzer, $args, $context); $fq_class_name = $method_id->fq_class_name; $method_name = $method_id->method_name; $fq_class_name = \strtolower($codebase->classlikes->getUnAliasedName($fq_class_name)); $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $method_storage = null; if (isset($class_storage->declaring_method_ids[$method_name])) { $declaring_method_id = $class_storage->declaring_method_ids[$method_name]; $declaring_fq_class_name = $declaring_method_id->fq_class_name; $declaring_method_name = $declaring_method_id->method_name; if ($declaring_fq_class_name !== $fq_class_name) { $declaring_class_storage = $codebase->classlike_storage_provider->get($declaring_fq_class_name); } else { $declaring_class_storage = $class_storage; } if (!isset($declaring_class_storage->methods[$declaring_method_name])) { throw new \UnexpectedValueException('Storage should not be empty here'); } $method_storage = $declaring_class_storage->methods[$declaring_method_name]; if ($declaring_class_storage->user_defined && !$method_storage->has_docblock_param_types && isset($declaring_class_storage->documenting_method_ids[$method_name])) { $documenting_method_id = $declaring_class_storage->documenting_method_ids[$method_name]; $documenting_method_storage = $codebase->methods->getStorage($documenting_method_id); if ($documenting_method_storage->template_types) { $method_storage = $documenting_method_storage; } } if (!$context->isSuppressingExceptions($statements_analyzer)) { $context->mergeFunctionExceptions($method_storage, $code_location); } } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $args, $method_params, (string) $method_id, $method_storage ? $method_storage->allow_named_arg_calls : \true, $context, $class_template_result) === \false) { return \false; } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::checkArgumentsMatch($statements_analyzer, $args, $method_id, $method_params, $method_storage, $class_storage, $class_template_result, $code_location, $context) === \false) { return \false; } if ($class_template_result) { self::checkTemplateResult($statements_analyzer, $class_template_result, $code_location, \strtolower((string) $method_id)); } return \true; } /** * @return array> * @param array> $existing_template_types */ public static function getTemplateTypesForCall(\Psalm\Codebase $codebase, ?\Psalm\Storage\ClassLikeStorage $declaring_class_storage, ?string $appearing_class_name, ?\Psalm\Storage\ClassLikeStorage $calling_class_storage, array $existing_template_types = []) : array { $template_types = $existing_template_types; if ($declaring_class_storage) { if ($calling_class_storage && $declaring_class_storage !== $calling_class_storage && $calling_class_storage->template_type_extends) { foreach ($calling_class_storage->template_type_extends as $class_name => $type_map) { foreach ($type_map as $template_name => $type) { if (\is_string($template_name) && $class_name === $declaring_class_storage->name) { $output_type = null; foreach ($type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam && isset($calling_class_storage->template_type_extends[$atomic_type->defining_class][$atomic_type->param_name])) { $output_type_candidate = $calling_class_storage->template_type_extends[$atomic_type->defining_class][$atomic_type->param_name]; } elseif ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $output_type_candidate = $atomic_type->as; } else { $output_type_candidate = new \Psalm\Type\Union([$atomic_type]); } if (!$output_type) { $output_type = $output_type_candidate; } else { $output_type = \Psalm\Type::combineUnionTypes($output_type_candidate, $output_type); } } $template_types[$template_name][$declaring_class_storage->name] = [$output_type]; } } } } elseif ($declaring_class_storage->template_types) { foreach ($declaring_class_storage->template_types as $template_name => $type_map) { foreach ($type_map as $key => [$type]) { $template_types[$template_name][$key] = [$type]; } } } } foreach ($template_types as $key => $type_map) { foreach ($type_map as $class => $type) { $template_types[$key][$class][0] = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $type[0], $appearing_class_name, $calling_class_storage ? $calling_class_storage->name : null, null, \true, \false, $calling_class_storage ? $calling_class_storage->final : \false); } } return $template_types; } /** * @param PhpParser\Node\Scalar\String_|PhpParser\Node\Expr\Array_|PhpParser\Node\Expr\BinaryOp\Concat * $callable_arg * * @return list * * @psalm-suppress LessSpecificReturnStatement * @psalm-suppress MoreSpecificReturnType */ public static function getFunctionIdsFromCallableArg(\Psalm\FileSource $file_source, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $callable_arg) : array { if ($callable_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { if ($callable_arg->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $callable_arg->left->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $callable_arg->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($callable_arg->left->name->name) === 'class' && !\in_array(\strtolower($callable_arg->left->class->parts[0]), ['self', 'static', 'parent']) && $callable_arg->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ && \preg_match('/^::[A-Za-z0-9]+$/', $callable_arg->right->value)) { return [(string) $callable_arg->left->class->getAttribute('resolvedName') . $callable_arg->right->value]; } return []; } if ($callable_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $potential_id = \preg_replace('/^\\\\/', '', $callable_arg->value); if (\preg_match('/^[A-Za-z0-9_]+(\\\\[A-Za-z0-9_]+)*(::[A-Za-z0-9_]+)?$/', $potential_id)) { return [$potential_id]; } return []; } if (\count($callable_arg->items) !== 2) { return []; } /** @psalm-suppress PossiblyNullPropertyFetch */ if ($callable_arg->items[0]->key || $callable_arg->items[1]->key) { return []; } if (!isset($callable_arg->items[0]) || !isset($callable_arg->items[1])) { throw new \UnexpectedValueException('These should never be unset'); } $class_arg = $callable_arg->items[0]->value; $method_name_arg = $callable_arg->items[1]->value; if (!$method_name_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { return []; } if ($class_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { return [\preg_replace('/^\\\\/', '', $class_arg->value) . '::' . $method_name_arg->value]; } if ($class_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $class_arg->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($class_arg->name->name) === 'class' && $class_arg->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $fq_class_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($class_arg->class, $file_source->getAliases()); return [$fq_class_name . '::' . $method_name_arg->value]; } if (!$file_source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer || !($class_arg_type = $file_source->node_data->getType($class_arg))) { return []; } $method_ids = []; foreach ($class_arg_type->getAtomicTypes() as $type_part) { if ($type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $method_id = $type_part->value . '::' . $method_name_arg->value; if ($type_part->extra_types) { foreach ($type_part->extra_types as $extra_type) { if ($extra_type instanceof \Psalm\Type\Atomic\TTemplateParam || $extra_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { throw new \UnexpectedValueException('Shouldn’t get a generic param here'); } $method_id .= '&' . $extra_type->value . '::' . $method_name_arg->value; } } $method_ids[] = '$' . $method_id; } } return $method_ids; } /** * @param non-empty-string $function_id * @param bool $can_be_in_root_scope if true, the function can be shortened to the root version * */ public static function checkFunctionExists(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string &$function_id, \Psalm\CodeLocation $code_location, bool $can_be_in_root_scope) : bool { $cased_function_id = $function_id; $function_id = \strtolower($function_id); $codebase = $statements_analyzer->getCodebase(); if (!$codebase->functions->functionExists($statements_analyzer, $function_id)) { /** @var non-empty-lowercase-string */ $root_function_id = \preg_replace('/.*\\\\/', '', $function_id); if ($can_be_in_root_scope && $function_id !== $root_function_id && $codebase->functions->functionExists($statements_analyzer, $root_function_id)) { $function_id = $root_function_id; } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedFunction('Function ' . $cased_function_id . ' does not exist', $code_location, $function_id), $statements_analyzer->getSuppressedIssues())) { // fall through } return \false; } } return \true; } /** * @param PhpParser\Node\Identifier|PhpParser\Node\Name $expr * @param \Psalm\Storage\Assertion[] $assertions * @param string $thisName * @param array $args * @param array> $template_type_map, * */ protected static function applyAssertionsToContext(\_HumbugBoxd02f763d3c56\PhpParser\NodeAbstract $expr, ?string $thisName, array $assertions, array $args, array $template_type_map, \Psalm\Context $context, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer) : void { $type_assertions = []; $asserted_keys = []; foreach ($assertions as $assertion) { $assertion_var_id = null; $arg_value = null; if (\is_int($assertion->var_id)) { if (!isset($args[$assertion->var_id])) { continue; } $arg_value = $args[$assertion->var_id]->value; $arg_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($arg_value, null, $statements_analyzer); if ($arg_var_id) { $assertion_var_id = $arg_var_id; } } elseif ($assertion->var_id === '$this' && $thisName !== null) { $assertion_var_id = $thisName; } elseif (\strpos($assertion->var_id, '$this->') === 0 && $thisName !== null) { $assertion_var_id = $thisName . \str_replace('$this->', '->', $assertion->var_id); } elseif (isset($context->vars_in_scope[$assertion->var_id])) { $assertion_var_id = $assertion->var_id; } if ($assertion_var_id) { $rule = $assertion->rule[0][0]; $prefix = ''; if ($rule[0] === '!') { $prefix .= '!'; $rule = \substr($rule, 1); } if ($rule[0] === '=') { $prefix .= '='; $rule = \substr($rule, 1); } if ($rule[0] === '~') { $prefix .= '~'; $rule = \substr($rule, 1); } if (isset($template_type_map[$rule])) { foreach ($template_type_map[$rule] as $template_map) { if ($template_map[0]->hasMixed()) { continue 2; } $replacement_atomic_types = $template_map[0]->getAtomicTypes(); if (\count($replacement_atomic_types) > 1) { continue 2; } $ored_type_assertions = []; foreach ($replacement_atomic_types as $replacement_atomic_type) { if ($replacement_atomic_type instanceof \Psalm\Type\Atomic\TMixed) { continue 3; } if ($replacement_atomic_type instanceof \Psalm\Type\Atomic\TArray || $replacement_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $ored_type_assertions[] = $prefix . 'array'; } elseif ($replacement_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $ored_type_assertions[] = $prefix . $replacement_atomic_type->value; } elseif ($replacement_atomic_type instanceof \Psalm\Type\Atomic\Scalar) { $ored_type_assertions[] = $prefix . $replacement_atomic_type->getId(); } elseif ($replacement_atomic_type instanceof \Psalm\Type\Atomic\TNull) { $ored_type_assertions[] = $prefix . 'null'; } elseif ($replacement_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $ored_type_assertions[] = $prefix . $replacement_atomic_type->param_name; } } if ($ored_type_assertions) { $type_assertions[$assertion_var_id] = [$ored_type_assertions]; } } } else { if (isset($type_assertions[$assertion_var_id])) { $type_assertions[$assertion_var_id] = \array_merge($type_assertions[$assertion_var_id], $assertion->rule); } else { $type_assertions[$assertion_var_id] = $assertion->rule; } } } elseif ($arg_value && ($assertion->rule === [['!falsy']] || $assertion->rule === [['true']])) { if ($assertion->rule === [['true']]) { $conditional = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical($arg_value, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('true'))); $assert_clauses = \Psalm\Type\Algebra::getFormula(\mt_rand(0, 1000000), \mt_rand(0, 1000000), $conditional, $context->self, $statements_analyzer, $statements_analyzer->getCodebase()); } else { $assert_clauses = \Psalm\Type\Algebra::getFormula(\spl_object_id($arg_value), \spl_object_id($arg_value), $arg_value, $context->self, $statements_analyzer, $statements_analyzer->getCodebase()); } $simplified_clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($context->clauses, $assert_clauses)); $assert_type_assertions = \Psalm\Type\Algebra::getTruthsFromFormula($simplified_clauses); $type_assertions = \array_merge($type_assertions, $assert_type_assertions); } elseif ($arg_value && $assertion->rule === [['falsy']]) { $assert_clauses = \Psalm\Type\Algebra::negateFormula(\Psalm\Type\Algebra::getFormula(\spl_object_id($arg_value), \spl_object_id($arg_value), $arg_value, $context->self, $statements_analyzer, $statements_analyzer->getCodebase())); $simplified_clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($context->clauses, $assert_clauses)); $assert_type_assertions = \Psalm\Type\Algebra::getTruthsFromFormula($simplified_clauses); $type_assertions = \array_merge($type_assertions, $assert_type_assertions); } } $changed_var_ids = []; foreach ($type_assertions as $var_id => $_) { $asserted_keys[$var_id] = \true; } if ($type_assertions) { foreach ($statements_analyzer->getTemplateTypeMap() ?: [] as $template_name => $map) { foreach ($map as $ref => [$type]) { $template_type_map[$template_name][$ref] = [new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParam($template_name, $type, $ref)])]; } } // while in an and, we allow scope to boil over to support // statements of the form if ($x && $x->foo()) $op_vars_in_scope = \Psalm\Type\Reconciler::reconcileKeyedTypes($type_assertions, $type_assertions, $context->vars_in_scope, $changed_var_ids, $asserted_keys, $statements_analyzer, $template_type_map, $context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $expr)); foreach ($changed_var_ids as $var_id => $_) { if (isset($op_vars_in_scope[$var_id])) { $first_appearance = $statements_analyzer->getFirstAppearance($var_id); $codebase = $statements_analyzer->getCodebase(); if ($first_appearance && isset($context->vars_in_scope[$var_id]) && $context->vars_in_scope[$var_id]->hasMixed()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->decrementMixedCount($statements_analyzer->getFilePath()); } \Psalm\IssueBuffer::remove($statements_analyzer->getFilePath(), 'MixedAssignment', $first_appearance->raw_file_start); } $op_vars_in_scope[$var_id]->from_docblock = \true; foreach ($op_vars_in_scope[$var_id]->getAtomicTypes() as $changed_atomic_type) { $changed_atomic_type->from_docblock = \true; if ($changed_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject && $changed_atomic_type->extra_types) { foreach ($changed_atomic_type->extra_types as $extra_type) { $extra_type->from_docblock = \true; } } } } } $context->vars_in_scope = $op_vars_in_scope; } } public static function checkTemplateResult(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Internal\Type\TemplateResult $template_result, \Psalm\CodeLocation $code_location, ?string $function_id) : void { if ($template_result->upper_bounds && $template_result->lower_bounds) { foreach ($template_result->lower_bounds as $template_name => $defining_map) { foreach ($defining_map as $defining_id => [$lower_bound_type]) { if (isset($template_result->upper_bounds[$template_name][$defining_id])) { $upper_bound_type = $template_result->upper_bounds[$template_name][$defining_id][0]; $union_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (\count($template_result->lower_bounds_unintersectable_types) > 1) { [$upper_bound_type, $lower_bound_type] = $template_result->lower_bounds_unintersectable_types; } if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($statements_analyzer->getCodebase(), $upper_bound_type, $lower_bound_type, \false, \false, $union_comparison_result)) { if ($union_comparison_result->type_coerced) { if ($union_comparison_result->type_coerced_from_mixed) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArgumentTypeCoercion('Type ' . $upper_bound_type->getId() . ' should be a subtype of ' . $lower_bound_type->getId(), $code_location, $function_id), $statements_analyzer->getSuppressedIssues())) { // continue } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ArgumentTypeCoercion('Type ' . $upper_bound_type->getId() . ' should be a subtype of ' . $lower_bound_type->getId(), $code_location, $function_id), $statements_analyzer->getSuppressedIssues())) { // continue } } } elseif ($union_comparison_result->scalar_type_match_found) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidScalarArgument('Type ' . $upper_bound_type->getId() . ' should be a subtype of ' . $lower_bound_type->getId(), $code_location, $function_id), $statements_analyzer->getSuppressedIssues())) { // continue } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArgument('Type ' . $upper_bound_type->getId() . ' should be a subtype of ' . $lower_bound_type->getId(), $code_location, $function_id), $statements_analyzer->getSuppressedIssues())) { // continue } } } } else { $template_result->upper_bounds[$template_name][$defining_id][0] = clone $lower_bound_type; } } } } } } 100) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getString()); // ignore deeply-nested string concatenation return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd) { $was_inside_use = $context->inside_use; $context->inside_use = \true; $expr_result = \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\AndAnalyzer::analyze($statements_analyzer, $stmt, $context, $from_stmt); $context->inside_use = $was_inside_use; $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getBool()); return $expr_result; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr) { $was_inside_use = $context->inside_use; $context->inside_use = \true; $expr_result = \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\OrAnalyzer::analyze($statements_analyzer, $stmt, $context, $from_stmt); $context->inside_use = $was_inside_use; $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getBool()); return $expr_result; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce) { $expr_result = \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\CoalesceAnalyzer::analyze($statements_analyzer, $stmt, $context); self::addDataFlow($statements_analyzer, $stmt, $stmt->left, $stmt->right, 'coalesce'); return $expr_result; } if ($stmt->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp) { if (self::analyze($statements_analyzer, $stmt->left, $context, $nesting + 1) === \false) { return \false; } } else { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->left, $context) === \false) { return \false; } } if ($stmt->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp) { if (self::analyze($statements_analyzer, $stmt->right, $context, $nesting + 1) === \false) { return \false; } } else { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->right, $context) === \false) { return \false; } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { $stmt_type = \Psalm\Type::getString(); \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\ConcatAnalyzer::analyze($statements_analyzer, $stmt->left, $stmt->right, $context, $result_type); if ($result_type) { $stmt_type = $result_type; } if ($statements_analyzer->data_flow_graph && ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph || !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues()))) { $stmt_left_type = $statements_analyzer->node_data->getType($stmt->left); $stmt_right_type = $statements_analyzer->node_data->getType($stmt->right); $var_location = new \Psalm\CodeLocation($statements_analyzer, $stmt); $new_parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment('concat', $var_location); $statements_analyzer->data_flow_graph->addNode($new_parent_node); $stmt_type->parent_nodes = [$new_parent_node->id => $new_parent_node]; if ($stmt_left_type && $stmt_left_type->parent_nodes) { foreach ($stmt_left_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $new_parent_node, 'concat'); } } if ($stmt_right_type && $stmt_right_type->parent_nodes) { foreach ($stmt_right_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $new_parent_node, 'concat'); } } } $statements_analyzer->node_data->setType($stmt, $stmt_type); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Spaceship) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getInt()); self::addDataFlow($statements_analyzer, $stmt, $stmt->left, $stmt->right, '<=>'); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getBool()); $stmt_left_type = $statements_analyzer->node_data->getType($stmt->left); $stmt_right_type = $statements_analyzer->node_data->getType($stmt->right); if (($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual) && $statements_analyzer->getCodebase()->config->strict_binary_operands && $stmt_left_type && $stmt_right_type && ($stmt_left_type->isSingle() && $stmt_left_type->hasBool() || $stmt_right_type->isSingle() && $stmt_right_type->hasBool())) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidOperand('Cannot compare ' . $stmt_left_type->getId() . ' to ' . $stmt_right_type->getId(), new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if (($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) && $stmt->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $stmt->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->left->name->parts === ['substr'] && isset($stmt->left->args[1]) && $stmt_right_type && $stmt_right_type->hasLiteralString()) { $from_type = $statements_analyzer->node_data->getType($stmt->left->args[1]->value); $length_type = isset($stmt->left->args[2]) ? $statements_analyzer->node_data->getType($stmt->left->args[2]->value) ?: \Psalm\Type::getMixed() : null; $string_length = null; if ($from_type && $from_type->isSingleIntLiteral() && $length_type === null) { $string_length = -$from_type->getSingleIntLiteral()->value; } elseif ($length_type && $length_type->isSingleIntLiteral()) { $string_length = $length_type->getSingleIntLiteral()->value; } if ($string_length > 0) { foreach ($stmt_right_type->getAtomicTypes() as $atomic_right_type) { if ($atomic_right_type instanceof \Psalm\Type\Atomic\TLiteralString) { if (\strlen($atomic_right_type->value) !== $string_length) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { if ($atomic_right_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($atomic_right_type . ' string length is not ' . $string_length, new \Psalm\CodeLocation($statements_analyzer, $stmt), null), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType($atomic_right_type . ' string length is not ' . $string_length, new \Psalm\CodeLocation($statements_analyzer, $stmt), null), $statements_analyzer->getSuppressedIssues())) { // fall through } } } else { if ($atomic_right_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType($atomic_right_type . ' string length is never ' . $string_length, new \Psalm\CodeLocation($statements_analyzer, $stmt), null), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition($atomic_right_type . ' string length is never ' . $string_length, new \Psalm\CodeLocation($statements_analyzer, $stmt), null), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } } } } } $codebase = $statements_analyzer->getCodebase(); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal && $stmt_left_type && $stmt_right_type && ($context->mutation_free || $codebase->alter_code)) { self::checkForImpureEqualityComparison($statements_analyzer, $stmt, $stmt_left_type, $stmt_right_type); } self::addDataFlow($statements_analyzer, $stmt, $stmt->left, $stmt->right, 'comparison'); return \true; } \Psalm\Internal\Analyzer\Statements\Expression\BinaryOp\NonComparisonOpAnalyzer::analyze($statements_analyzer, $stmt, $context); return \true; } public static function addDataFlow(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $left, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $right, string $type = 'binaryop') : void { if ($stmt->getLine() === -1) { throw new \UnexpectedValueException('bad'); } $result_type = $statements_analyzer->node_data->getType($stmt); if ($statements_analyzer->data_flow_graph && $result_type) { $stmt_left_type = $statements_analyzer->node_data->getType($left); $stmt_right_type = $statements_analyzer->node_data->getType($right); $var_location = new \Psalm\CodeLocation($statements_analyzer, $stmt); $new_parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($type, $var_location); $statements_analyzer->data_flow_graph->addNode($new_parent_node); $result_type->parent_nodes = [$new_parent_node->id => $new_parent_node]; if ($stmt_left_type && $stmt_left_type->parent_nodes) { foreach ($stmt_left_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $new_parent_node, $type); } } if ($stmt_right_type && $stmt_right_type->parent_nodes) { foreach ($stmt_right_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $new_parent_node, $type); } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp && $statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph) { $root_expr = $left; while ($root_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { $root_expr = $root_expr->var; } if ($left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch) { $statements_analyzer->data_flow_graph->addPath($new_parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'used-by-instance-property'); } if ($left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch) { $statements_analyzer->data_flow_graph->addPath($new_parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'use-in-static-property'); } elseif (!$left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { $statements_analyzer->data_flow_graph->addPath($new_parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'variable-use'); } } } } private static function checkForImpureEqualityComparison(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal $stmt, \Psalm\Type\Union $stmt_left_type, \Psalm\Type\Union $stmt_right_type) : void { $codebase = $statements_analyzer->getCodebase(); if ($stmt_left_type->hasString() && $stmt_right_type->hasObjectType()) { foreach ($stmt_right_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { try { $storage = $codebase->methods->getStorage(new \Psalm\Internal\MethodIdentifier($atomic_type->value, '__tostring')); } catch (\UnexpectedValueException $e) { continue; } if (!$storage->mutation_free) { if ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call a possibly-mutating method ' . $atomic_type->value . '::__toString from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } } } elseif ($stmt_right_type->hasString() && $stmt_left_type->hasObjectType()) { foreach ($stmt_left_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { try { $storage = $codebase->methods->getStorage(new \Psalm\Internal\MethodIdentifier($atomic_type->value, '__tostring')); } catch (\UnexpectedValueException $e) { continue; } if (!$storage->mutation_free) { if ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call a possibly-mutating method ' . $atomic_type->value . '::__toString from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } } } } } inside_call; $context->inside_call = \true; $was_inside_use = $context->inside_use; $context->inside_use = \true; $existing_stmt_var_type = null; if (!$real_method_call) { $existing_stmt_var_type = $statements_analyzer->node_data->getType($stmt->var); } if ($existing_stmt_var_type) { $statements_analyzer->node_data->setType($stmt->var, $existing_stmt_var_type); } elseif (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === \false) { return \false; } $context->inside_call = $was_inside_call; if (!$stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->name, $context) === \false) { return \false; } } $context->inside_call = $was_inside_call; $context->inside_use = $was_inside_use; if ($stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { if (\is_string($stmt->var->name) && $stmt->var->name === 'this' && !$statements_analyzer->getFQCLN()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidScope('Use of $this in non-class context', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } } } $lhs_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->var, $statements_analyzer->getFQCLN(), $statements_analyzer); $class_type = $lhs_var_id && $context->hasVariable($lhs_var_id) ? $context->vars_in_scope[$lhs_var_id] : null; if ($stmt_var_type = $statements_analyzer->node_data->getType($stmt->var)) { $class_type = $stmt_var_type; } elseif (!$class_type) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } if (!$context->check_classes) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context) === \false) { return \false; } return \true; } if ($class_type && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && ($class_type->isNull() || $class_type->isVoid())) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullReference('Cannot call method ' . $stmt->name->name . ' on null value', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->name)), $statements_analyzer->getSuppressedIssues())) { return \false; } return \true; } if ($class_type && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $class_type->isNullable() && !$class_type->ignore_nullable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullReference('Cannot call method ' . $stmt->name->name . ' on possibly null value', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($class_type && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $class_type->isFalsable() && !$class_type->ignore_falsable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyFalseReference('Cannot call method ' . $stmt->name->name . ' on possibly false value', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $codebase = $statements_analyzer->getCodebase(); $source = $statements_analyzer->getSource(); if (!$class_type) { $class_type = \Psalm\Type::getMixed(); } $lhs_types = $class_type->getAtomicTypes(); $result = new \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\AtomicMethodCallAnalysisResult(); $possible_new_class_types = []; foreach ($lhs_types as $lhs_type_part) { \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\AtomicMethodCallAnalyzer::analyze($statements_analyzer, $stmt, $codebase, $context, $lhs_type_part, $lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject || $lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParam ? $lhs_type_part : null, \false, $lhs_var_id, $result); if (isset($context->vars_in_scope[$lhs_var_id]) && ($possible_new_class_type = $context->vars_in_scope[$lhs_var_id]) instanceof \Psalm\Type\Union && !$possible_new_class_type->equals($class_type)) { $possible_new_class_types[] = $context->vars_in_scope[$lhs_var_id]; } } if (\count($possible_new_class_types) > 0) { $class_type = \array_reduce($possible_new_class_types, function (?\Psalm\Type\Union $type_1, \Psalm\Type\Union $type_2) use($codebase) : Type\Union { if ($type_1 === null) { return $type_2; } return \Psalm\Type::combineUnionTypes($type_1, $type_2, $codebase); }); } if ($result->invalid_method_call_types) { $invalid_class_type = $result->invalid_method_call_types[0]; if ($result->has_valid_method_call_type || $result->has_mixed_method_call) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidMethodCall('Cannot call method on possible ' . $invalid_class_type . ' variable ' . $lhs_var_id, new \Psalm\CodeLocation($source, $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // keep going } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidMethodCall('Cannot call method on ' . $invalid_class_type . ' variable ' . $lhs_var_id, new \Psalm\CodeLocation($source, $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // keep going } } } if ($result->non_existent_magic_method_ids) { if ($context->check_methods) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedMagicMethod('Magic method ' . $result->non_existent_magic_method_ids[0] . ' does not exist', new \Psalm\CodeLocation($source, $stmt->name), $result->non_existent_magic_method_ids[0]), $statements_analyzer->getSuppressedIssues())) { // keep going } } } if ($result->non_existent_class_method_ids) { if ($context->check_methods) { if ($result->existent_method_ids || $result->has_mixed_method_call) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedMethod('Method ' . $result->non_existent_class_method_ids[0] . ' does not exist', new \Psalm\CodeLocation($source, $stmt->name), $result->non_existent_class_method_ids[0]), $statements_analyzer->getSuppressedIssues())) { // keep going } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedMethod('Method ' . $result->non_existent_class_method_ids[0] . ' does not exist', new \Psalm\CodeLocation($source, $stmt->name), $result->non_existent_class_method_ids[0]), $statements_analyzer->getSuppressedIssues())) { // keep going } } } return \true; } if ($result->non_existent_interface_method_ids) { if ($context->check_methods) { if ($result->existent_method_ids || $result->has_mixed_method_call) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedMethod('Method ' . $result->non_existent_interface_method_ids[0] . ' does not exist', new \Psalm\CodeLocation($source, $stmt->name), $result->non_existent_interface_method_ids[0]), $statements_analyzer->getSuppressedIssues())) { // keep going } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedInterfaceMethod('Method ' . $result->non_existent_interface_method_ids[0] . ' does not exist', new \Psalm\CodeLocation($source, $stmt->name), $result->non_existent_interface_method_ids[0]), $statements_analyzer->getSuppressedIssues())) { // keep going } } } return \true; } if ($result->too_many_arguments && $result->too_many_arguments_method_ids) { $error_method_id = $result->too_many_arguments_method_ids[0]; if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooManyArguments('Too many arguments for method ' . $error_method_id . ' - saw ' . \count($stmt->args), new \Psalm\CodeLocation($source, $stmt->name), (string) $error_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($result->too_few_arguments && $result->too_few_arguments_method_ids) { $error_method_id = $result->too_few_arguments_method_ids[0]; if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooFewArguments('Too few arguments for method ' . $error_method_id . ' saw ' . \count($stmt->args), new \Psalm\CodeLocation($source, $stmt->name), (string) $error_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } $stmt_type = $result->return_type; if ($stmt_type) { $statements_analyzer->node_data->setType($stmt, $stmt_type); } if ($result->returns_by_ref) { if (!$stmt_type) { $stmt_type = \Psalm\Type::getMixed(); $statements_analyzer->node_data->setType($stmt, $stmt_type); } $stmt_type->by_ref = $result->returns_by_ref; } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations && $stmt_type) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt->name, $stmt_type->getId(), $stmt); } if (!$result->existent_method_ids) { return self::checkMethodArgs(null, $stmt->args, null, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer); } // if we called a method on this nullable variable, remove the nullable status here // because any further calls must have worked if ($lhs_var_id && !$class_type->isMixed() && $result->has_valid_method_call_type && !$result->has_mixed_method_call && !$result->invalid_method_call_types && ($class_type->from_docblock || $class_type->isNullable()) && $real_method_call) { $keys_to_remove = []; $class_type = clone $class_type; foreach ($class_type->getAtomicTypes() as $key => $type) { if (!$type instanceof \Psalm\Type\Atomic\TNamedObject) { $keys_to_remove[] = $key; } else { $type->from_docblock = \false; } } foreach ($keys_to_remove as $key) { $class_type->removeType($key); } $class_type->from_docblock = \false; $context->removeVarFromConflictingClauses($lhs_var_id, null, $statements_analyzer); $context->vars_in_scope[$lhs_var_id] = $class_type; } if ($lhs_var_id) { // TODO: Always defined? Always correct? $method_id = $result->existent_method_ids[0]; if ($method_id instanceof \Psalm\Internal\MethodIdentifier) { // TODO: When should a method have a storage? if ($codebase->methods->hasStorage($method_id)) { $storage = $codebase->methods->getStorage($method_id); if ($storage->self_out_type) { $self_out_type = $storage->self_out_type; $context->vars_in_scope[$lhs_var_id] = $self_out_type; } } } else { // TODO: When is method_id a string? } } return \true; } } $args */ public static function checkArgumentsMatch(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Context $context, array $args, string $method_id, bool $check_functions) : void { $closure_index = $method_id === 'array_map' ? 0 : 1; $array_arg_types = []; foreach ($args as $i => $arg) { if ($i === 0 && $method_id === 'array_map') { continue; } if ($i === 1 && $method_id === 'array_filter') { break; } /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var TKeyedArray|TArray|TList|null */ $array_arg_type = ($arg_value_type = $statements_analyzer->node_data->getType($arg->value)) && ($types = $arg_value_type->getAtomicTypes()) && isset($types['array']) ? $types['array'] : null; if ($array_arg_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $array_arg_type = $array_arg_type->getGenericArrayType(); } if ($array_arg_type instanceof \Psalm\Type\Atomic\TList) { $array_arg_type = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $array_arg_type->type_param]); } $array_arg_types[] = $array_arg_type; } $closure_arg = isset($args[$closure_index]) ? $args[$closure_index] : null; $closure_arg_type = null; if ($closure_arg) { $closure_arg_type = $statements_analyzer->node_data->getType($closure_arg->value); } if ($closure_arg && $closure_arg_type) { $min_closure_param_count = $max_closure_param_count = \count($array_arg_types); if ($method_id === 'array_filter') { $max_closure_param_count = \count($args) > 2 ? 2 : 1; } foreach ($closure_arg_type->getAtomicTypes() as $closure_type) { self::checkClosureType($statements_analyzer, $context, $method_id, $closure_type, $closure_arg, $min_closure_param_count, $max_closure_param_count, $array_arg_types, $check_functions); } } } /** * @param array $args * * @return false|null */ public static function handleAddition(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, array $args, \Psalm\Context $context, bool $is_push) : ?bool { $array_arg = $args[0]->value; $unpacked_args = \array_filter($args, function ($arg) { return $arg->unpack; }); if ($is_push && !$unpacked_args) { for ($i = 1, $iMax = \count($args); $i < $iMax; $i++) { $was_inside_assignment = $context->inside_assignment; $context->inside_assignment = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $args[$i]->value, $context) === \false) { return \false; } $context->inside_assignment = $was_inside_assignment; $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; \Psalm\Internal\Analyzer\Statements\Expression\Assignment\ArrayAssignmentAnalyzer::analyze($statements_analyzer, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch($args[0]->value, null, $args[$i]->value->getAttributes()), $context, $args[$i]->value, $statements_analyzer->node_data->getType($args[$i]->value) ?: \Psalm\Type::getMixed()); $statements_analyzer->node_data = $old_node_data; } return null; } $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $array_arg, $context) === \false) { return \false; } for ($i = 1, $iMax = \count($args); $i < $iMax; $i++) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $args[$i]->value, $context) === \false) { return \false; } } if (($array_arg_type = $statements_analyzer->node_data->getType($array_arg)) && $array_arg_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var TArray|TKeyedArray|TList */ $array_type = $array_arg_type->getAtomicTypes()['array']; $objectlike_list = null; if ($array_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($array_type->is_list) { $objectlike_list = clone $array_type; } $array_type = $array_type->getGenericArrayType(); if ($objectlike_list) { if ($array_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $array_type = new \Psalm\Type\Atomic\TNonEmptyList($array_type->type_params[1]); } else { $array_type = new \Psalm\Type\Atomic\TList($array_type->type_params[1]); } } } $by_ref_type = new \Psalm\Type\Union([clone $array_type]); foreach ($args as $argument_offset => $arg) { if ($argument_offset === 0) { continue; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $arg->value, $context) === \false) { return \false; } if (!($arg_value_type = $statements_analyzer->node_data->getType($arg->value)) || $arg_value_type->hasMixed()) { $by_ref_type = \Psalm\Type::combineUnionTypes($by_ref_type, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), \Psalm\Type::getMixed()])])); } elseif ($arg->unpack) { $arg_value_type = clone $arg_value_type; foreach ($arg_value_type->getAtomicTypes() as $arg_value_atomic_type) { if ($arg_value_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $was_list = $arg_value_atomic_type->is_list; $arg_value_atomic_type = $arg_value_atomic_type->getGenericArrayType(); if ($was_list) { if ($arg_value_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $arg_value_atomic_type = new \Psalm\Type\Atomic\TNonEmptyList($arg_value_atomic_type->type_params[1]); } else { $arg_value_atomic_type = new \Psalm\Type\Atomic\TList($arg_value_atomic_type->type_params[1]); } } $arg_value_type->addType($arg_value_atomic_type); } } $by_ref_type = \Psalm\Type::combineUnionTypes($by_ref_type, $arg_value_type); } else { if ($objectlike_list) { \array_unshift($objectlike_list->properties, $arg_value_type); $by_ref_type = new \Psalm\Type\Union([$objectlike_list]); } elseif ($array_type instanceof \Psalm\Type\Atomic\TList) { $by_ref_type = \Psalm\Type::combineUnionTypes($by_ref_type, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyList(clone $arg_value_type)])); } else { $by_ref_type = \Psalm\Type::combineUnionTypes($by_ref_type, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyArray([\Psalm\Type::getInt(), clone $arg_value_type])])); } } } \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::assignByRefParam($statements_analyzer, $array_arg, $by_ref_type, $by_ref_type, $context, \false); } $context->inside_call = \false; return null; } /** * @param array $args * * @return false|null */ public static function handleSplice(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, array $args, \Psalm\Context $context) : ?bool { $context->inside_call = \true; $array_arg = $args[0]->value; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $array_arg, $context) === \false) { return \false; } $offset_arg = $args[1]->value; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $offset_arg, $context) === \false) { return \false; } if (!isset($args[2])) { return null; } $length_arg = $args[2]->value; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $length_arg, $context) === \false) { return \false; } if (!isset($args[3])) { return null; } $replacement_arg = $args[3]->value; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $replacement_arg, $context) === \false) { return \false; } $context->inside_call = \false; $replacement_arg_type = $statements_analyzer->node_data->getType($replacement_arg); if ($replacement_arg_type && !$replacement_arg_type->hasArray() && $replacement_arg_type->hasString() && $replacement_arg_type->isSingle()) { $replacement_arg_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $replacement_arg_type])]); $statements_analyzer->node_data->setType($replacement_arg, $replacement_arg_type); } if (($array_arg_type = $statements_analyzer->node_data->getType($array_arg)) && $array_arg_type->hasArray() && $replacement_arg_type && $replacement_arg_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var TArray|TKeyedArray|TList */ $array_type = $array_arg_type->getAtomicTypes()['array']; if ($array_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($array_type->is_list) { $array_type = new \Psalm\Type\Atomic\TNonEmptyList($array_type->getGenericValueType()); } else { $array_type = $array_type->getGenericArrayType(); } } if ($array_type instanceof \Psalm\Type\Atomic\TArray && $array_type->type_params[0]->hasInt() && !$array_type->type_params[0]->hasString()) { if ($array_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $array_type = new \Psalm\Type\Atomic\TNonEmptyList($array_type->type_params[1]); } else { $array_type = new \Psalm\Type\Atomic\TList($array_type->type_params[1]); } } /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var TArray|TKeyedArray|TList */ $replacement_array_type = $replacement_arg_type->getAtomicTypes()['array']; if ($replacement_array_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $was_list = $replacement_array_type->is_list; $replacement_array_type = $replacement_array_type->getGenericArrayType(); if ($was_list) { if ($replacement_array_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $replacement_array_type = new \Psalm\Type\Atomic\TNonEmptyList($replacement_array_type->type_params[1]); } else { $replacement_array_type = new \Psalm\Type\Atomic\TList($replacement_array_type->type_params[1]); } } } $by_ref_type = \Psalm\Internal\Type\TypeCombination::combineTypes([$array_type, $replacement_array_type]); \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::assignByRefParam($statements_analyzer, $array_arg, $by_ref_type, $by_ref_type, $context, \false); return null; } $array_type = \Psalm\Type::getArray(); \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::assignByRefParam($statements_analyzer, $array_arg, $array_type, $array_type, $context, \false); return null; } public static function handleByRefArrayAdjustment(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg, \Psalm\Context $context, bool $is_array_shift) : void { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($arg->value, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($var_id) { $context->removeVarFromConflictingClauses($var_id, null, $statements_analyzer); if (isset($context->vars_in_scope[$var_id])) { $array_type = clone $context->vars_in_scope[$var_id]; $array_atomic_types = $array_type->getAtomicTypes(); foreach ($array_atomic_types as $array_atomic_type) { if ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($is_array_shift && $array_atomic_type->is_list) { $array_atomic_type = clone $array_atomic_type; $array_properties = $array_atomic_type->properties; \array_shift($array_properties); if (!$array_properties) { $array_atomic_type = new \Psalm\Type\Atomic\TList($array_atomic_type->previous_value_type ?: \Psalm\Type::getMixed()); $array_type->addType($array_atomic_type); } else { $array_atomic_type->properties = $array_properties; } } if ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $array_atomic_type = $array_atomic_type->getGenericArrayType(); } } if ($array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { if (!$context->inside_loop && $array_atomic_type->count !== null) { if ($array_atomic_type->count === 0) { $array_atomic_type = new \Psalm\Type\Atomic\TArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()])]); } else { $array_atomic_type->count--; } } else { $array_atomic_type = new \Psalm\Type\Atomic\TArray($array_atomic_type->type_params); } $array_type->addType($array_atomic_type); $context->removeDescendents($var_id, $array_type); } elseif ($array_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyList) { if (!$context->inside_loop && $array_atomic_type->count !== null) { if ($array_atomic_type->count === 0) { $array_atomic_type = new \Psalm\Type\Atomic\TArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()])]); } else { $array_atomic_type->count--; } } else { $array_atomic_type = new \Psalm\Type\Atomic\TList($array_atomic_type->type_param); } $array_type->addType($array_atomic_type); $context->removeDescendents($var_id, $array_type); } } $context->vars_in_scope[$var_id] = $array_type; } } } /** * @param (TArray|null)[] $array_arg_types * */ private static function checkClosureType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Context $context, string $method_id, \Psalm\Type\Atomic $closure_type, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $closure_arg, int $min_closure_param_count, int $max_closure_param_count, array $array_arg_types, bool $check_functions) : void { $codebase = $statements_analyzer->getCodebase(); if (!$closure_type instanceof \Psalm\Type\Atomic\TClosure) { if ($method_id === 'array_map') { return; } if (!$closure_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ && !$closure_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ && !$closure_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { return; } $function_ids = \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::getFunctionIdsFromCallableArg($statements_analyzer, $closure_arg->value); $closure_types = []; foreach ($function_ids as $function_id) { $function_id = \strtolower($function_id); if (\strpos($function_id, '::') !== \false) { if ($function_id[0] === '$') { $function_id = \substr($function_id, 1); } $function_id_parts = \explode('&', $function_id); foreach ($function_id_parts as $function_id_part) { [$callable_fq_class_name, $method_name] = \explode('::', $function_id_part); switch ($callable_fq_class_name) { case 'self': case 'static': case 'parent': $container_class = $statements_analyzer->getFQCLN(); if ($callable_fq_class_name === 'parent') { $container_class = $statements_analyzer->getParentFQCLN(); } if (!$container_class) { continue 2; } $callable_fq_class_name = $container_class; } if (!$codebase->classOrInterfaceExists($callable_fq_class_name)) { return; } $function_id_part = new \Psalm\Internal\MethodIdentifier($callable_fq_class_name, \strtolower($method_name)); try { $method_storage = $codebase->methods->getStorage($function_id_part); } catch (\UnexpectedValueException $e) { // the method may not exist, but we're suppressing that issue continue; } $closure_types[] = new \Psalm\Type\Atomic\TClosure('Closure', $method_storage->params, $method_storage->return_type ?: \Psalm\Type::getMixed()); } } else { if (!$check_functions) { continue; } if (!$codebase->functions->functionExists($statements_analyzer, $function_id)) { continue; } $function_storage = $codebase->functions->getStorage($statements_analyzer, $function_id); if (\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($function_id)) { $callmap_callables = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallablesFromCallMap($function_id); if ($callmap_callables === null) { throw new \UnexpectedValueException('This should not happen'); } $passing_callmap_callables = []; foreach ($callmap_callables as $callmap_callable) { $required_param_count = 0; \assert($callmap_callable->params !== null); foreach ($callmap_callable->params as $i => $param) { if (!$param->is_optional && !$param->is_variadic) { $required_param_count = $i + 1; } } if ($required_param_count <= $max_closure_param_count) { $passing_callmap_callables[] = $callmap_callable; } } if ($passing_callmap_callables) { foreach ($passing_callmap_callables as $passing_callmap_callable) { $closure_types[] = $passing_callmap_callable; } } else { $closure_types[] = $callmap_callables[0]; } } else { $closure_types[] = new \Psalm\Type\Atomic\TClosure('Closure', $function_storage->params, $function_storage->return_type ?: \Psalm\Type::getMixed()); } } } } else { $closure_types = [$closure_type]; } foreach ($closure_types as $closure_type) { if ($closure_type->params === null) { continue; } self::checkClosureTypeArgs($statements_analyzer, $context, $method_id, $closure_type, $closure_arg, $min_closure_param_count, $max_closure_param_count, $array_arg_types); } } /** * @param Type\Atomic\TClosure|Type\Atomic\TCallable $closure_type * @param (TArray|null)[] $array_arg_types */ private static function checkClosureTypeArgs(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Context $context, string $method_id, \Psalm\Type\Atomic $closure_type, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $closure_arg, int $min_closure_param_count, int $max_closure_param_count, array $array_arg_types) : void { $codebase = $statements_analyzer->getCodebase(); $closure_params = $closure_type->params; if ($closure_params === null) { throw new \UnexpectedValueException('Closure params should not be null here'); } $required_param_count = 0; foreach ($closure_params as $i => $param) { if (!$param->is_optional && !$param->is_variadic) { $required_param_count = $i + 1; } } if (\count($closure_params) < $min_closure_param_count) { $argument_text = $min_closure_param_count === 1 ? 'one argument' : $min_closure_param_count . ' arguments'; if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooManyArguments('The callable passed to ' . $method_id . ' will be called with ' . $argument_text . ', expecting ' . $required_param_count, new \Psalm\CodeLocation($statements_analyzer->getSource(), $closure_arg), $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } elseif ($required_param_count > $max_closure_param_count) { $argument_text = $max_closure_param_count === 1 ? 'one argument' : $max_closure_param_count . ' arguments'; if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooFewArguments('The callable passed to ' . $method_id . ' will be called with ' . $argument_text . ', expecting ' . $required_param_count, new \Psalm\CodeLocation($statements_analyzer->getSource(), $closure_arg), $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } // abandon attempt to validate closure params if we have an extra arg for ARRAY_FILTER if ($method_id === 'array_filter' && $max_closure_param_count > 1) { return; } foreach ($closure_params as $i => $closure_param) { if (!isset($array_arg_types[$i])) { continue; } $array_arg_type = $array_arg_types[$i]; $input_type = $array_arg_type->type_params[1]; if ($input_type->hasMixed()) { continue; } $closure_param_type = $closure_param->type; if (!$closure_param_type) { continue; } if ($method_id === 'array_map' && $i === 0 && $closure_type->return_type && $closure_param_type->hasTemplate()) { $closure_param_type = clone $closure_param_type; $closure_type->return_type = clone $closure_type->return_type; $template_result = new \Psalm\Internal\Type\TemplateResult([], []); foreach ($closure_param_type->getTemplateTypes() as $template_type) { $template_result->template_types[$template_type->param_name] = [$template_type->defining_class => [$template_type->as]]; } $closure_param_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($closure_param_type, $template_result, $codebase, $statements_analyzer, $input_type, $i, $context->self, $context->calling_method_id ?: $context->calling_function_id); $closure_type->return_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); } $closure_param_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $closure_param_type, $context->self, null, $statements_analyzer->getParentFQCLN()); $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $type_match_found = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_type, $closure_param_type, $input_type->ignore_nullable_issues, $input_type->ignore_falsable_issues, $union_comparison_results); if ($union_comparison_results->type_coerced) { if ($union_comparison_results->type_coerced_from_mixed) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArgumentTypeCoercion('Parameter ' . ($i + 1) . ' of closure passed to function ' . $method_id . ' expects ' . $closure_param_type->getId() . ', parent type ' . $input_type->getId() . ' provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $closure_arg), $method_id), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ArgumentTypeCoercion('Parameter ' . ($i + 1) . ' of closure passed to function ' . $method_id . ' expects ' . $closure_param_type->getId() . ', parent type ' . $input_type->getId() . ' provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $closure_arg), $method_id), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } } if (!$union_comparison_results->type_coerced && !$type_match_found) { $types_can_be_identical = \Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $input_type, $closure_param_type); if ($union_comparison_results->scalar_type_match_found) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidScalarArgument('Parameter ' . ($i + 1) . ' of closure passed to function ' . $method_id . ' expects ' . $closure_param_type->getId() . ', ' . $input_type->getId() . ' provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $closure_arg), $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($types_can_be_identical) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidArgument('Parameter ' . ($i + 1) . ' of closure passed to function ' . $method_id . ' expects ' . $closure_param_type->getId() . ', possibly different type ' . $input_type->getId() . ' provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $closure_arg), $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArgument('Parameter ' . ($i + 1) . ' of closure passed to function ' . $method_id . ' expects ' . $closure_param_type->getId() . ', ' . $input_type->getId() . ' provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $closure_arg), $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } } $args * @param array|null $function_params * @param array>|null $generic_params * * @return false|null */ public static function analyze(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, array $args, ?array $function_params, ?string $method_id, bool $allow_named_args, \Psalm\Context $context, ?\Psalm\Internal\Type\TemplateResult $template_result = null) : ?bool { $last_param = $function_params ? $function_params[\count($function_params) - 1] : null; // if this modifies the array type based on further args if ($method_id && \in_array($method_id, ['array_push', 'array_unshift'], \true) && $function_params && isset($args[0]) && isset($args[1])) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArrayFunctionArgumentsAnalyzer::handleAddition($statements_analyzer, $args, $context, $method_id === 'array_push') === \false) { return \false; } return null; } if ($method_id && $method_id === 'array_splice' && $function_params && \count($args) > 1) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArrayFunctionArgumentsAnalyzer::handleSplice($statements_analyzer, $args, $context) === \false) { return \false; } return null; } if ($method_id === 'array_map') { $args = \array_reverse($args, \true); } foreach ($args as $argument_offset => $arg) { if ($function_params === null) { if (self::evaluateAribitraryParam($statements_analyzer, $arg, $context) === \false) { return \false; } continue; } $param = null; if ($arg->name && $allow_named_args) { foreach ($function_params as $candidate_param) { if ($candidate_param->name === $arg->name->name) { $param = $candidate_param; break; } } } elseif ($argument_offset < \count($function_params)) { $param = $function_params[$argument_offset]; } elseif ($last_param && $last_param->is_variadic) { $param = $last_param; } $by_ref = $param && $param->by_ref; $by_ref_type = null; if ($by_ref && $param) { $by_ref_type = $param->type ? clone $param->type : \Psalm\Type::getMixed(); } if ($by_ref && $by_ref_type && !($arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp)) { if (self::handleByRefFunctionArg($statements_analyzer, $method_id, $argument_offset, $arg, $context) === \false) { return \false; } continue; } $toggled_class_exists = \false; if ($method_id === 'class_exists' && $argument_offset === 0 && !$context->inside_class_exists) { $context->inside_class_exists = \true; $toggled_class_exists = \true; } if (($arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) && $template_result && $template_result->upper_bounds && $param && !$arg->value->getDocComment()) { self::handleClosureArg($statements_analyzer, $args, $method_id, $context, $template_result, $argument_offset, $arg, $param); } $was_inside_call = $context->inside_call; $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $arg->value, $context) === \false) { return \false; } if (!$was_inside_call) { $context->inside_call = \false; } if ($argument_offset === 0 && $method_id === 'array_filter' && \count($args) === 2 || $argument_offset > 0 && $method_id === 'array_map' && \count($args) >= 2) { self::handleArrayMapFilterArrayArg($statements_analyzer, $method_id, $argument_offset, $arg, $context, $template_result); } if ($toggled_class_exists) { $context->inside_class_exists = \false; } } return null; } private static function handleArrayMapFilterArrayArg(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $method_id, int $argument_offset, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg, \Psalm\Context $context, ?\Psalm\Internal\Type\TemplateResult &$template_result) : void { $codebase = $statements_analyzer->getCodebase(); $generic_param_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getArrayKey(), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParam('ArrayValue' . $argument_offset, \Psalm\Type::getMixed(), $method_id)])])]); $template_types = ['ArrayValue' . $argument_offset => [$method_id => [\Psalm\Type::getMixed()]]]; $replace_template_result = new \Psalm\Internal\Type\TemplateResult($template_types, []); $existing_type = $statements_analyzer->node_data->getType($arg->value); \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($generic_param_type, $replace_template_result, $codebase, $statements_analyzer, $existing_type, $argument_offset, 'fn-' . ($context->calling_method_id ?: $context->calling_function_id)); if ($replace_template_result->upper_bounds) { if (!$template_result) { $template_result = new \Psalm\Internal\Type\TemplateResult([], []); } $template_result->upper_bounds += $replace_template_result->upper_bounds; } } /** * @param array $args */ private static function handleClosureArg(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, array $args, ?string $method_id, \Psalm\Context $context, \Psalm\Internal\Type\TemplateResult $template_result, int $argument_offset, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg, \Psalm\Storage\FunctionLikeParameter $param) : void { if (!$param->type) { return; } $codebase = $statements_analyzer->getCodebase(); if ($argument_offset === 1 && $method_id === 'array_filter' && \count($args) === 2 || $argument_offset === 0 && $method_id === 'array_map' && \count($args) >= 2) { $function_like_params = []; foreach ($template_result->upper_bounds as $template_name => $_) { $function_like_params[] = new \Psalm\Storage\FunctionLikeParameter('function', \false, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParam($template_name, \Psalm\Type::getMixed(), $method_id)])); } $replaced_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TCallable('callable', \array_reverse($function_like_params))]); } else { $replaced_type = clone $param->type; } $replace_template_result = new \Psalm\Internal\Type\TemplateResult($template_result->upper_bounds, []); $replaced_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($replaced_type, $replace_template_result, $codebase, $statements_analyzer, null, null, null, 'fn-' . ($context->calling_method_id ?: $context->calling_function_id)); $replaced_type->replaceTemplateTypesWithArgTypes($replace_template_result, $codebase); $closure_id = \strtolower($statements_analyzer->getFilePath()) . ':' . $arg->value->getLine() . ':' . (int) $arg->value->getAttribute('startFilePos') . ':-:closure'; try { $closure_storage = $codebase->getClosureStorage($statements_analyzer->getFilePath(), $closure_id); } catch (\UnexpectedValueException $e) { return; } foreach ($closure_storage->params as $closure_param_offset => $param_storage) { $param_type_inferred = $param_storage->type_inferred; $newly_inferred_type = null; $has_different_docblock_type = \false; if ($param_storage->type && !$param_type_inferred) { if ($param_storage->type !== $param_storage->signature_type) { $has_different_docblock_type = \true; } } if (!$has_different_docblock_type) { foreach ($replaced_type->getAtomicTypes() as $replaced_type_part) { if ($replaced_type_part instanceof \Psalm\Type\Atomic\TCallable || $replaced_type_part instanceof \Psalm\Type\Atomic\TClosure) { if (isset($replaced_type_part->params[$closure_param_offset]->type) && !$replaced_type_part->params[$closure_param_offset]->type->hasTemplate()) { if ($param_storage->type && !$param_type_inferred) { $type_match_found = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $replaced_type_part->params[$closure_param_offset]->type, $param_storage->type); if (!$type_match_found) { continue; } } if (!$newly_inferred_type) { $newly_inferred_type = $replaced_type_part->params[$closure_param_offset]->type; } else { $newly_inferred_type = \Psalm\Type::combineUnionTypes($newly_inferred_type, $replaced_type_part->params[$closure_param_offset]->type, $codebase); } } } } } if ($newly_inferred_type) { $param_storage->type = $newly_inferred_type; $param_storage->type_inferred = \true; } if ($param_storage->type && ($method_id === 'array_map' || $method_id === 'array_filter')) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::taintArrayFetch($statements_analyzer, $args[1 - $argument_offset]->value, null, $param_storage->type, \Psalm\Type::getMixed()); } } } /** * @param array $args * @param string|MethodIdentifier|null $method_id * @param array $function_params * * @return false|null */ public static function checkArgumentsMatch(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, array $args, $method_id, array $function_params, ?\Psalm\Storage\FunctionLikeStorage $function_storage, ?\Psalm\Storage\ClassLikeStorage $class_storage, ?\Psalm\Internal\Type\TemplateResult $class_template_result, \Psalm\CodeLocation $code_location, \Psalm\Context $context) : ?bool { $in_call_map = $method_id ? \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap((string) $method_id) : \false; $cased_method_id = (string) $method_id; $is_variadic = \false; $fq_class_name = null; $codebase = $statements_analyzer->getCodebase(); if ($method_id) { if (!$in_call_map && $method_id instanceof \Psalm\Internal\MethodIdentifier) { $fq_class_name = $method_id->fq_class_name; } if ($function_storage) { $is_variadic = $function_storage->variadic; } elseif (\is_string($method_id)) { $is_variadic = $codebase->functions->isVariadic($codebase, \strtolower($method_id), $statements_analyzer->getRootFilePath()); } else { $is_variadic = $codebase->methods->isVariadic($method_id); } } if ($method_id instanceof \Psalm\Internal\MethodIdentifier) { $cased_method_id = $codebase->methods->getCasedMethodId($method_id); } elseif ($function_storage) { $cased_method_id = $function_storage->cased_name; } $calling_class_storage = $class_storage; $static_fq_class_name = $fq_class_name; $self_fq_class_name = $fq_class_name; if ($method_id instanceof \Psalm\Internal\MethodIdentifier) { $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if ($declaring_method_id && (string) $declaring_method_id !== (string) $method_id) { $self_fq_class_name = $declaring_method_id->fq_class_name; $class_storage = $codebase->classlike_storage_provider->get($self_fq_class_name); } $appearing_method_id = $codebase->methods->getAppearingMethodId($method_id); if ($appearing_method_id && $declaring_method_id !== $appearing_method_id) { $self_fq_class_name = $appearing_method_id->fq_class_name; } } if ($function_params) { foreach ($function_params as $function_param) { $is_variadic = $is_variadic || $function_param->is_variadic; } } $has_packed_var = \false; $packed_var_definite_args = 0; foreach ($args as $arg) { if ($arg->unpack) { $arg_value_type = $statements_analyzer->node_data->getType($arg->value); if (!$arg_value_type || !$arg_value_type->isSingle() || !$arg_value_type->hasArray()) { $has_packed_var = \true; break; } foreach ($arg_value_type->getAtomicTypes() as $atomic_arg_type) { if (!$atomic_arg_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $has_packed_var = \true; break 2; } $packed_var_definite_args = 0; foreach ($atomic_arg_type->properties as $property_type) { if ($property_type->possibly_undefined) { $has_packed_var = \true; } else { $packed_var_definite_args++; } } } } } if (!$has_packed_var) { $packed_var_definite_args = \max(0, $packed_var_definite_args - 1); } $last_param = $function_params ? $function_params[\count($function_params) - 1] : null; $template_result = null; $class_generic_params = $class_template_result ? $class_template_result->upper_bounds : []; if ($function_storage) { $template_types = \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::getTemplateTypesForCall($codebase, $class_storage, $self_fq_class_name, $calling_class_storage, $function_storage->template_types ?: []); if ($template_types) { $template_result = $class_template_result; if (!$template_result) { $template_result = new \Psalm\Internal\Type\TemplateResult($template_types, []); } elseif (!$template_result->template_types) { $template_result->template_types = $template_types; } foreach ($args as $argument_offset => $arg) { $function_param = null; if ($arg->name && $function_storage->allow_named_arg_calls) { foreach ($function_params as $candidate_param) { if ($candidate_param->name === $arg->name->name) { $function_param = $candidate_param; break; } } } elseif ($argument_offset < \count($function_params)) { $function_param = $function_params[$argument_offset]; } elseif ($last_param && $last_param->is_variadic) { $function_param = $last_param; } if (!$function_param || !$function_param->type) { continue; } $arg_value_type = $statements_analyzer->node_data->getType($arg->value); if (!$arg_value_type) { continue; } \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($function_param->type, $template_result, $codebase, $statements_analyzer, $arg_value_type, $argument_offset, $context->self, $context->calling_method_id ?: $context->calling_function_id, \false); if (!$class_template_result) { $template_result->upper_bounds = []; } } } } foreach ($class_generic_params as $template_name => $type_map) { foreach ($type_map as $class => $type) { $class_generic_params[$template_name][$class][0] = clone $type[0]; } } $function_param_count = \count($function_params); if (\count($function_params) > \count($args) && !$has_packed_var) { for ($i = \count($args), $iMax = \count($function_params); $i < $iMax; $i++) { if ($function_params[$i]->default_type && $function_params[$i]->type && $function_params[$i]->type->hasTemplate() && $function_params[$i]->default_type->hasLiteralValue()) { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentAnalyzer::checkArgumentMatches($statements_analyzer, $cased_method_id, $self_fq_class_name, $static_fq_class_name, $code_location, $function_params[$i], $i, $i, $function_storage ? $function_storage->allow_named_arg_calls : \true, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(\Psalm\Internal\Stubs\Generator\StubsGenerator::getExpressionFromType($function_params[$i]->default_type)), $function_params[$i]->default_type, $context, $class_generic_params, $template_result, $function_storage ? $function_storage->specialize_call : \true, $in_call_map); } } } if ($method_id === 'preg_match_all' && \count($args) > 3) { $args = \array_reverse($args, \true); } foreach ($args as $argument_offset => $arg) { $arg_function_params = []; if ($arg->unpack && $function_param_count > $argument_offset) { for ($i = $argument_offset; $i < $function_param_count; $i++) { $arg_function_params[] = $function_params[$i]; } } elseif ($arg->name && $function_storage && $function_storage->allow_named_arg_calls) { foreach ($function_params as $candidate_param) { if ($candidate_param->name === $arg->name->name) { $arg_function_params = [$candidate_param]; break; } } if (!$arg_function_params) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidNamedArgument('Parameter $' . $arg->name->name . ' does not exist on function ' . ($cased_method_id ?: $method_id), new \Psalm\CodeLocation($statements_analyzer, $arg->name), (string) $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } elseif ($function_param_count > $argument_offset) { $arg_function_params = [$function_params[$argument_offset]]; } elseif ($last_param && $last_param->is_variadic) { $arg_function_params = [$last_param]; } if ($arg_function_params && $arg_function_params[0]->by_ref && $method_id !== 'extract') { if (self::handlePossiblyMatchingByRefParam($statements_analyzer, $codebase, (string) $method_id, $cased_method_id, $last_param, $function_params, $argument_offset, $arg, $context, $template_result) === \false) { return null; } } $arg_value_type = $statements_analyzer->node_data->getType($arg->value); foreach ($arg_function_params as $i => $function_param) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentAnalyzer::checkArgumentMatches($statements_analyzer, $cased_method_id, $self_fq_class_name, $static_fq_class_name, $code_location, $function_param, $argument_offset + $i, $i, $function_storage ? $function_storage->allow_named_arg_calls : \true, $arg, $arg_value_type, $context, $class_generic_params, $template_result, $function_storage ? $function_storage->specialize_call : \true, $in_call_map) === \false) { return \false; } } } if ($method_id === 'array_map' || $method_id === 'array_filter') { if ($method_id === 'array_map' && \count($args) < 2) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooFewArguments('Too few arguments for ' . $method_id, $code_location, $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($method_id === 'array_filter' && \count($args) < 1) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooFewArguments('Too few arguments for ' . $method_id, $code_location, $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } \Psalm\Internal\Analyzer\Statements\Expression\Call\ArrayFunctionArgumentsAnalyzer::checkArgumentsMatch($statements_analyzer, $context, $args, $method_id, $context->check_functions); return null; } if (!$is_variadic && \count($args) > \count($function_params) && (!\count($function_params) || $function_params[\count($function_params) - 1]->name !== '...=') && ($in_call_map || !$function_storage instanceof \Psalm\Storage\MethodStorage || $function_storage->is_static || $method_id instanceof \Psalm\Internal\MethodIdentifier && $method_id->method_name === '__construct')) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooManyArguments('Too many arguments for ' . ($cased_method_id ?: $method_id) . ' - expecting ' . \count($function_params) . ' but saw ' . \count($args), $code_location, (string) $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } return null; } if (!$has_packed_var && \count($args) < \count($function_params)) { if ($function_storage) { $expected_param_count = $function_storage->required_param_count; } else { for ($i = 0, $j = \count($function_params); $i < $j; ++$i) { $param = $function_params[$i]; if ($param->is_optional || $param->is_variadic) { break; } } $expected_param_count = $i; } for ($i = \count($args) + $packed_var_definite_args, $j = \count($function_params); $i < $j; ++$i) { $param = $function_params[$i]; if (!$param->is_optional && !$param->is_variadic && ($in_call_map || !$function_storage instanceof \Psalm\Storage\MethodStorage || $function_storage->is_static || $method_id instanceof \Psalm\Internal\MethodIdentifier && $method_id->method_name === '__construct')) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooFewArguments('Too few arguments for ' . $cased_method_id . ' - expecting ' . $expected_param_count . ' but saw ' . (\count($args) + $packed_var_definite_args), $code_location, (string) $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } break; } if ($param->is_optional && $param->type && $param->default_type && !$param->is_variadic && $template_result) { \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($param->type, $template_result, $codebase, $statements_analyzer, clone $param->default_type, $i, $context->self, $context->calling_method_id ?: $context->calling_function_id, \true); } } } return null; } /** * @param array $function_params * @return false|null */ private static function handlePossiblyMatchingByRefParam(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, ?string $method_id, ?string $cased_method_id, ?\Psalm\Storage\FunctionLikeParameter $last_param, array $function_params, int $argument_offset, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg, \Psalm\Context $context, ?\Psalm\Internal\Type\TemplateResult $template_result) : ?bool { if ($arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary || ($arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall) && (!($arg_value_type = $statements_analyzer->node_data->getType($arg->value)) || !$arg_value_type->by_ref)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidPassByReference('Parameter ' . ($argument_offset + 1) . ' of ' . $cased_method_id . ' expects a variable', new \Psalm\CodeLocation($statements_analyzer->getSource(), $arg->value)), $statements_analyzer->getSuppressedIssues())) { // fall through } return \false; } if (!\in_array($method_id, ['ksort', 'asort', 'krsort', 'arsort', 'natcasesort', 'natsort', 'reset', 'end', 'next', 'prev', 'array_pop', 'array_shift', 'array_push', 'array_unshift', 'socket_select', 'array_splice'], \true)) { $by_ref_type = null; $by_ref_out_type = null; $check_null_ref = \true; if ($last_param) { if ($argument_offset < \count($function_params)) { $function_param = $function_params[$argument_offset]; } else { $function_param = $last_param; } $by_ref_type = $function_param->type; $by_ref_out_type = $function_param->out_type; if ($by_ref_type && $by_ref_type->isNullable()) { $check_null_ref = \false; } if ($template_result && $by_ref_type) { $original_by_ref_type = clone $by_ref_type; $by_ref_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins(clone $by_ref_type, $template_result, $codebase, $statements_analyzer, $statements_analyzer->node_data->getType($arg->value), $argument_offset, 'fn-' . ($context->calling_method_id ?: $context->calling_function_id)); if ($template_result->upper_bounds) { $original_by_ref_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); $by_ref_type = $original_by_ref_type; } } if ($template_result && $by_ref_out_type) { $original_by_ref_out_type = clone $by_ref_out_type; $by_ref_out_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins(clone $by_ref_out_type, $template_result, $codebase, $statements_analyzer, $statements_analyzer->node_data->getType($arg->value), $argument_offset, 'fn-' . ($context->calling_method_id ?: $context->calling_function_id)); if ($template_result->upper_bounds) { $original_by_ref_out_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); $by_ref_out_type = $original_by_ref_out_type; } } if ($by_ref_type && $function_param->is_variadic && $arg->unpack) { $by_ref_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $by_ref_type])]); } } $by_ref_type = $by_ref_type ?: \Psalm\Type::getMixed(); \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::assignByRefParam($statements_analyzer, $arg->value, $by_ref_type, $by_ref_out_type ?: $by_ref_type, $context, $method_id && (\strpos($method_id, '::') !== \false || !\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($method_id)), $check_null_ref); } return null; } /** * @return false|null */ private static function evaluateAribitraryParam(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg, \Psalm\Context $context) : ?bool { // there are a bunch of things we want to evaluate even when we don't // know what function/method is being called if ($arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\Encapsed || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc || $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec) { $was_inside_call = $context->inside_call; $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $arg->value, $context) === \false) { return \false; } if (!$was_inside_call) { $context->inside_call = \false; } } if ($arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && $arg->value->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $var_id = '$' . $arg->value->name->name; } else { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($arg->value, $statements_analyzer->getFQCLN(), $statements_analyzer); } if ($var_id) { if ($arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { $statements_analyzer->registerPossiblyUndefinedVariable($var_id, $arg->value); } if (!$context->hasVariable($var_id) || $context->vars_in_scope[$var_id]->isNull()) { if (!isset($context->vars_in_scope[$var_id]) && $arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedVariable('Variable ' . $var_id . ' must be defined prior to use within an unknown function or method', new \Psalm\CodeLocation($statements_analyzer->getSource(), $arg->value)), $statements_analyzer->getSuppressedIssues())) { // fall through } } // we don't know if it exists, assume it's passed by reference $context->vars_in_scope[$var_id] = \Psalm\Type::getMixed(); $context->vars_possibly_in_scope[$var_id] = \true; } else { $was_inside_call = $context->inside_call; $context->inside_call = \true; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $arg->value, $context); $context->inside_call = $was_inside_call; $context->removeVarFromConflictingClauses($var_id, $context->vars_in_scope[$var_id], $statements_analyzer); foreach ($context->vars_in_scope[$var_id]->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TArray && $type->type_params[1]->isEmpty()) { $context->vars_in_scope[$var_id]->removeType('array'); $context->vars_in_scope[$var_id]->addType(new \Psalm\Type\Atomic\TArray([\Psalm\Type::getArrayKey(), \Psalm\Type::getMixed()])); } } } } return null; } /** * @return false|null */ private static function handleByRefFunctionArg(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, ?string $method_id, int $argument_offset, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg, \Psalm\Context $context) : ?bool { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($arg->value, $statements_analyzer->getFQCLN(), $statements_analyzer); $builtin_array_functions = ['ksort', 'asort', 'krsort', 'arsort', 'natcasesort', 'natsort', 'reset', 'end', 'next', 'prev', 'array_pop', 'array_shift']; if ($var_id && isset($context->vars_in_scope[$var_id]) || $method_id && \in_array($method_id, $builtin_array_functions, \true)) { $was_inside_assignment = $context->inside_assignment; $context->inside_assignment = \true; // if the variable is in scope, get or we're in a special array function, // figure out its type before proceeding if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $arg->value, $context) === \false) { return \false; } $context->inside_assignment = $was_inside_assignment; } // special handling for array sort if ($argument_offset === 0 && $method_id && \in_array($method_id, $builtin_array_functions, \true)) { if (\in_array($method_id, ['array_pop', 'array_shift'], \true)) { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArrayFunctionArgumentsAnalyzer::handleByRefArrayAdjustment($statements_analyzer, $arg, $context, $method_id === 'array_shift'); return null; } // noops if (\in_array($method_id, ['reset', 'end', 'next', 'prev', 'ksort'], \true)) { return null; } if (($arg_value_type = $statements_analyzer->node_data->getType($arg->value)) && $arg_value_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var TArray|TList|TKeyedArray */ $array_type = $arg_value_type->getAtomicTypes()['array']; if ($array_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $array_type = $array_type->getGenericArrayType(); } if ($array_type instanceof \Psalm\Type\Atomic\TList) { $array_type = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $array_type->type_param]); } $by_ref_type = new \Psalm\Type\Union([clone $array_type]); \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::assignByRefParam($statements_analyzer, $arg->value, $by_ref_type, $by_ref_type, $context, \false); return null; } } if ($method_id === 'socket_select') { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $arg->value, $context) === \false) { return \false; } } if (!$arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('EmptyArrayAccess', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['EmptyArrayAccess']); } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $arg->value, $context) === \false) { return \false; } if (!\in_array('EmptyArrayAccess', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['EmptyArrayAccess']); } } return null; } } getCodebase(); $config = $codebase->config; $can_extend = \false; $from_static = \false; if ($stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { if (!\in_array(\strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], \true)) { $aliases = $statements_analyzer->getAliases(); if ($context->calling_method_id && !$stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified) { $codebase->file_reference_provider->addMethodReferenceToClassMember($context->calling_method_id, 'use:' . $stmt->class->parts[0] . ':' . \md5($statements_analyzer->getFilePath())); } $fq_class_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($stmt->class, $aliases); $fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name); } elseif ($context->self !== null) { switch ($stmt->class->parts[0]) { case 'self': $class_storage = $codebase->classlike_storage_provider->get($context->self); $fq_class_name = $class_storage->name; break; case 'parent': $fq_class_name = $context->parent; break; case 'static': // @todo maybe we can do better here $class_storage = $codebase->classlike_storage_provider->get($context->self); $fq_class_name = $class_storage->name; if (!$class_storage->final) { $can_extend = \true; $from_static = \true; } break; } } if ($codebase->store_node_types && $fq_class_name && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->class, $codebase->classlikes->classExists($fq_class_name) ? $fq_class_name : '*' . \implode('\\', $stmt->class->parts)); } } elseif ($stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { $statements_analyzer->analyze([$stmt->class], $context); $fq_class_name = \Psalm\Internal\Analyzer\ClassAnalyzer::getAnonymousClassName($stmt->class, $statements_analyzer->getFilePath()); } else { $was_inside_use = $context->inside_use; $context->inside_use = \true; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context); $context->inside_use = $was_inside_use; if ($stmt_class_type = $statements_analyzer->node_data->getType($stmt->class)) { $has_single_class = $stmt_class_type->isSingleStringLiteral(); if ($has_single_class) { $fq_class_name = $stmt_class_type->getSingleStringLiteral()->value; } else { if (self::checkMethodArgs(null, $stmt->args, null, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer) === \false) { return \false; } } $new_type = null; foreach ($stmt_class_type->getAtomicTypes() as $lhs_type_part) { if ($lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParamClass) { if (!$statements_analyzer->node_data->getType($stmt)) { $new_type_part = new \Psalm\Type\Atomic\TTemplateParam($lhs_type_part->param_name, $lhs_type_part->as_type ? new \Psalm\Type\Union([$lhs_type_part->as_type]) : \Psalm\Type::getObject(), $lhs_type_part->defining_class); if (!$lhs_type_part->as_type) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedMethodCall('Cannot call constructor on an unknown class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($new_type) { $new_type = \Psalm\Type::combineUnionTypes($new_type, new \Psalm\Type\Union([$new_type_part])); } else { $new_type = new \Psalm\Type\Union([$new_type_part]); } if ($lhs_type_part->as_type && $codebase->classlikes->classExists($lhs_type_part->as_type->value)) { $as_storage = $codebase->classlike_storage_provider->get($lhs_type_part->as_type->value); if (!$as_storage->preserve_constructor_signature) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnsafeInstantiation('Cannot safely instantiate class ' . $lhs_type_part->as_type->value . ' with "new $class_name" as' . ' its constructor might change in child classes', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } if ($lhs_type_part->as_type) { $codebase->methods->methodExists(new \Psalm\Internal\MethodIdentifier($lhs_type_part->as_type->value, '__construct'), $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null, $statements_analyzer, $statements_analyzer->getFilePath()); } continue; } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TLiteralClassString || $lhs_type_part instanceof \Psalm\Type\Atomic\TClassString || $lhs_type_part instanceof \Psalm\Type\Atomic\TDependentGetClass) { if (!$statements_analyzer->node_data->getType($stmt)) { if ($lhs_type_part instanceof \Psalm\Type\Atomic\TClassString) { $generated_type = $lhs_type_part->as_type ? clone $lhs_type_part->as_type : new \Psalm\Type\Atomic\TObject(); if ($lhs_type_part->as_type && $codebase->classlikes->classExists($lhs_type_part->as_type->value)) { $as_storage = $codebase->classlike_storage_provider->get($lhs_type_part->as_type->value); if (!$as_storage->preserve_constructor_signature) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnsafeInstantiation('Cannot safely instantiate class ' . $lhs_type_part->as_type->value . ' with "new $class_name" as' . ' its constructor might change in child classes', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TDependentGetClass) { $generated_type = new \Psalm\Type\Atomic\TObject(); if ($lhs_type_part->as_type->hasObjectType() && $lhs_type_part->as_type->isSingle()) { foreach ($lhs_type_part->as_type->getAtomicTypes() as $typeof_type_atomic) { if ($typeof_type_atomic instanceof \Psalm\Type\Atomic\TNamedObject) { $generated_type = new \Psalm\Type\Atomic\TNamedObject($typeof_type_atomic->value); } } } } else { $generated_type = new \Psalm\Type\Atomic\TNamedObject($lhs_type_part->value); } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TClassString) { $can_extend = \true; } if ($generated_type instanceof \Psalm\Type\Atomic\TObject) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedMethodCall('Cannot call constructor on an unknown class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($new_type) { $new_type = \Psalm\Type::combineUnionTypes($new_type, new \Psalm\Type\Union([$generated_type])); } else { $new_type = new \Psalm\Type\Union([$generated_type]); } } continue; } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TString) { if ($config->allow_string_standin_for_class && !$lhs_type_part instanceof \Psalm\Type\Atomic\TNumericString) { // do nothing } elseif (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidStringClass('String cannot be used as a class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TMixed || $lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedMethodCall('Cannot call constructor on an unknown class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TFalse && $stmt_class_type->ignore_falsable_issues) { // do nothing } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TNull && $stmt_class_type->ignore_nullable_issues) { // do nothing } elseif (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedClass('Type ' . $lhs_type_part . ' cannot be called as a class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), (string) $lhs_type_part), $statements_analyzer->getSuppressedIssues())) { // fall through } if ($new_type) { $new_type = \Psalm\Type::combineUnionTypes($new_type, \Psalm\Type::getObject()); } else { $new_type = \Psalm\Type::getObject(); } } if (!$has_single_class) { if ($new_type) { $statements_analyzer->node_data->setType($stmt, $new_type); } \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context); return \true; } } else { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context); return \true; } } if ($fq_class_name) { if ($codebase->alter_code && $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && !\in_array($stmt->class->parts[0], ['parent', 'static'])) { $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $stmt->class, $fq_class_name, $context->calling_method_id); } if ($context->check_classes) { if ($context->isPhantomClass($fq_class_name)) { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context); return \true; } if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_class_name, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->class), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues(), \false) === \false) { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context); return \true; } if ($codebase->interfaceExists($fq_class_name)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InterfaceInstantiation('Interface ' . $fq_class_name . ' cannot be instantiated', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->class)), $statements_analyzer->getSuppressedIssues())) { } return \true; } } if ($stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { $result_atomic_type = new \Psalm\Type\Atomic\TAnonymousClassInstance($fq_class_name); } else { $result_atomic_type = new \Psalm\Type\Atomic\TNamedObject($fq_class_name); $result_atomic_type->was_static = $from_static; } $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([$result_atomic_type])); if (\strtolower($fq_class_name) !== 'stdclass' && $codebase->classlikes->classExists($fq_class_name)) { $storage = $codebase->classlike_storage_provider->get($fq_class_name); if ($from_static && !$storage->preserve_constructor_signature) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnsafeInstantiation('Cannot safely instantiate class ' . $fq_class_name . ' with "new static" as' . ' its constructor might change in child classes', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } // if we're not calling this constructor via new static() if ($storage->abstract && !$can_extend) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\AbstractInstantiation('Unable to instantiate a abstract class ' . $fq_class_name, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \true; } } if ($storage->deprecated && \strtolower($fq_class_name) !== \strtolower((string) $context->self)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedClass($fq_class_name . ' is marked deprecated', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $fq_class_name), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($context->self && !$context->collect_initializations && !$context->collect_mutations && !\Psalm\Internal\Analyzer\NamespaceAnalyzer::isWithin($context->self, $storage->internal)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InternalClass($fq_class_name . ' is internal to ' . $storage->internal . ' but called from ' . $context->self, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $fq_class_name), $statements_analyzer->getSuppressedIssues())) { // fall through } } $method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, '__construct'); if ($codebase->methods->methodExists($method_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null, $statements_analyzer, $statements_analyzer->getFilePath())) { if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentMapPopulator::recordArgumentPositions($statements_analyzer, $stmt, $codebase, (string) $method_id); } $template_result = new \Psalm\Internal\Type\TemplateResult([], []); if (self::checkMethodArgs($method_id, $stmt->args, $template_result, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer) === \false) { return \false; } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodVisibilityAnalyzer::analyze($method_id, $context, $statements_analyzer->getSource(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues()) === \false) { return \false; } $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if ($declaring_method_id) { $method_storage = $codebase->methods->getStorage($declaring_method_id); if (!$method_storage->external_mutation_free && !$context->inside_throw) { if ($context->pure) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call an impure constructor from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } } } $generic_param_types = null; if ($storage->template_types) { $declaring_fq_class_name = $declaring_method_id ? $declaring_method_id->fq_class_name : $fq_class_name; foreach ($storage->template_types as $template_name => $base_type) { if (isset($template_result->upper_bounds[$template_name][$fq_class_name])) { $generic_param_type = $template_result->upper_bounds[$template_name][$fq_class_name][0]; } elseif ($storage->template_type_extends && $template_result->upper_bounds) { $generic_param_type = self::getGenericParamForOffset($declaring_fq_class_name, $template_name, $storage->template_type_extends, $template_result->upper_bounds); } else { if ($fq_class_name === 'SplObjectStorage') { $generic_param_type = \Psalm\Type::getEmpty(); } else { $generic_param_type = \array_values($base_type)[0][0]; } } $generic_param_type->had_template = \true; $generic_param_types[] = $generic_param_type; } } if ($generic_param_types) { $result_atomic_type = new \Psalm\Type\Atomic\TGenericObject($fq_class_name, $generic_param_types); $result_atomic_type->was_static = $from_static; $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([$result_atomic_type])); } } elseif ($stmt->args) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooManyArguments('Class ' . $fq_class_name . ' has no __construct, but arguments were passed', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $fq_class_name . '::__construct'), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($storage->external_mutation_free) { /** @psalm-suppress UndefinedPropertyAssignment */ $stmt->external_mutation_free = \true; $stmt_type = $statements_analyzer->node_data->getType($stmt); if ($stmt_type) { $stmt_type->reference_free = \true; } } if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues()) && ($stmt_type = $statements_analyzer->node_data->getType($stmt))) { $code_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $method_storage = null; $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if ($declaring_method_id) { $method_storage = $codebase->methods->getStorage($declaring_method_id); } if ($storage->external_mutation_free || $method_storage && $method_storage->specialize_call) { $method_source = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodReturn((string) $method_id, $fq_class_name . '::__construct', $storage->location, $code_location); } else { $method_source = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodReturn((string) $method_id, $fq_class_name . '::__construct', $storage->location); } $statements_analyzer->data_flow_graph->addNode($method_source); $stmt_type->parent_nodes = [$method_source->id => $method_source]; } } else { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context); } } if (!$config->remember_property_assignments_after_call && !$context->collect_initializations) { $context->removeAllObjectVars(); } return \true; } /** * @param array> $template_type_extends * @param array> $found_generic_params */ private static function getGenericParamForOffset(string $fq_class_name, string $template_name, array $template_type_extends, array $found_generic_params, bool $mapped = \false) : \Psalm\Type\Union { if (isset($found_generic_params[$template_name][$fq_class_name])) { if (!$mapped && isset($template_type_extends[$fq_class_name][$template_name])) { foreach ($template_type_extends[$fq_class_name][$template_name]->getAtomicTypes() as $t) { if ($t instanceof \Psalm\Type\Atomic\TTemplateParam) { if ($t->param_name !== $template_name) { return $t->as; } } } } return $found_generic_params[$template_name][$fq_class_name][0]; } foreach ($template_type_extends as $type_map) { foreach ($type_map as $extended_template_name => $extended_type) { foreach ($extended_type->getAtomicTypes() as $extended_atomic_type) { if (\is_string($extended_template_name) && $extended_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam && $extended_atomic_type->param_name === $template_name && $extended_template_name !== $template_name) { return self::getGenericParamForOffset($fq_class_name, $extended_template_name, $template_type_extends, $found_generic_params, \true); } } } } return \Psalm\Type::getMixed(); } } name; $function_id = null; $function_params = null; $in_call_map = \false; $is_stubbed = \false; $function_storage = null; $codebase = $statements_analyzer->getCodebase(); $code_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $codebase_functions = $codebase->functions; $config = $codebase->config; $defined_constants = []; $global_variables = []; $function_exists = \false; $real_stmt = $stmt; if ($function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && isset($stmt->args[0]) && !$stmt->args[0]->unpack) { $original_function_id = \implode('\\', $function_name->parts); if ($original_function_id === 'call_user_func') { $other_args = \array_slice($stmt->args, 1); $function_name = $stmt->args[0]->value; $stmt = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall($function_name, $other_args, $stmt->getAttributes()); } if ($original_function_id === 'call_user_func_array' && isset($stmt->args[1])) { $function_name = $stmt->args[0]->value; $stmt = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall($function_name, [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($stmt->args[1]->value, \false, \true)], $stmt->getAttributes()); } } $byref_uses = []; $allow_named_args = \true; if ($function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { [$expr_function_exists, $expr_function_name, $expr_function_params, $byref_uses] = self::getAnalyzeNamedExpression($statements_analyzer, $codebase, $stmt, $real_stmt, $function_name, $context); if ($expr_function_exists === \false) { return \true; } if ($expr_function_exists === \true) { $function_exists = \true; } if ($expr_function_name) { $function_name = $expr_function_name; } if ($expr_function_params) { $function_params = $expr_function_params; } } else { $original_function_id = \implode('\\', $function_name->parts); if (!$function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified) { $function_id = $codebase_functions->getFullyQualifiedFunctionNameFromString($original_function_id, $statements_analyzer); } else { $function_id = $original_function_id; } $namespaced_function_exists = $codebase_functions->functionExists($statements_analyzer, \strtolower($function_id)); if (!$namespaced_function_exists && !$function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified) { $in_call_map = \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($original_function_id); $is_stubbed = $codebase_functions->hasStubbedFunction($original_function_id); if ($is_stubbed || $in_call_map) { $function_id = $original_function_id; } } else { $in_call_map = \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($function_id); $is_stubbed = $codebase_functions->hasStubbedFunction($function_id); } if ($is_stubbed || $in_call_map || $namespaced_function_exists) { $function_exists = \true; } if ($function_exists && $codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentMapPopulator::recordArgumentPositions($statements_analyzer, $stmt, $codebase, $function_id); } $is_predefined = \true; $is_maybe_root_function = !$function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified && \count($function_name->parts) === 1; if (!$in_call_map) { $predefined_functions = $config->getPredefinedFunctions(); $is_predefined = isset($predefined_functions[\strtolower($original_function_id)]) || isset($predefined_functions[\strtolower($function_id)]); if ($context->check_functions) { if (self::checkFunctionExists($statements_analyzer, $function_id, $code_location, $is_maybe_root_function) === \false) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context) === \false) { // fall through } return \true; } } } else { $function_exists = \true; } if ($function_exists) { $function_params = null; if ($codebase->functions->params_provider->has($function_id)) { $function_params = $codebase->functions->params_provider->getFunctionParams($statements_analyzer, $function_id, $stmt->args); } if ($function_params === null) { if (!$in_call_map || $is_stubbed) { try { $function_storage = $codebase_functions->getStorage($statements_analyzer, \strtolower($function_id)); $function_params = $function_storage->params; if (!$function_storage->allow_named_arg_calls) { $allow_named_args = \false; } if (!$is_predefined) { $defined_constants = $function_storage->defined_constants; $global_variables = $function_storage->global_variables; } } catch (\UnexpectedValueException $e) { $function_params = [new \Psalm\Storage\FunctionLikeParameter('args', \false, null, null, null, \false, \false, \true)]; } } else { $function_callable = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallableFromCallMapById($codebase, $function_id, $stmt->args, $statements_analyzer->node_data); $function_params = $function_callable->params; } } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $function_name, $function_id . '()'); } } } $set_inside_conditional = \false; if ($function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $function_name->parts === ['assert'] && !$context->inside_conditional) { $context->inside_conditional = \true; $set_inside_conditional = \true; } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, $function_params, $function_id, $allow_named_args, $context) === \false) { // fall through } if ($set_inside_conditional) { $context->inside_conditional = \false; } $template_result = null; $function_callable = null; if ($function_exists) { if ($function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $function_id) { if (!$is_stubbed && $in_call_map) { $function_callable = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallableFromCallMapById($codebase, $function_id, $stmt->args, $statements_analyzer->node_data); $function_params = $function_callable->params; } } $template_result = new \Psalm\Internal\Type\TemplateResult([], []); // do this here to allow closure param checks if ($function_params !== null && \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::checkArgumentsMatch($statements_analyzer, $stmt->args, $function_id, $function_params, $function_storage, null, $template_result, $code_location, $context) === \false) { // fall through } \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::checkTemplateResult($statements_analyzer, $template_result, $code_location, $function_id); if ($function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $function_id) { $stmt_type = self::getFunctionCallReturnType($statements_analyzer, $codebase, $stmt, $function_name, $function_id, $in_call_map, $is_stubbed, $function_storage, $function_callable, $template_result, $context); $statements_analyzer->node_data->setType($real_stmt, $stmt_type); if ($config->after_every_function_checks) { foreach ($config->after_every_function_checks as $plugin_fq_class_name) { $plugin_fq_class_name::afterEveryFunctionCallAnalysis($stmt, $function_id, $context, $statements_analyzer->getSource(), $codebase); } } } foreach ($defined_constants as $const_name => $const_type) { $context->constants[$const_name] = clone $const_type; $context->vars_in_scope[$const_name] = clone $const_type; } foreach ($global_variables as $var_id => $_) { $context->vars_in_scope[$var_id] = \Psalm\Type::getMixed(); $context->vars_possibly_in_scope[$var_id] = \true; } if ($function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $function_name->parts === ['assert'] && isset($stmt->args[0])) { self::processAssertFunctionEffects($statements_analyzer, $codebase, $stmt, $stmt->args[0], $context); } } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations && ($stmt_type = $statements_analyzer->node_data->getType($real_stmt))) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt, $stmt_type->getId()); } self::checkFunctionCallPurity($statements_analyzer, $codebase, $stmt, $function_name, $function_id, $in_call_map, $function_storage, $context); if ($function_storage) { $generic_params = $template_result ? $template_result->upper_bounds : []; if ($function_storage->assertions && $function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { self::applyAssertionsToContext($function_name, null, $function_storage->assertions, $stmt->args, $generic_params, $context, $statements_analyzer); } if ($function_storage->if_true_assertions) { $statements_analyzer->node_data->setIfTrueAssertions($stmt, \array_map(function (\Psalm\Storage\Assertion $assertion) use($generic_params) : Assertion { return $assertion->getUntemplatedCopy($generic_params ?: [], null); }, $function_storage->if_true_assertions)); } if ($function_storage->if_false_assertions) { $statements_analyzer->node_data->setIfFalseAssertions($stmt, \array_map(function (\Psalm\Storage\Assertion $assertion) use($generic_params) : Assertion { return $assertion->getUntemplatedCopy($generic_params ?: [], null); }, $function_storage->if_false_assertions)); } if ($function_storage->deprecated && $function_id) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedFunction('The function ' . $function_id . ' has been marked as deprecated', $code_location, $function_id), $statements_analyzer->getSuppressedIssues())) { // continue } } } if ($byref_uses) { foreach ($byref_uses as $byref_use_var => $_) { $context->vars_in_scope['$' . $byref_use_var] = \Psalm\Type::getMixed(); $context->vars_possibly_in_scope['$' . $byref_use_var] = \true; } } if ($function_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { self::handleNamedFunction($statements_analyzer, $codebase, $stmt, $real_stmt, $function_name, $function_id, $context); } if (!$statements_analyzer->node_data->getType($real_stmt)) { $statements_analyzer->node_data->setType($real_stmt, \Psalm\Type::getMixed()); } return \true; } /** * @return array{ * ?bool, * ?PhpParser\Node\Expr|PhpParser\Node\Name, * array|null, * ?array * } */ private static function getAnalyzeNamedExpression(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $real_stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $function_name, \Psalm\Context $context) : array { $function_params = null; $explicit_function_name = null; $function_exists = null; $was_in_call = $context->inside_call; $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $function_name, $context) === \false) { $context->inside_call = $was_in_call; return [\false, null, null, null]; } $context->inside_call = $was_in_call; $byref_uses = []; if ($stmt_name_type = $statements_analyzer->node_data->getType($function_name)) { if ($stmt_name_type->isNull()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullFunctionCall('Cannot call function on null value', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } return [\false, null, null, null]; } if ($stmt_name_type->isNullable()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullFunctionCall('Cannot call function on possibly null value', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $invalid_function_call_types = []; $has_valid_function_call_type = \false; foreach ($stmt_name_type->getAtomicTypes() as $var_type_part) { if ($var_type_part instanceof \Psalm\Type\Atomic\TClosure || $var_type_part instanceof \Psalm\Type\Atomic\TCallable) { if (!$var_type_part->is_pure && $context->pure) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureFunctionCall('Cannot call an impure function from a mutation-free context', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $function_params = $var_type_part->params; if (($stmt_type = $statements_analyzer->node_data->getType($real_stmt)) && $var_type_part->return_type) { $statements_analyzer->node_data->setType($real_stmt, \Psalm\Type::combineUnionTypes($stmt_type, $var_type_part->return_type)); } else { $statements_analyzer->node_data->setType($real_stmt, $var_type_part->return_type ?: \Psalm\Type::getMixed()); } if ($var_type_part instanceof \Psalm\Type\Atomic\TClosure) { $byref_uses += $var_type_part->byref_uses; } $function_exists = \true; $has_valid_function_call_type = \true; } elseif ($var_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && $var_type_part->as->hasCallableType()) { $has_valid_function_call_type = \true; } elseif ($var_type_part instanceof \Psalm\Type\Atomic\TMixed || $var_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $has_valid_function_call_type = \true; if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedFunctionCall('Cannot call function on ' . $var_type_part->getId(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($var_type_part instanceof \Psalm\Type\Atomic\TCallableObject || $var_type_part instanceof \Psalm\Type\Atomic\TCallableString) { // this is fine $has_valid_function_call_type = \true; } elseif ($var_type_part instanceof \Psalm\Type\Atomic\TNamedObject && $var_type_part->value === 'Closure') { // this is fine $has_valid_function_call_type = \true; } elseif ($var_type_part instanceof \Psalm\Type\Atomic\TString || $var_type_part instanceof \Psalm\Type\Atomic\TArray || $var_type_part instanceof \Psalm\Type\Atomic\TList || $var_type_part instanceof \Psalm\Type\Atomic\TKeyedArray && \count($var_type_part->properties) === 2) { $potential_method_id = null; if ($var_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $potential_method_id = \Psalm\Internal\Type\Comparator\CallableTypeComparator::getCallableMethodIdFromTKeyedArray($var_type_part, $codebase, $context->calling_method_id, $statements_analyzer->getFilePath()); if ($potential_method_id === 'not-callable') { $potential_method_id = null; } } elseif ($var_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { if (!$var_type_part->value) { $invalid_function_call_types[] = '\'\''; continue; } if (\strpos($var_type_part->value, '::')) { $parts = \explode('::', \strtolower($var_type_part->value)); $fq_class_name = $parts[0]; $fq_class_name = \preg_replace('/^\\\\/', '', $fq_class_name); $potential_method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, $parts[1]); } else { $explicit_function_name = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($var_type_part->value, $function_name->getAttributes()); } } if ($potential_method_id) { $codebase->methods->methodExists($potential_method_id, $context->calling_method_id, null, $statements_analyzer, $statements_analyzer->getFilePath()); } // this is also kind of fine $has_valid_function_call_type = \true; } elseif ($var_type_part instanceof \Psalm\Type\Atomic\TNull) { // handled above } elseif (!$var_type_part instanceof \Psalm\Type\Atomic\TNamedObject || !$codebase->classlikes->classOrInterfaceExists($var_type_part->value) || !$codebase->methods->methodExists(new \Psalm\Internal\MethodIdentifier($var_type_part->value, '__invoke'))) { $invalid_function_call_types[] = (string) $var_type_part; } else { self::analyzeInvokeCall($statements_analyzer, $stmt, $real_stmt, $function_name, $context, $var_type_part); } } if ($invalid_function_call_types) { $var_type_part = \reset($invalid_function_call_types); if ($has_valid_function_call_type) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidFunctionCall('Cannot treat type ' . $var_type_part . ' as callable', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidFunctionCall('Cannot treat type ' . $var_type_part . ' as callable', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } return [\false, null, null, null]; } } if (!$statements_analyzer->node_data->getType($real_stmt)) { $statements_analyzer->node_data->setType($real_stmt, \Psalm\Type::getMixed()); } return [$function_exists, $explicit_function_name ?: $function_name, $function_params, $byref_uses]; } private static function analyzeInvokeCall(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $real_stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $function_name, \Psalm\Context $context, \Psalm\Type\Atomic $atomic_type) : void { $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($function_name, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('__invoke', $function_name->getAttributes()), $stmt->args); $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('PossiblyNullReference', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyNullReference']); } if (!\in_array('InternalMethod', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['InternalMethod']); } if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyInvalidMethodCall']); } $statements_analyzer->node_data->setType($function_name, new \Psalm\Type\Union([$atomic_type])); \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_method_call, $context, \false); if (!\in_array('PossiblyNullReference', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyNullReference']); } if (!\in_array('InternalMethod', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['InternalMethod']); } if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyInvalidMethodCall']); } $fake_method_call_type = $statements_analyzer->node_data->getType($fake_method_call); $statements_analyzer->node_data = $old_data_provider; if ($stmt_type = $statements_analyzer->node_data->getType($real_stmt)) { $statements_analyzer->node_data->setType($real_stmt, \Psalm\Type::combineUnionTypes($fake_method_call_type ?: \Psalm\Type::getMixed(), $stmt_type)); } else { $statements_analyzer->node_data->setType($real_stmt, $fake_method_call_type ?: \Psalm\Type::getMixed()); } } private static function processAssertFunctionEffects(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $first_arg, \Psalm\Context $context) : void { $first_arg_value_id = \spl_object_id($first_arg->value); $assert_clauses = \Psalm\Type\Algebra::getFormula($first_arg_value_id, $first_arg_value_id, $first_arg->value, $context->self, $statements_analyzer, $codebase); $cond_assigned_var_ids = []; \Psalm\Internal\Analyzer\AlgebraAnalyzer::checkForParadox($context->clauses, $assert_clauses, $statements_analyzer, $stmt, $cond_assigned_var_ids); $simplified_clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($context->clauses, $assert_clauses)); $assert_type_assertions = \Psalm\Type\Algebra::getTruthsFromFormula($simplified_clauses); if ($assert_type_assertions) { $changed_var_ids = []; // while in an and, we allow scope to boil over to support // statements of the form if ($x && $x->foo()) $op_vars_in_scope = \Psalm\Type\Reconciler::reconcileKeyedTypes($assert_type_assertions, $assert_type_assertions, $context->vars_in_scope, $changed_var_ids, \array_map(function ($_) : bool { return \true; }, $assert_type_assertions), $statements_analyzer, $statements_analyzer->getTemplateTypeMap() ?: [], $context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)); foreach ($changed_var_ids as $var_id => $_) { $first_appearance = $statements_analyzer->getFirstAppearance($var_id); if ($first_appearance && isset($context->vars_in_scope[$var_id]) && $context->vars_in_scope[$var_id]->hasMixed()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->decrementMixedCount($statements_analyzer->getFilePath()); } \Psalm\IssueBuffer::remove($statements_analyzer->getFilePath(), 'MixedAssignment', $first_appearance->raw_file_start); } if (isset($op_vars_in_scope[$var_id])) { $op_vars_in_scope[$var_id]->from_docblock = \true; } } $context->vars_in_scope = $op_vars_in_scope; } } /** * @param non-empty-string $function_id */ private static function getFunctionCallReturnType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node\Name $function_name, string $function_id, bool $in_call_map, bool $is_stubbed, ?\Psalm\Storage\FunctionLikeStorage $function_storage, ?\Psalm\Type\Atomic\TCallable $callmap_callable, \Psalm\Internal\Type\TemplateResult $template_result, \Psalm\Context $context) : \Psalm\Type\Union { $stmt_type = null; $config = $codebase->config; if ($codebase->functions->return_type_provider->has($function_id)) { $stmt_type = $codebase->functions->return_type_provider->getReturnType($statements_analyzer, $function_id, $stmt->args, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $function_name)); } if (!$stmt_type) { if (!$in_call_map || $is_stubbed) { if ($function_storage && $function_storage->template_types) { foreach ($function_storage->template_types as $template_name => $_) { if (!isset($template_result->upper_bounds[$template_name])) { if ($template_name === 'TFunctionArgCount') { $template_result->upper_bounds[$template_name] = ['fn-' . $function_id => [\Psalm\Type::getInt(\false, \count($stmt->args)), 0]]; } else { $template_result->upper_bounds[$template_name] = ['fn-' . $function_id => [\Psalm\Type::getEmpty(), 0]]; } } } } if ($function_storage && !$context->isSuppressingExceptions($statements_analyzer)) { $context->mergeFunctionExceptions($function_storage, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)); } try { if ($function_storage && $function_storage->return_type) { $return_type = clone $function_storage->return_type; if ($template_result->upper_bounds && $function_storage->template_types) { $return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type, null, null, null); $return_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); } $return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type, null, null, null); $return_type_location = $function_storage->return_type_location; if ($config->after_function_checks) { $file_manipulations = []; foreach ($config->after_function_checks as $plugin_fq_class_name) { $plugin_fq_class_name::afterFunctionCallAnalysis($stmt, $function_id, $context, $statements_analyzer->getSource(), $codebase, $return_type, $file_manipulations); } if ($file_manipulations) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } $stmt_type = $return_type; $return_type->by_ref = $function_storage->returns_by_ref; // only check the type locally if it's defined externally if ($return_type_location && !$is_stubbed && !$config->isInProjectDirs($return_type_location->file_path)) { $return_type->check($statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues(), $context->phantom_classes, \true, \false, \false, $context->calling_method_id); } } } catch (\InvalidArgumentException $e) { // this can happen when the function was defined in the Config startup script $stmt_type = \Psalm\Type::getMixed(); } } else { if (!$callmap_callable) { throw new \UnexpectedValueException('We should have a callmap callable here'); } $stmt_type = self::getReturnTypeFromCallMapWithArgs($statements_analyzer, $function_id, $stmt->args, $callmap_callable, $context); } } if (!$stmt_type) { $stmt_type = \Psalm\Type::getMixed(); } if ($function_storage) { self::taintReturnType($statements_analyzer, $stmt, $function_id, $function_storage, $stmt_type); } return $stmt_type; } /** * @param array $call_args */ private static function getReturnTypeFromCallMapWithArgs(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $function_id, array $call_args, \Psalm\Type\Atomic\TCallable $callmap_callable, \Psalm\Context $context) : \Psalm\Type\Union { $call_map_key = \strtolower($function_id); $codebase = $statements_analyzer->getCodebase(); if (!$call_args) { switch ($call_map_key) { case 'hrtime': return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TKeyedArray([\Psalm\Type::getInt(), \Psalm\Type::getInt()])]); case 'get_called_class': return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClassString($context->self ?: 'object', $context->self ? new \Psalm\Type\Atomic\TNamedObject($context->self, \true) : null)]); case 'get_parent_class': if ($context->self && $codebase->classExists($context->self)) { $classlike_storage = $codebase->classlike_storage_provider->get($context->self); if ($classlike_storage->parent_classes) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClassString(\array_values($classlike_storage->parent_classes)[0])]); } } } } else { switch ($call_map_key) { case 'count': if ($first_arg_type = $statements_analyzer->node_data->getType($call_args[0]->value)) { $atomic_types = $first_arg_type->getAtomicTypes(); if (\count($atomic_types) === 1) { if (isset($atomic_types['array'])) { if ($atomic_types['array'] instanceof \Psalm\Type\Atomic\TCallableArray || $atomic_types['array'] instanceof \Psalm\Type\Atomic\TCallableList || $atomic_types['array'] instanceof \Psalm\Type\Atomic\TCallableKeyedArray) { return \Psalm\Type::getInt(\false, 2); } if ($atomic_types['array'] instanceof \Psalm\Type\Atomic\TNonEmptyArray) { return new \Psalm\Type\Union([$atomic_types['array']->count !== null ? new \Psalm\Type\Atomic\TLiteralInt($atomic_types['array']->count) : new \Psalm\Type\Atomic\TInt()]); } if ($atomic_types['array'] instanceof \Psalm\Type\Atomic\TNonEmptyList) { return new \Psalm\Type\Union([$atomic_types['array']->count !== null ? new \Psalm\Type\Atomic\TLiteralInt($atomic_types['array']->count) : new \Psalm\Type\Atomic\TInt()]); } if ($atomic_types['array'] instanceof \Psalm\Type\Atomic\TKeyedArray && $atomic_types['array']->sealed) { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralInt(\count($atomic_types['array']->properties))]); } } } } break; case 'hrtime': if ($first_arg_type = $statements_analyzer->node_data->getType($call_args[0]->value)) { if ((string) $first_arg_type === 'true') { $int = \Psalm\Type::getInt(); $int->from_calculation = \true; return $int; } if ((string) $first_arg_type === 'false') { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TKeyedArray([\Psalm\Type::getInt(), \Psalm\Type::getInt()])]); } return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TKeyedArray([\Psalm\Type::getInt(), \Psalm\Type::getInt()]), new \Psalm\Type\Atomic\TInt()]); } $int = \Psalm\Type::getInt(); $int->from_calculation = \true; return $int; case 'min': case 'max': if (isset($call_args[0])) { $first_arg = $call_args[0]->value; if ($first_arg_type = $statements_analyzer->node_data->getType($first_arg)) { if ($first_arg_type->hasArray()) { /** @psalm-suppress PossiblyUndefinedStringArrayOffset */ $array_type = $first_arg_type->getAtomicTypes()['array']; if ($array_type instanceof \Psalm\Type\Atomic\TKeyedArray) { return $array_type->getGenericValueType(); } if ($array_type instanceof \Psalm\Type\Atomic\TArray) { return clone $array_type->type_params[1]; } if ($array_type instanceof \Psalm\Type\Atomic\TList) { return clone $array_type->type_param; } } elseif ($first_arg_type->hasScalarType() && ($second_arg = $call_args[1]->value ?? null) && ($second_arg_type = $statements_analyzer->node_data->getType($second_arg)) && $second_arg_type->hasScalarType()) { return \Psalm\Type::combineUnionTypes($first_arg_type, $second_arg_type); } } } break; case 'get_parent_class': // this is unreliable, as it's hard to know exactly what's wanted - attempted this in // https://github.com/vimeo/psalm/commit/355ed831e1c69c96bbf9bf2654ef64786cbe9fd7 // but caused problems where it didn’t know exactly what level of child we // were receiving. // // Really this should only work on instances we've created with new Foo(), // but that requires more work break; case 'fgetcsv': $string_type = \Psalm\Type::getString(); $string_type->addType(new \Psalm\Type\Atomic\TNull()); $string_type->ignore_nullable_issues = \true; $call_map_return_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyList($string_type), new \Psalm\Type\Atomic\TFalse(), new \Psalm\Type\Atomic\TNull()]); if ($codebase->config->ignore_internal_nullable_issues) { $call_map_return_type->ignore_nullable_issues = \true; } if ($codebase->config->ignore_internal_falsable_issues) { $call_map_return_type->ignore_falsable_issues = \true; } return $call_map_return_type; } } $stmt_type = $callmap_callable->return_type ? clone $callmap_callable->return_type : \Psalm\Type::getMixed(); switch ($function_id) { case 'mb_strpos': case 'mb_strrpos': case 'mb_stripos': case 'mb_strripos': case 'strpos': case 'strrpos': case 'stripos': case 'strripos': case 'strstr': case 'stristr': case 'strrchr': case 'strpbrk': case 'array_search': break; default: if ($stmt_type->isFalsable() && $codebase->config->ignore_internal_falsable_issues) { $stmt_type->ignore_falsable_issues = \true; } } switch ($call_map_key) { case 'array_replace': case 'array_replace_recursive': if ($codebase->config->ignore_internal_nullable_issues) { $stmt_type->ignore_nullable_issues = \true; } break; } return $stmt_type; } private static function taintReturnType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt, string $function_id, \Psalm\Storage\FunctionLikeStorage $function_storage, \Psalm\Type\Union $stmt_type) : void { if (!$statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph || \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { return; } $node_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $function_call_node = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodReturn($function_id, $function_id, $function_storage->signature_return_type_location ?: $function_storage->location, $function_storage->specialize_call ? $node_location : null); $statements_analyzer->data_flow_graph->addNode($function_call_node); $stmt_type->parent_nodes[$function_call_node->id] = $function_call_node; if ($function_storage->return_source_params) { $removed_taints = $function_storage->removed_taints; if ($function_id === 'preg_replace' && \count($stmt->args) > 2) { $first_stmt_type = $statements_analyzer->node_data->getType($stmt->args[0]->value); $second_stmt_type = $statements_analyzer->node_data->getType($stmt->args[1]->value); if ($first_stmt_type && $second_stmt_type && $first_stmt_type->isSingleStringLiteral() && $second_stmt_type->isSingleStringLiteral()) { $first_arg_value = $first_stmt_type->getSingleStringLiteral()->value; $pattern = \substr($first_arg_value, 1, -1); if ($pattern[0] === '[' && $pattern[1] === '^' && \substr($pattern, -1) === ']') { $pattern = \substr($pattern, 2, -1); if (self::simpleExclusion($pattern, $first_arg_value[0])) { $removed_taints[] = 'html'; $removed_taints[] = 'sql'; } } } } foreach ($function_storage->return_source_params as $i => $path_type) { if (!isset($stmt->args[$i])) { continue; } $arg_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->args[$i]->value); $function_param_sink = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodArgument($function_id, $function_id, $i, $arg_location, $function_storage->specialize_call ? $node_location : null); $statements_analyzer->data_flow_graph->addNode($function_param_sink); $statements_analyzer->data_flow_graph->addPath($function_param_sink, $function_call_node, $path_type, $function_storage->added_taints, $removed_taints); } } if ($function_storage->taint_source_types) { $method_node = \Psalm\Internal\DataFlow\TaintSource::getForMethodReturn($function_id, $function_id, $node_location); $method_node->taints = $function_storage->taint_source_types; $statements_analyzer->data_flow_graph->addSource($method_node); } } /** * @psalm-pure */ private static function simpleExclusion(string $pattern, string $escape_char) : bool { $str_length = \strlen($pattern); for ($i = 0; $i < $str_length; $i++) { $current = $pattern[$i]; $next = $pattern[$i + 1] ?? null; if ($current === '\\') { if ($next == null || $next === 'x' || $next === 'u') { return \false; } if ($next === '.' || $next === '(' || $next === ')' || $next === '[' || $next === ']' || $next === 's' || $next === 'w' || $next === $escape_char) { $i++; continue; } return \false; } if ($next !== '-') { if ($current === '_' || $current === '-' || $current === '|' || $current === ':' || $current === '#' || $current === '.' || $current === ' ') { continue; } return \false; } if ($current === ']') { return \false; } if (!isset($pattern[$i + 2])) { return \false; } if ($current === 'a' && $pattern[$i + 2] === 'z' || $current === 'a' && $pattern[$i + 2] === 'Z' || $current === 'A' && $pattern[$i + 2] === 'Z' || $current === '0' && $pattern[$i + 2] === '9') { $i += 2; continue; } return \false; } return \true; } private static function checkFunctionCallPurity(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node $function_name, ?string $function_id, bool $in_call_map, ?\Psalm\Storage\FunctionLikeStorage $function_storage, \Psalm\Context $context) : void { $config = $codebase->config; if (!$context->collect_initializations && !$context->collect_mutations && ($context->mutation_free || $context->external_mutation_free || $codebase->find_unused_variables || !$config->remember_property_assignments_after_call || $statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations)) { $must_use = \true; $callmap_function_pure = $function_id && $in_call_map ? $codebase->functions->isCallMapFunctionPure($codebase, $statements_analyzer->node_data, $function_id, $stmt->args, $must_use) : null; if (!$in_call_map && $function_storage && !$function_storage->pure || $callmap_function_pure === \false) { if ($context->mutation_free || $context->external_mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureFunctionCall('Cannot call an impure function from a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $function_name)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } if (!$config->remember_property_assignments_after_call) { $context->removeAllObjectVars(); } } elseif ($function_id && ($function_storage && $function_storage->pure && !$function_storage->assertions && $must_use || $callmap_function_pure === \true && $must_use) && $codebase->find_unused_variables && !$context->inside_conditional && !$context->inside_unset) { if (!$context->inside_assignment && !$context->inside_call && !$context->inside_use) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnusedFunctionCall('The call to ' . $function_id . ' is not used', new \Psalm\CodeLocation($statements_analyzer, $function_name), $function_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { /** @psalm-suppress UndefinedPropertyAssignment */ $stmt->pure = \true; } } } } private static function handleNamedFunction(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $real_stmt, \_HumbugBoxd02f763d3c56\PhpParser\Node\Name $function_name, ?string $function_id, \Psalm\Context $context) : void { $first_arg = isset($stmt->args[0]) ? $stmt->args[0] : null; if ($function_name->parts === ['get_class'] || $function_name->parts === ['gettype'] || $function_name->parts === ['get_debug_type']) { if ($first_arg) { $var = $first_arg->value; if ($var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($var->name)) { $var_id = '$' . $var->name; if (isset($context->vars_in_scope[$var_id])) { if ($function_name->parts === ['get_class']) { $atomic_type = new \Psalm\Type\Atomic\TDependentGetClass($var_id, $context->vars_in_scope[$var_id]->hasMixed() ? \Psalm\Type::getObject() : $context->vars_in_scope[$var_id]); } elseif ($function_name->parts === ['gettype']) { $atomic_type = new \Psalm\Type\Atomic\TDependentGetType($var_id); } else { $atomic_type = new \Psalm\Type\Atomic\TDependentGetDebugType($var_id); } $statements_analyzer->node_data->setType($real_stmt, new \Psalm\Type\Union([$atomic_type])); } } elseif (($var_type = $statements_analyzer->node_data->getType($var)) && ($function_name->parts === ['get_class'] || $function_name->parts === ['get_debug_type'])) { $class_string_types = []; foreach ($var_type->getAtomicTypes() as $class_type) { if ($class_type instanceof \Psalm\Type\Atomic\TNamedObject) { $class_string_types[] = new \Psalm\Type\Atomic\TClassString($class_type->value, clone $class_type); } elseif ($class_type instanceof \Psalm\Type\Atomic\TTemplateParam && $class_type->as->isSingle()) { $as_atomic_type = \array_values($class_type->as->getAtomicTypes())[0]; if ($as_atomic_type instanceof \Psalm\Type\Atomic\TObject) { $class_string_types[] = new \Psalm\Type\Atomic\TTemplateParamClass($class_type->param_name, 'object', null, $class_type->defining_class); } elseif ($as_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $class_string_types[] = new \Psalm\Type\Atomic\TTemplateParamClass($class_type->param_name, $as_atomic_type->value, $as_atomic_type, $class_type->defining_class); } } elseif ($function_name->parts === ['get_class']) { $class_string_types[] = new \Psalm\Type\Atomic\TClassString(); } elseif ($function_name->parts === ['get_debug_type']) { if ($class_type instanceof \Psalm\Type\Atomic\TInt) { $class_string_types[] = new \Psalm\Type\Atomic\TLiteralString('int'); } elseif ($class_type instanceof \Psalm\Type\Atomic\TString) { $class_string_types[] = new \Psalm\Type\Atomic\TLiteralString('string'); } elseif ($class_type instanceof \Psalm\Type\Atomic\TFloat) { $class_string_types[] = new \Psalm\Type\Atomic\TLiteralString('float'); } elseif ($class_type instanceof \Psalm\Type\Atomic\TBool) { $class_string_types[] = new \Psalm\Type\Atomic\TLiteralString('bool'); } elseif ($class_type instanceof \Psalm\Type\Atomic\TClosedResource) { $class_string_types[] = new \Psalm\Type\Atomic\TLiteralString('resource (closed)'); } elseif ($class_type instanceof \Psalm\Type\Atomic\TNull) { $class_string_types[] = new \Psalm\Type\Atomic\TLiteralString('null'); } else { $class_string_types[] = new \Psalm\Type\Atomic\TString(); } } } if ($class_string_types) { $statements_analyzer->node_data->setType($real_stmt, new \Psalm\Type\Union($class_string_types)); } } } elseif ($function_name->parts === ['get_class'] && ($get_class_name = $statements_analyzer->getFQCLN())) { $statements_analyzer->node_data->setType($real_stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClassString($get_class_name, new \Psalm\Type\Atomic\TNamedObject($get_class_name))])); } } if ($function_name->parts === ['method_exists']) { $second_arg = isset($stmt->args[1]) ? $stmt->args[1] : null; if ($first_arg && $first_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $second_arg && $second_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { // do nothing } else { $context->check_methods = \false; } } elseif ($function_name->parts === ['class_exists']) { if ($first_arg) { if ($first_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if (!$codebase->classlikes->classExists($first_arg->value->value)) { $context->phantom_classes[\strtolower($first_arg->value->value)] = \true; } } elseif ($first_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $first_arg->value->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $first_arg->value->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $first_arg->value->name->name === 'class') { $resolved_name = (string) $first_arg->value->class->getAttribute('resolvedName'); if (!$codebase->classlikes->classExists($resolved_name)) { $context->phantom_classes[\strtolower($resolved_name)] = \true; } } } } elseif ($function_name->parts === ['interface_exists']) { if ($first_arg) { if ($first_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $context->phantom_classes[\strtolower($first_arg->value->value)] = \true; } elseif ($first_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $first_arg->value->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $first_arg->value->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $first_arg->value->name->name === 'class') { $resolved_name = (string) $first_arg->value->class->getAttribute('resolvedName'); if (!$codebase->classlikes->interfaceExists($resolved_name)) { $context->phantom_classes[\strtolower($resolved_name)] = \true; } } } } elseif ($function_name->parts === ['file_exists'] && $first_arg) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($first_arg->value, null); if ($var_id) { $context->phantom_files[$var_id] = \true; } } elseif ($function_name->parts === ['extension_loaded']) { if ($first_arg && $first_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if (@\extension_loaded($first_arg->value->value)) { // do nothing } else { $context->check_classes = \false; } } } elseif ($function_name->parts === ['function_exists']) { $context->check_functions = \false; } elseif ($function_name->parts === ['is_callable']) { $context->check_methods = \false; $context->check_functions = \false; } elseif ($function_name->parts === ['defined']) { $context->check_consts = \false; } elseif ($function_name->parts === ['extract']) { $context->check_variables = \false; foreach ($context->vars_in_scope as $var_id => $_) { if ($var_id === '$this' || \strpos($var_id, '[') || \strpos($var_id, '>')) { continue; } $mixed_type = \Psalm\Type::getMixed(); $mixed_type->parent_nodes = $context->vars_in_scope[$var_id]->parent_nodes; $context->vars_in_scope[$var_id] = $mixed_type; $context->assigned_var_ids[$var_id] = \true; $context->possibly_assigned_var_ids[$var_id] = \true; } } elseif ($function_name->parts === ['compact']) { $all_args_string_literals = \true; $new_items = []; foreach ($stmt->args as $arg) { $arg_type = $statements_analyzer->node_data->getType($arg->value); if (!$arg_type || !$arg_type->isSingleStringLiteral()) { $all_args_string_literals = \false; break; } $var_name = $arg_type->getSingleStringLiteral()->value; $new_items[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($var_name, $arg->value->getAttributes()), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($var_name, $arg->value->getAttributes()), \false, $arg->getAttributes()); } if ($all_args_string_literals) { $arr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($new_items, $stmt->getAttributes()); $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $arr, $context); $arr_type = $statements_analyzer->node_data->getType($arr); $statements_analyzer->node_data = $old_node_data; if ($arr_type) { $statements_analyzer->node_data->setType($stmt, $arr_type); } } } elseif ($function_name->parts === ['func_get_args']) { $source = $statements_analyzer->getSource(); if ($statements_analyzer->data_flow_graph && $source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) { if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph) { foreach ($source->param_nodes as $param_node) { $statements_analyzer->data_flow_graph->addPath($param_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'variable-use'); } } } } elseif (\strtolower($function_name->parts[0]) === 'var_dump' || \strtolower($function_name->parts[0]) === 'shell_exec') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ForbiddenCode('Unsafe ' . \implode('', $function_name->parts), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // continue } } elseif (isset($codebase->config->forbidden_functions[\strtolower((string) $function_name)])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ForbiddenCode('You have forbidden the use of ' . $function_name, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // continue } } elseif ($function_name->parts === ['define']) { if ($first_arg) { $fq_const_name = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::getConstName($first_arg->value, $statements_analyzer->node_data, $codebase, $statements_analyzer->getAliases()); if ($fq_const_name !== null && isset($stmt->args[1])) { $second_arg = $stmt->args[1]; $was_in_call = $context->inside_call; $context->inside_call = \true; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $second_arg->value, $context); $context->inside_call = $was_in_call; \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::setConstType($statements_analyzer, $fq_const_name, $statements_analyzer->node_data->getType($second_arg->value) ?: \Psalm\Type::getMixed(), $context); } } else { $context->check_consts = \false; } } elseif ($function_name->parts === ['constant']) { if ($first_arg) { $fq_const_name = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::getConstName($first_arg->value, $statements_analyzer->node_data, $codebase, $statements_analyzer->getAliases()); if ($fq_const_name !== null) { $const_type = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::getConstType($statements_analyzer, $fq_const_name, \true, $context); if ($const_type) { $statements_analyzer->node_data->setType($real_stmt, $const_type); } } } else { $context->check_consts = \false; } } elseif ($first_arg && $function_id && \strpos($function_id, 'is_') === 0 && $function_id !== 'is_a') { $stmt_assertions = $statements_analyzer->node_data->getAssertions($stmt); if ($stmt_assertions !== null) { $assertions = $stmt_assertions; } else { $assertions = \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::processFunctionCall($stmt, $context->self, $statements_analyzer, $codebase, $context->inside_negation); } $changed_vars = []; $referenced_var_ids = \array_map(function (array $_) : bool { return \true; }, $assertions); if ($assertions) { \Psalm\Type\Reconciler::reconcileKeyedTypes($assertions, $assertions, $context->vars_in_scope, $changed_vars, $referenced_var_ids, $statements_analyzer, [], $context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)); } } elseif ($first_arg && $function_id === 'strtolower') { $first_arg_type = $statements_analyzer->node_data->getType($first_arg->value); if ($first_arg_type && \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $first_arg_type, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLowercaseString()]))) { if ($first_arg_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType('The call to strtolower is unnecessary given the docblock type', new \Psalm\CodeLocation($statements_analyzer, $function_name), null), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition('The call to strtolower is unnecessary', new \Psalm\CodeLocation($statements_analyzer, $function_name), null), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } } } >|null */ public static function collect(\Psalm\Codebase $codebase, \Psalm\Storage\ClassLikeStorage $class_storage, \Psalm\Storage\ClassLikeStorage $static_class_storage, ?string $method_name = null, ?\Psalm\Type\Atomic $lhs_type_part = null, ?string $lhs_var_id = null) : ?array { $static_fq_class_name = $static_class_storage->name; $non_trait_class_storage = $class_storage->is_trait ? $static_class_storage : $class_storage; $template_types = $class_storage->template_types; $candidate_class_storages = [$class_storage]; if ($static_class_storage->template_type_extends && $method_name && !empty($non_trait_class_storage->overridden_method_ids[$method_name]) && isset($class_storage->methods[$method_name]) && (!isset($non_trait_class_storage->methods[$method_name]->return_type) || $class_storage->methods[$method_name]->inherited_return_type)) { foreach ($non_trait_class_storage->overridden_method_ids[$method_name] as $overridden_method_id) { $overridden_storage = $codebase->methods->getStorage($overridden_method_id); if (!$overridden_storage->return_type) { continue; } if ($overridden_storage->return_type->isNull()) { continue; } $fq_overridden_class = $overridden_method_id->fq_class_name; $overridden_class_storage = $codebase->classlike_storage_provider->get($fq_overridden_class); $overridden_template_types = $overridden_class_storage->template_types; if (!$template_types) { $template_types = $overridden_template_types; } elseif ($overridden_template_types) { foreach ($overridden_template_types as $template_name => $template_map) { if (isset($template_types[$template_name])) { $template_types[$template_name] = \array_merge($template_types[$template_name], $template_map); } else { $template_types[$template_name] = $template_map; } } } $candidate_class_storages[] = $overridden_class_storage; } } if (!$template_types) { return null; } $class_template_params = []; $e = $static_class_storage->template_type_extends; if ($lhs_type_part instanceof \Psalm\Type\Atomic\TGenericObject) { if ($class_storage === $static_class_storage && $static_class_storage->template_types) { $i = 0; foreach ($static_class_storage->template_types as $type_name => $_) { if (isset($lhs_type_part->type_params[$i])) { if ($lhs_var_id !== '$this' || $static_fq_class_name !== $static_class_storage->name) { $class_template_params[$type_name][$static_class_storage->name] = [$lhs_type_part->type_params[$i]]; } } $i++; } } foreach ($template_types as $type_name => $_) { if (isset($class_template_params[$type_name])) { continue; } if ($class_storage !== $static_class_storage && isset($e[$class_storage->name][$type_name])) { $input_type_extends = $e[$class_storage->name][$type_name]; $output_type_extends = null; foreach ($input_type_extends->getAtomicTypes() as $type_extends_atomic) { if ($type_extends_atomic instanceof \Psalm\Type\Atomic\TTemplateParam) { if (isset($static_class_storage->template_types[$type_extends_atomic->param_name])) { $mapped_offset = \array_search($type_extends_atomic->param_name, \array_keys($static_class_storage->template_types)); if (isset($lhs_type_part->type_params[(int) $mapped_offset])) { $candidate_type = $lhs_type_part->type_params[(int) $mapped_offset]; if (!$output_type_extends) { $output_type_extends = $candidate_type; } else { $output_type_extends = \Psalm\Type::combineUnionTypes($candidate_type, $output_type_extends); } } } elseif (isset($static_class_storage->template_type_extends[$type_extends_atomic->defining_class][$type_extends_atomic->param_name])) { $mapped_offset = \array_search($type_extends_atomic->param_name, \array_keys($static_class_storage->template_type_extends[$type_extends_atomic->defining_class])); if (isset($lhs_type_part->type_params[(int) $mapped_offset])) { $candidate_type = $lhs_type_part->type_params[(int) $mapped_offset]; if (!$output_type_extends) { $output_type_extends = $candidate_type; } else { $output_type_extends = \Psalm\Type::combineUnionTypes($candidate_type, $output_type_extends); } } } } else { if (!$output_type_extends) { $output_type_extends = new \Psalm\Type\Union([$type_extends_atomic]); } else { $output_type_extends = \Psalm\Type::combineUnionTypes(new \Psalm\Type\Union([$type_extends_atomic]), $output_type_extends); } } } if ($lhs_var_id !== '$this' || $static_fq_class_name !== $class_storage->name) { $class_template_params[$type_name][$class_storage->name] = [$output_type_extends ?: \Psalm\Type::getMixed()]; } } if (($lhs_var_id !== '$this' || $static_fq_class_name !== $class_storage->name) && !isset($class_template_params[$type_name])) { $class_template_params[$type_name] = [$class_storage->name => [\Psalm\Type::getMixed()]]; } } } foreach ($template_types as $type_name => $type_map) { foreach ($type_map as [$type]) { foreach ($candidate_class_storages as $candidate_class_storage) { if ($candidate_class_storage !== $static_class_storage && isset($e[$candidate_class_storage->name][$type_name]) && !isset($class_template_params[$type_name][$candidate_class_storage->name])) { $class_template_params[$type_name][$candidate_class_storage->name] = [new \Psalm\Type\Union(self::expandType($codebase, $e[$candidate_class_storage->name][$type_name], $e, $static_class_storage->name, $static_class_storage->template_types))]; } } if ($lhs_var_id !== '$this') { if (!isset($class_template_params[$type_name])) { $class_template_params[$type_name][$class_storage->name] = [$type]; } } } } return $class_template_params; } /** * @param array> $e * @return non-empty-list */ private static function expandType(\Psalm\Codebase $codebase, \Psalm\Type\Union $input_type_extends, array $e, string $static_fq_class_name, ?array $static_template_types) : array { $output_type_extends = []; foreach ($input_type_extends->getAtomicTypes() as $type_extends_atomic) { if ($type_extends_atomic instanceof \Psalm\Type\Atomic\TTemplateParam && ($static_fq_class_name !== $type_extends_atomic->defining_class || !isset($static_template_types[$type_extends_atomic->param_name])) && isset($e[$type_extends_atomic->defining_class][$type_extends_atomic->param_name])) { $output_type_extends = \array_merge($output_type_extends, self::expandType($codebase, $e[$type_extends_atomic->defining_class][$type_extends_atomic->param_name], $e, $static_fq_class_name, $static_template_types)); } elseif ($type_extends_atomic instanceof \Psalm\Type\Atomic\TScalarClassConstant) { $expanded = \Psalm\Internal\Type\TypeExpander::expandAtomic($codebase, $type_extends_atomic, $type_extends_atomic->fq_classlike_name, $type_extends_atomic->fq_classlike_name, null, \true, \true); if ($expanded instanceof \Psalm\Type\Atomic) { $output_type_extends[] = $expanded; } else { foreach ($expanded as $type) { $output_type_extends[] = $type; } } } else { $output_type_extends[] = $type_extends_atomic; } } return $output_type_extends; } } fq_class_name; $method_name_lc = $method_id->method_name; if ($codebase->methods->return_type_provider->has($fq_class_name)) { $return_type_candidate = $codebase->methods->return_type_provider->getReturnType($statements_analyzer, $method_id->fq_class_name, $method_id->method_name, $stmt->args, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->name)); if ($return_type_candidate) { if ($all_intersection_return_type) { $return_type_candidate = \Psalm\Type::intersectUnionTypes($all_intersection_return_type, $return_type_candidate, $codebase) ?: \Psalm\Type::getMixed(); } if (!$result->return_type) { $result->return_type = $return_type_candidate; } else { $result->return_type = \Psalm\Type::combineUnionTypes($return_type_candidate, $result->return_type, $codebase); } \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::checkMethodArgs($method_id, $stmt->args, null, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer); return null; } } if (isset($class_storage->pseudo_methods[$method_name_lc])) { $result->has_valid_method_call_type = \true; $result->existent_method_ids[] = $method_id; $pseudo_method_storage = $class_storage->pseudo_methods[$method_name_lc]; \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, $pseudo_method_storage->params, (string) $method_id, \true, $context); \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::checkArgumentsMatch($statements_analyzer, $stmt->args, null, $pseudo_method_storage->params, $pseudo_method_storage, null, null, new \Psalm\CodeLocation($statements_analyzer, $stmt), $context); if ($pseudo_method_storage->return_type) { $return_type_candidate = clone $pseudo_method_storage->return_type; $return_type_candidate = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type_candidate, $fq_class_name, $fq_class_name, $class_storage->parent_class); if ($all_intersection_return_type) { $return_type_candidate = \Psalm\Type::intersectUnionTypes($all_intersection_return_type, $return_type_candidate, $codebase) ?: \Psalm\Type::getMixed(); } if (!$result->return_type) { $result->return_type = $return_type_candidate; } else { $result->return_type = \Psalm\Type::combineUnionTypes($return_type_candidate, $result->return_type, $codebase); } return null; } } else { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context); if ($class_storage->sealed_methods || $config->seal_all_methods) { $result->non_existent_magic_method_ids[] = $method_id; return null; } } $result->has_valid_method_call_type = \true; $result->existent_method_ids[] = $method_id; $array_values = \array_map( /** * @return PhpParser\Node\Expr\ArrayItem */ function (\_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg) : PhpParser\Node\Expr\ArrayItem { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($arg->value); }, $stmt->args ); $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; return new \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\AtomicCallContext(new \Psalm\Internal\MethodIdentifier($fq_class_name, '__call'), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($method_name_lc)), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($array_values))], $old_node_data); } public static function handleMissingOrMagicMethod(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall $stmt, \Psalm\Internal\MethodIdentifier $method_id, bool $is_interface, \Psalm\Context $context, \Psalm\Config $config, ?\Psalm\Type\Union $all_intersection_return_type, \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\AtomicMethodCallAnalysisResult $result) : void { $fq_class_name = $method_id->fq_class_name; $method_name_lc = $method_id->method_name; $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); if (($is_interface || $config->use_phpdoc_method_without_magic_or_parent) && isset($class_storage->pseudo_methods[$method_name_lc])) { $result->has_valid_method_call_type = \true; $result->existent_method_ids[] = $method_id; $pseudo_method_storage = $class_storage->pseudo_methods[$method_name_lc]; if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, $pseudo_method_storage->params, (string) $method_id, \true, $context) === \false) { return; } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::checkArgumentsMatch($statements_analyzer, $stmt->args, null, $pseudo_method_storage->params, $pseudo_method_storage, null, null, new \Psalm\CodeLocation($statements_analyzer, $stmt->name), $context) === \false) { return; } if ($pseudo_method_storage->return_type) { $return_type_candidate = clone $pseudo_method_storage->return_type; if ($all_intersection_return_type) { $return_type_candidate = \Psalm\Type::intersectUnionTypes($all_intersection_return_type, $return_type_candidate, $codebase) ?: \Psalm\Type::getMixed(); } $return_type_candidate = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type_candidate, $fq_class_name, $fq_class_name, $class_storage->parent_class, \true, \false, $class_storage->final); if (!$result->return_type) { $result->return_type = $return_type_candidate; } else { $result->return_type = \Psalm\Type::combineUnionTypes($return_type_candidate, $result->return_type); } return; } $result->return_type = \Psalm\Type::getMixed(); return; } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context) === \false) { return; } } } methods; $method_id = $codebase_methods->getDeclaringMethodId($method_id); if ($method_id === null) { return null; } $storage = $codebase_methods->getStorage($method_id); if ($storage->deprecated) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedMethod('The method ' . $codebase_methods->getCasedMethodId($method_id) . ' has been marked as deprecated', $code_location, (string) $method_id), $suppressed_issues)) { // continue } } if (!$context->collect_initializations && !$context->collect_mutations) { if (!\Psalm\Internal\Analyzer\NamespaceAnalyzer::isWithin($namespace ?: '', $storage->internal)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InternalMethod('The method ' . $codebase_methods->getCasedMethodId($method_id) . ' is internal to ' . $storage->internal . ' but called from ' . $context->self, $code_location, (string) $method_id), $suppressed_issues)) { // fall through } } } return null; } } */ public $invalid_method_call_types = []; /** * @var array */ public $existent_method_ids = []; /** * @var array */ public $non_existent_class_method_ids = []; /** * @var array */ public $non_existent_interface_method_ids = []; /** * @var array */ public $non_existent_magic_method_ids = []; /** * @var bool */ public $check_visibility = \true; /** * @var bool */ public $too_many_arguments = \true; /** * @var list<\Psalm\Internal\MethodIdentifier> */ public $too_many_arguments_method_ids = []; /** * @var bool */ public $too_few_arguments = \false; /** * @var list<\Psalm\Internal\MethodIdentifier> */ public $too_few_arguments_method_ids = []; } getCodebase(); $codebase_methods = $codebase->methods; $codebase_classlikes = $codebase->classlikes; $fq_classlike_name = $method_id->fq_class_name; $method_name = $method_id->method_name; if ($codebase_methods->visibility_provider->has($fq_classlike_name)) { $method_visible = $codebase_methods->visibility_provider->isMethodVisible($source, $fq_classlike_name, $method_name, $context, $code_location); if ($method_visible === \false) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleMethod('Cannot access method ' . $codebase_methods->getCasedMethodId($method_id) . ' from context ' . $context->self, $code_location), $suppressed_issues)) { return \false; } } elseif ($method_visible === \true) { return \false; } } $declaring_method_id = $codebase_methods->getDeclaringMethodId($method_id); if (!$declaring_method_id) { if ($method_name === '__construct' || $method_id->fq_class_name === 'Closure' && ($method_id->method_name === 'fromcallable' || $method_id->method_name === '__invoke')) { return null; } throw new \UnexpectedValueException('$declaring_method_id not expected to be null here'); } $appearing_method_id = $codebase_methods->getAppearingMethodId($method_id); $appearing_method_class = null; $appearing_class_storage = null; $appearing_method_name = null; if ($appearing_method_id) { $appearing_method_class = $appearing_method_id->fq_class_name; $appearing_method_name = $appearing_method_id->method_name; // if the calling class is the same, we know the method exists, so it must be visible if ($appearing_method_class === $context->self) { return null; } $appearing_class_storage = $codebase->classlike_storage_provider->get($appearing_method_class); } $declaring_method_class = $declaring_method_id->fq_class_name; if ($source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer && \strtolower($declaring_method_class) === \strtolower((string) $source->getFQCLN())) { return null; } $storage = $codebase->methods->getStorage($declaring_method_id); $visibility = $storage->visibility; if ($appearing_method_name && isset($appearing_class_storage->trait_visibility_map[$appearing_method_name])) { $visibility = $appearing_class_storage->trait_visibility_map[$appearing_method_name]; } switch ($visibility) { case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC: return null; case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE: if (!$context->self || $appearing_method_class !== $context->self) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleMethod('Cannot access private method ' . $codebase_methods->getCasedMethodId($method_id) . ' from context ' . $context->self, $code_location), $suppressed_issues)) { return \false; } } return null; case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED: if (!$context->self) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleMethod('Cannot access protected method ' . $method_id, $code_location), $suppressed_issues)) { return \false; } return null; } if ($appearing_method_class && $codebase_classlikes->classExtends($appearing_method_class, $context->self)) { return null; } if ($appearing_method_class && !$codebase_classlikes->classExtends($context->self, $appearing_method_class)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleMethod('Cannot access protected method ' . $codebase_methods->getCasedMethodId($method_id) . ' from context ' . $context->self, $code_location), $suppressed_issues)) { return \false; } } } return null; } } $args */ public static function fetch(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall $stmt, \Psalm\Context $context, \Psalm\Internal\MethodIdentifier $method_id, ?\Psalm\Internal\MethodIdentifier $declaring_method_id, \Psalm\Internal\MethodIdentifier $premixin_method_id, string $cased_method_id, \Psalm\Type\Atomic $lhs_type_part, ?\Psalm\Type\Atomic $static_type, array $args, \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\AtomicMethodCallAnalysisResult $result, \Psalm\Internal\Type\TemplateResult $template_result) : \Psalm\Type\Union { $call_map_id = $declaring_method_id ?: $method_id; $fq_class_name = $method_id->fq_class_name; $method_name = $method_id->method_name; if ($codebase->methods->return_type_provider->has($premixin_method_id->fq_class_name)) { $return_type_candidate = $codebase->methods->return_type_provider->getReturnType($statements_analyzer, $premixin_method_id->fq_class_name, $premixin_method_id->method_name, $stmt->args, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->name), $lhs_type_part instanceof \Psalm\Type\Atomic\TGenericObject ? $lhs_type_part->type_params : null); if ($return_type_candidate) { return $return_type_candidate; } } if ($declaring_method_id && $declaring_method_id !== $method_id) { $declaring_fq_class_name = $declaring_method_id->fq_class_name; $declaring_method_name = $declaring_method_id->method_name; if ($codebase->methods->return_type_provider->has($declaring_fq_class_name)) { $return_type_candidate = $codebase->methods->return_type_provider->getReturnType($statements_analyzer, $declaring_fq_class_name, $declaring_method_name, $stmt->args, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->name), $lhs_type_part instanceof \Psalm\Type\Atomic\TGenericObject ? $lhs_type_part->type_params : null, $fq_class_name, $method_name); if ($return_type_candidate) { return $return_type_candidate; } } } $class_storage = $codebase->methods->getClassLikeStorageForMethod($method_id); if (\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap((string) $call_map_id)) { if (($template_result->upper_bounds || $class_storage->stubbed) && ($method_storage = $class_storage->methods[$method_id->method_name] ?? null) && $method_storage->return_type) { $return_type_candidate = clone $method_storage->return_type; $return_type_candidate = self::replaceTemplateTypes($return_type_candidate, $template_result, $method_id, \count($stmt->args), $codebase); } else { $callmap_callables = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallablesFromCallMap((string) $call_map_id); if (!$callmap_callables || $callmap_callables[0]->return_type === null) { throw new \UnexpectedValueException('Shouldn’t get here'); } $return_type_candidate = $callmap_callables[0]->return_type; } if (($call_map_id->fq_class_name === 'Iterator' || $call_map_id->fq_class_name === 'IteratorIterator' || $call_map_id->fq_class_name === 'Generator' || $call_map_id->fq_class_name === 'SplDoublyLinkedList' || $call_map_id->fq_class_name === 'SplObjectStorage') && $method_name === 'current') { if ($stmt->getAttributes()) { $return_type_candidate->addType(new \Psalm\Type\Atomic\TNull()); $return_type_candidate->ignore_nullable_issues = \true; } } if ($return_type_candidate->isFalsable()) { $return_type_candidate->ignore_falsable_issues = \true; } $return_type_candidate = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type_candidate, $fq_class_name, $static_type, $class_storage->parent_class); } else { $self_fq_class_name = $fq_class_name; $return_type_candidate = $codebase->methods->getMethodReturnType($method_id, $self_fq_class_name, $statements_analyzer, $args); if ($return_type_candidate) { $return_type_candidate = clone $return_type_candidate; $return_type_candidate = self::replaceTemplateTypes($return_type_candidate, $template_result, $method_id, \count($stmt->args), $codebase); $return_type_candidate = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type_candidate, $self_fq_class_name, $static_type, $class_storage->parent_class, \true, \false, $static_type instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classlike_storage_provider->get($static_type->value)->final); $return_type_location = $codebase->methods->getMethodReturnTypeLocation($method_id, $secondary_return_type_location); if ($secondary_return_type_location) { $return_type_location = $secondary_return_type_location; } $config = \Psalm\Config::getInstance(); // only check the type locally if it's defined externally if ($return_type_location && !$config->isInProjectDirs($return_type_location->file_path)) { $return_type_candidate->check($statements_analyzer, new \Psalm\CodeLocation($statements_analyzer, $stmt), $statements_analyzer->getSuppressedIssues(), $context->phantom_classes, \true, \false, \false, $context->calling_method_id); } } else { $result->returns_by_ref = $result->returns_by_ref || $codebase->methods->getMethodReturnsByRef($method_id); } } if (!$return_type_candidate) { $return_type_candidate = $method_name === '__tostring' ? \Psalm\Type::getString() : \Psalm\Type::getMixed(); } self::taintMethodCallResult($statements_analyzer, $return_type_candidate, $stmt->name, $stmt->var, $method_id, $declaring_method_id, $cased_method_id, $context); return $return_type_candidate; } public static function taintMethodCallResult(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Type\Union $return_type_candidate, \_HumbugBoxd02f763d3c56\PhpParser\Node $name_expr, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $var_expr, \Psalm\Internal\MethodIdentifier $method_id, ?\Psalm\Internal\MethodIdentifier $declaring_method_id, string $cased_method_id, \Psalm\Context $context) : void { $codebase = $statements_analyzer->getCodebase(); if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && $declaring_method_id && !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $method_storage = $codebase->methods->getStorage($declaring_method_id); $node_location = new \Psalm\CodeLocation($statements_analyzer, $name_expr); $method_call_node = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodReturn((string) $method_id, $cased_method_id, $method_storage->signature_return_type_location ?: $method_storage->location, $method_storage->specialize_call ? $node_location : null); $statements_analyzer->data_flow_graph->addNode($method_call_node); $return_type_candidate->parent_nodes = [$method_call_node->id => $method_call_node]; if ($method_storage->specialize_call) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($var_expr, null, $statements_analyzer); if ($var_id && isset($context->vars_in_scope[$var_id])) { $var_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_id, new \Psalm\CodeLocation($statements_analyzer, $var_expr)); $statements_analyzer->data_flow_graph->addNode($var_node); $statements_analyzer->data_flow_graph->addPath($method_call_node, $var_node, 'method-call-' . $method_id->method_name); $stmt_var_type = clone $context->vars_in_scope[$var_id]; if ($context->vars_in_scope[$var_id]->parent_nodes) { foreach ($context->vars_in_scope[$var_id]->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $var_node, '='); } } $stmt_var_type->parent_nodes = [$var_node->id => $var_node]; $context->vars_in_scope[$var_id] = $stmt_var_type; } } if ($method_storage->taint_source_types) { $method_node = \Psalm\Internal\DataFlow\TaintSource::getForMethodReturn((string) $method_id, $cased_method_id, $method_storage->signature_return_type_location ?: $method_storage->location); $method_node->taints = $method_storage->taint_source_types; $statements_analyzer->data_flow_graph->addSource($method_node); } } } private static function replaceTemplateTypes(\Psalm\Type\Union $return_type_candidate, \Psalm\Internal\Type\TemplateResult $template_result, \Psalm\Internal\MethodIdentifier $method_id, int $arg_count, \Psalm\Codebase $codebase) : \Psalm\Type\Union { if ($template_result->template_types) { $bindable_template_types = $return_type_candidate->getTemplateTypes(); foreach ($bindable_template_types as $template_type) { if ($template_type->defining_class !== $method_id->fq_class_name && !isset($template_result->upper_bounds[$template_type->param_name][$template_type->defining_class])) { if ($template_type->param_name === 'TFunctionArgCount') { $template_result->upper_bounds[$template_type->param_name] = ['fn-' . \strtolower((string) $method_id) => [\Psalm\Type::getInt(\false, $arg_count), 0]]; } else { $template_result->upper_bounds[$template_type->param_name] = [$template_type->defining_class => [\Psalm\Type::getEmpty(), 0]]; } } } } if ($template_result->upper_bounds) { $return_type_candidate = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type_candidate, null, null, null); $return_type_candidate->replaceTemplateTypesWithArgTypes($template_result, $codebase); } return $return_type_candidate; } } config; if ($lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && !$lhs_type_part->as->isMixed()) { $extra_types = $lhs_type_part->extra_types; $lhs_type_part = \array_values($lhs_type_part->as->getAtomicTypes())[0]; $lhs_type_part->from_docblock = \true; if ($lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $lhs_type_part->extra_types = $extra_types; } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TObject && $extra_types) { $lhs_type_part = \array_shift($extra_types); if ($extra_types) { $lhs_type_part->extra_types = $extra_types; } } $result->has_mixed_method_call = \true; } $source = $statements_analyzer->getSource(); if (!$lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { self::handleInvalidClass($statements_analyzer, $codebase, $stmt, $lhs_type_part, $lhs_var_id, $context, $is_intersection, $result); return; } if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } $result->has_valid_method_call_type = \true; $fq_class_name = $lhs_type_part->value; $is_mock = \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::isMock($fq_class_name); $result->has_mock = $result->has_mock || $is_mock; if ($fq_class_name === 'static') { $fq_class_name = (string) $context->self; } if ($is_mock || $context->isPhantomClass($fq_class_name)) { $result->return_type = \Psalm\Type::getMixed(); \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context); return; } if ($lhs_var_id === '$this') { $does_class_exist = \true; } else { $does_class_exist = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_class_name, new \Psalm\CodeLocation($source, $stmt->var), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues(), \true, \false, \true, $lhs_type_part->from_docblock); } if (!$does_class_exist) { return; } $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $result->check_visibility = $result->check_visibility && !$class_storage->override_method_visibility; $intersection_types = $lhs_type_part->getIntersectionTypes(); $all_intersection_return_type = null; $all_intersection_existent_method_ids = []; if ($intersection_types) { foreach ($intersection_types as $intersection_type) { $intersection_result = clone $result; /** @var ?Type\Union */ $intersection_result->return_type = null; self::analyze($statements_analyzer, $stmt, $codebase, $context, $intersection_type, $lhs_type_part, \true, $lhs_var_id, $intersection_result); $result->returns_by_ref = $intersection_result->returns_by_ref; $result->has_mock = $intersection_result->has_mock; $result->has_valid_method_call_type = $intersection_result->has_valid_method_call_type; $result->has_mixed_method_call = $intersection_result->has_mixed_method_call; $result->invalid_method_call_types = $intersection_result->invalid_method_call_types; $result->check_visibility = $intersection_result->check_visibility; $result->too_many_arguments = $intersection_result->too_many_arguments; $all_intersection_existent_method_ids = \array_merge($all_intersection_existent_method_ids, $intersection_result->existent_method_ids); if ($intersection_result->return_type) { if (!$all_intersection_return_type || $all_intersection_return_type->isMixed()) { $all_intersection_return_type = $intersection_result->return_type; } else { $all_intersection_return_type = \Psalm\Type::intersectUnionTypes($all_intersection_return_type, $intersection_result->return_type, $codebase) ?: \Psalm\Type::getMixed(); } } } } if (!$stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { if (!$context->ignore_variable_method) { $codebase->analyzer->addMixedMemberName(\strtolower($fq_class_name) . '::', $context->calling_method_id ?: $statements_analyzer->getFileName()); } \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context); $result->return_type = \Psalm\Type::getMixed(); return; } $method_name_lc = \strtolower($stmt->name->name); $method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, $method_name_lc); $cased_method_id = $fq_class_name . '::' . $stmt->name->name; $intersection_method_id = $intersection_types ? '(' . $lhs_type_part . ')' . '::' . $stmt->name->name : null; $args = $stmt->args; $old_node_data = null; $naive_method_id = $method_id; $naive_method_exists = $codebase->methods->methodExists($method_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($source, $stmt->name) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath(), \false); if ($naive_method_exists && $fq_class_name === 'Closure' && $method_name_lc === '__invoke') { $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_function_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall($stmt->var, $stmt->args, $stmt->getAttributes()); \Psalm\Internal\Analyzer\Statements\Expression\Call\FunctionCallAnalyzer::analyze($statements_analyzer, $fake_function_call, $context); $function_return = $statements_analyzer->node_data->getType($fake_function_call) ?: \Psalm\Type::getMixed(); $statements_analyzer->node_data = $old_node_data; if (!$result->return_type) { $result->return_type = $function_return; } else { $result->return_type = \Psalm\Type::combineUnionTypes($function_return, $result->return_type); } return; } $fake_method_exists = \false; if (!$naive_method_exists && $codebase->methods->existence_provider->has($fq_class_name)) { $method_exists = $codebase->methods->existence_provider->doesMethodExist($fq_class_name, $method_id->method_name, $source, null); if ($method_exists) { $fake_method_exists = \true; } } if (!$naive_method_exists) { [$lhs_type_part, $class_storage, $naive_method_exists, $method_id, $fq_class_name] = self::handleMixins($class_storage, $lhs_type_part, $method_name_lc, $codebase, $context, $method_id, $source, $stmt, $statements_analyzer, $fq_class_name, $lhs_var_id); } if ($fake_method_exists && $codebase->methods->methodExists(new \Psalm\Internal\MethodIdentifier($fq_class_name, '__call')) || !$naive_method_exists || !\Psalm\Internal\Analyzer\MethodAnalyzer::isMethodVisible($method_id, $context, $statements_analyzer->getSource())) { $interface_has_method = \false; if ($class_storage->abstract && $class_storage->class_implements) { foreach ($class_storage->class_implements as $interface_fqcln_lc => $_) { $interface_storage = $codebase->classlike_storage_provider->get($interface_fqcln_lc); if (isset($interface_storage->methods[$method_name_lc])) { $interface_has_method = \true; $fq_class_name = $interface_storage->name; $method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, $method_name_lc); break; } } } if (!$interface_has_method && $codebase->methods->methodExists(new \Psalm\Internal\MethodIdentifier($fq_class_name, '__call'), $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($source, $stmt->name) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath())) { $new_call_context = \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MissingMethodCallHandler::handleMagicMethod($statements_analyzer, $codebase, $stmt, $method_id, $class_storage, $context, $config, $all_intersection_return_type, $result); if ($new_call_context) { if ($method_id === $new_call_context->method_id) { return; } $method_id = $new_call_context->method_id; $args = $new_call_context->args; $old_node_data = $statements_analyzer->node_data; } else { return; } } } $source_source = $statements_analyzer->getSource(); /** * @var \Psalm\Internal\Analyzer\ClassLikeAnalyzer|null */ $classlike_source = $source_source->getSource(); $classlike_source_fqcln = $classlike_source ? $classlike_source->getFQCLN() : null; if ($lhs_var_id === '$this' && $context->self && $classlike_source_fqcln && $fq_class_name !== $context->self && $codebase->methods->methodExists(new \Psalm\Internal\MethodIdentifier($context->self, $method_name_lc))) { $method_id = new \Psalm\Internal\MethodIdentifier($context->self, $method_name_lc); $cased_method_id = $context->self . '::' . $stmt->name->name; $fq_class_name = $context->self; } $is_interface = \false; if ($codebase->interfaceExists($fq_class_name)) { $is_interface = \true; } $source_method_id = $source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer ? $source->getId() : null; $corrected_method_exists = $naive_method_exists && $method_id === $naive_method_id || $method_id !== $naive_method_id && $codebase->methods->methodExists($method_id, $context->calling_method_id, $codebase->collect_locations && $method_id !== $source_method_id ? new \Psalm\CodeLocation($source, $stmt->name) : null); if (!$corrected_method_exists || $config->use_phpdoc_method_without_magic_or_parent && isset($class_storage->pseudo_methods[$method_name_lc])) { \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MissingMethodCallHandler::handleMissingOrMagicMethod($statements_analyzer, $codebase, $stmt, $method_id, $is_interface, $context, $config, $all_intersection_return_type, $result); if ($all_intersection_return_type && $all_intersection_existent_method_ids) { $result->existent_method_ids = \array_merge($result->existent_method_ids, $all_intersection_existent_method_ids); if (!$result->return_type) { $result->return_type = $all_intersection_return_type; } else { $result->return_type = \Psalm\Type::combineUnionTypes($all_intersection_return_type, $result->return_type); } return; } if (!$is_interface && !$config->use_phpdoc_method_without_magic_or_parent || !isset($class_storage->pseudo_methods[$method_name_lc])) { if ($is_interface) { $result->non_existent_interface_method_ids[] = $intersection_method_id ?: $cased_method_id; } else { $result->non_existent_class_method_ids[] = $intersection_method_id ?: $cased_method_id; } } return; } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->name, $method_id . '()'); } if ($context->collect_initializations && $context->calling_method_id) { [$calling_method_class] = \explode('::', $context->calling_method_id); $codebase->file_reference_provider->addMethodReferenceToClassMember($calling_method_class . '::__construct', \strtolower((string) $method_id)); } $result->existent_method_ids[] = $method_id; if ($stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && ($context->collect_initializations || $context->collect_mutations) && $stmt->var->name === 'this' && $source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) { self::collectSpecialInformation($source, $stmt->name->name, $context); } $fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name); $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $parent_source = $statements_analyzer->getSource(); $class_template_params = \Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector::collect($codebase, $codebase->methods->getClassLikeStorageForMethod($method_id), $class_storage, $method_name_lc, $lhs_type_part, $lhs_var_id); if ($lhs_var_id === '$this' && $parent_source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) { $grandparent_source = $parent_source->getSource(); if ($grandparent_source instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) { $fq_trait_name = $grandparent_source->getFQCLN(); $fq_trait_name_lc = \strtolower($fq_trait_name); $trait_storage = $codebase->classlike_storage_provider->get($fq_trait_name_lc); if (isset($trait_storage->methods[$method_name_lc])) { $trait_method_id = new \Psalm\Internal\MethodIdentifier($trait_storage->name, $method_name_lc); $class_template_params = \Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector::collect($codebase, $codebase->methods->getClassLikeStorageForMethod($trait_method_id), $class_storage, $method_name_lc, $lhs_type_part, $lhs_var_id); } } } $template_result = new \Psalm\Internal\Type\TemplateResult([], $class_template_params ?: []); if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentMapPopulator::recordArgumentPositions($statements_analyzer, $stmt, $codebase, (string) $method_id); } if (self::checkMethodArgs($method_id, $args, $template_result, $context, new \Psalm\CodeLocation($source, $stmt->name), $statements_analyzer) === \false) { return; } $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); $can_memoize = \false; $return_type_candidate = \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodCallReturnTypeFetcher::fetch($statements_analyzer, $codebase, $stmt, $context, $method_id, $declaring_method_id, $naive_method_id, $cased_method_id, $lhs_type_part, $static_type, $args, $result, $template_result); $in_call_map = \Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap((string) ($declaring_method_id ?: $method_id)); if (!$in_call_map) { $name_code_location = new \Psalm\CodeLocation($statements_analyzer, $stmt->name); if ($result->check_visibility) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodVisibilityAnalyzer::analyze($method_id, $context, $statements_analyzer->getSource(), $name_code_location, $statements_analyzer->getSuppressedIssues()) === \false) { self::updateResultReturnType($result, $return_type_candidate, $all_intersection_return_type, $method_name_lc, $codebase); return; } } \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodCallProhibitionAnalyzer::analyze($codebase, $context, $method_id, $statements_analyzer->getNamespace(), $name_code_location, $statements_analyzer->getSuppressedIssues()); $getter_return_type = self::getMagicGetterOrSetterProperty($statements_analyzer, $stmt, $context, $fq_class_name); if ($getter_return_type) { $return_type_candidate = $getter_return_type; } } try { $method_storage = $codebase->methods->getStorage($declaring_method_id ?: $method_id); } catch (\UnexpectedValueException $e) { $method_storage = null; } if ($method_storage) { if (!$context->collect_mutations && !$context->collect_initializations) { $can_memoize = \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodCallPurityAnalyzer::analyze($statements_analyzer, $codebase, $stmt, $lhs_var_id, $cased_method_id, $method_id, $method_storage, $class_storage, $context, $config); } $has_packed_arg = \false; foreach ($args as $arg) { $has_packed_arg = $has_packed_arg || $arg->unpack; } if (!$has_packed_arg) { $has_variadic_param = $method_storage->variadic; foreach ($method_storage->params as $param) { $has_variadic_param = $has_variadic_param || $param->is_variadic; } for ($i = \count($args), $j = \count($method_storage->params); $i < $j; ++$i) { $param = $method_storage->params[$i]; if (!$param->is_optional && !$param->is_variadic && !$in_call_map) { $result->too_few_arguments = \true; $result->too_few_arguments_method_ids[] = $declaring_method_id ?: $method_id; } } if ($has_variadic_param || \count($method_storage->params) >= \count($args) || $in_call_map) { $result->too_many_arguments = \false; } else { $result->too_many_arguments_method_ids[] = $declaring_method_id ?: $method_id; } } $class_template_params = $template_result->upper_bounds; if ($method_storage->assertions) { self::applyAssertionsToContext($stmt->name, \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->var, null, $statements_analyzer), $method_storage->assertions, $args, $class_template_params, $context, $statements_analyzer); } if ($method_storage->if_true_assertions) { $statements_analyzer->node_data->setIfTrueAssertions($stmt, \array_map(function (\Psalm\Storage\Assertion $assertion) use($class_template_params, $lhs_var_id) : Assertion { return $assertion->getUntemplatedCopy($class_template_params ?: [], $lhs_var_id); }, $method_storage->if_true_assertions)); } if ($method_storage->if_false_assertions) { $statements_analyzer->node_data->setIfFalseAssertions($stmt, \array_map(function (\Psalm\Storage\Assertion $assertion) use($class_template_params, $lhs_var_id) : Assertion { return $assertion->getUntemplatedCopy($class_template_params ?: [], $lhs_var_id); }, $method_storage->if_false_assertions)); } } if ($old_node_data) { $statements_analyzer->node_data = $old_node_data; } if (!$args && $lhs_var_id) { if ($config->memoize_method_calls || $can_memoize) { $method_var_id = $lhs_var_id . '->' . $method_name_lc . '()'; if (isset($context->vars_in_scope[$method_var_id])) { $return_type_candidate = clone $context->vars_in_scope[$method_var_id]; if ($can_memoize) { /** @psalm-suppress UndefinedPropertyAssignment */ $stmt->pure = \true; } } else { $context->vars_in_scope[$method_var_id] = $return_type_candidate; } } } if ($codebase->methods_to_rename) { $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); foreach ($codebase->methods_to_rename as $original_method_id => $new_method_name) { if ($declaring_method_id && \strtolower((string) $declaring_method_id) === $original_method_id) { $file_manipulations = [new \Psalm\FileManipulation((int) $stmt->name->getAttribute('startFilePos'), (int) $stmt->name->getAttribute('endFilePos') + 1, $new_method_name)]; \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } } if ($config->after_method_checks) { $file_manipulations = []; $appearing_method_id = $codebase->methods->getAppearingMethodId($method_id); $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if ($appearing_method_id !== null && $declaring_method_id !== null) { foreach ($config->after_method_checks as $plugin_fq_class_name) { $plugin_fq_class_name::afterMethodCallAnalysis($stmt, (string) $method_id, (string) $appearing_method_id, (string) $declaring_method_id, $context, $statements_analyzer, $codebase, $file_manipulations, $return_type_candidate); } } if ($file_manipulations) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } self::updateResultReturnType($result, $return_type_candidate, $all_intersection_return_type, $method_name_lc, $codebase); } private static function updateResultReturnType(\Psalm\Internal\Analyzer\Statements\Expression\Call\Method\AtomicMethodCallAnalysisResult $result, ?\Psalm\Type\Union $return_type_candidate, ?\Psalm\Type\Union $all_intersection_return_type, string $method_name, \Psalm\Codebase $codebase) : void { if ($return_type_candidate) { if ($all_intersection_return_type) { $return_type_candidate = \Psalm\Type::intersectUnionTypes($all_intersection_return_type, $return_type_candidate, $codebase) ?: \Psalm\Type::getMixed(); } if (!$result->return_type) { $result->return_type = $return_type_candidate; } else { $result->return_type = \Psalm\Type::combineUnionTypes($return_type_candidate, $result->return_type); } } elseif ($all_intersection_return_type) { if (!$result->return_type) { $result->return_type = $all_intersection_return_type; } else { $result->return_type = \Psalm\Type::combineUnionTypes($all_intersection_return_type, $result->return_type); } } elseif ($method_name === '__tostring') { $result->return_type = \Psalm\Type::getString(); } else { $result->return_type = \Psalm\Type::getMixed(); } } private static function handleInvalidClass(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall $stmt, \Psalm\Type\Atomic $lhs_type_part, ?string $lhs_var_id, \Psalm\Context $context, bool $is_intersection, \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\AtomicMethodCallAnalysisResult $result) : void { switch (\get_class($lhs_type_part)) { case \Psalm\Type\Atomic\TNull::class: case \Psalm\Type\Atomic\TFalse::class: // handled above return; case \Psalm\Type\Atomic\TTemplateParam::class: case \Psalm\Type\Atomic\TEmptyMixed::class: case \Psalm\Type\Atomic\TEmpty::class: case \Psalm\Type\Atomic\TMixed::class: case \Psalm\Type\Atomic\TNonEmptyMixed::class: case \Psalm\Type\Atomic\TObject::class: case \Psalm\Type\Atomic\TObjectWithProperties::class: if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } $result->has_mixed_method_call = \true; if ($lhs_type_part instanceof \Psalm\Type\Atomic\TObjectWithProperties && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && isset($lhs_type_part->methods[$stmt->name->name])) { $result->existent_method_ids[] = $lhs_type_part->methods[$stmt->name->name]; } elseif (!$is_intersection) { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $codebase->analyzer->addMixedMemberName(\strtolower($stmt->name->name), $context->calling_method_id ?: $statements_analyzer->getFileName()); } if ($context->check_methods) { $message = 'Cannot determine the type of the object' . ' on the left hand side of this expression'; if ($lhs_var_id) { $message = 'Cannot determine the type of ' . $lhs_var_id; if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $message .= ' when calling method ' . $stmt->name->name; } } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedMethodCall($message, new \Psalm\CodeLocation($statements_analyzer, $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context) === \false) { return; } $result->return_type = \Psalm\Type::getMixed(); return; default: $result->invalid_method_call_types[] = (string) $lhs_type_part; return; } } /** * Check properties accessed with magic getters and setters. * If `@psalm-seal-properties` is set, they must be defined. * If an `@property` annotation is specified, the setter must set something with the correct * type. */ private static function getMagicGetterOrSetterProperty(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall $stmt, \Psalm\Context $context, string $fq_class_name) : ?\Psalm\Type\Union { if (!$stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { return null; } $method_name = \strtolower($stmt->name->name); if (!\in_array($method_name, ['__get', '__set'], \true)) { return null; } $codebase = $statements_analyzer->getCodebase(); $first_arg_value = $stmt->args[0]->value; if (!$first_arg_value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { return null; } $prop_name = $first_arg_value->value; $property_id = $fq_class_name . '::$' . $prop_name; $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $codebase->properties->propertyExists($property_id, $method_name === '__get', $statements_analyzer, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)); switch ($method_name) { case '__set': // If `@psalm-seal-properties` is set, the property must be defined with // a `@property` annotation if ($class_storage->sealed_properties && !isset($class_storage->pseudo_property_set_types['$' . $prop_name]) && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedThisPropertyAssignment('Instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } // If a `@property` annotation is set, the type of the value passed to the // magic setter must match the annotation. $second_arg_type = $statements_analyzer->node_data->getType($stmt->args[1]->value); if (isset($class_storage->pseudo_property_set_types['$' . $prop_name]) && $second_arg_type) { $pseudo_set_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $class_storage->pseudo_property_set_types['$' . $prop_name], $fq_class_name, new \Psalm\Type\Atomic\TNamedObject($fq_class_name), $class_storage->parent_class); $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $type_match_found = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $second_arg_type, $pseudo_set_type, $second_arg_type->ignore_nullable_issues, $second_arg_type->ignore_falsable_issues, $union_comparison_results); if ($union_comparison_results->type_coerced) { if ($union_comparison_results->type_coerced_from_mixed) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedPropertyTypeCoercion($prop_name . ' expects \'' . $pseudo_set_type->getId() . '\', ' . ' parent type `' . $second_arg_type . '` provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PropertyTypeCoercion($prop_name . ' expects \'' . $pseudo_set_type->getId() . '\', ' . ' parent type `' . $second_arg_type . '` provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } } if (!$type_match_found && !$union_comparison_results->type_coerced_from_mixed) { if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::canBeContainedBy($codebase, $second_arg_type, $pseudo_set_type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidPropertyAssignmentValue($prop_name . ' with declared type \'' . $pseudo_set_type . '\' cannot be assigned possibly different type \'' . $second_arg_type . '\'', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidPropertyAssignmentValue($prop_name . ' with declared type \'' . $pseudo_set_type . '\' cannot be assigned type \'' . $second_arg_type . '\'', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } break; case '__get': // If `@psalm-seal-properties` is set, the property must be defined with // a `@property` annotation if ($class_storage->sealed_properties && !isset($class_storage->pseudo_property_get_types['$' . $prop_name]) && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedThisPropertyFetch('Instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } if (isset($class_storage->pseudo_property_get_types['$' . $prop_name])) { return clone $class_storage->pseudo_property_get_types['$' . $prop_name]; } break; } return null; } /** * @param lowercase-string $method_name_lc * @return array{Type\Atomic, \Psalm\Storage\ClassLikeStorage, bool, MethodIdentifier, string} */ private static function handleMixins(\Psalm\Storage\ClassLikeStorage $class_storage, \Psalm\Type\Atomic $lhs_type_part, string $method_name_lc, \Psalm\Codebase $codebase, \Psalm\Context $context, \Psalm\Internal\MethodIdentifier $method_id, \Psalm\StatementsSource $source, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall $stmt, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $fq_class_name, ?string $lhs_var_id) { $naive_method_exists = \false; if ($class_storage->templatedMixins && $lhs_type_part instanceof \Psalm\Type\Atomic\TGenericObject && $class_storage->template_types) { $template_type_keys = \array_keys($class_storage->template_types); foreach ($class_storage->templatedMixins as $mixin) { $param_position = \array_search($mixin->param_name, $template_type_keys); if ($param_position !== \false && isset($lhs_type_part->type_params[$param_position])) { $current_type_param = $lhs_type_part->type_params[$param_position]; if ($current_type_param->isSingle()) { $lhs_type_part_new = \array_values($current_type_param->getAtomicTypes())[0]; if ($lhs_type_part_new instanceof \Psalm\Type\Atomic\TNamedObject) { $new_method_id = new \Psalm\Internal\MethodIdentifier($lhs_type_part_new->value, $method_name_lc); $mixin_class_storage = $codebase->classlike_storage_provider->get($lhs_type_part_new->value); if ($codebase->methods->methodExists($new_method_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($source, $stmt->name) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath())) { $lhs_type_part = clone $lhs_type_part_new; $class_storage = $mixin_class_storage; $naive_method_exists = \true; $method_id = $new_method_id; } elseif (isset($mixin_class_storage->pseudo_methods[$method_name_lc])) { $lhs_type_part = clone $lhs_type_part_new; $class_storage = $mixin_class_storage; $method_id = $new_method_id; } } } } } } elseif ($class_storage->mixin_declaring_fqcln && $class_storage->namedMixins) { foreach ($class_storage->namedMixins as $mixin) { if (!$class_storage->mixin_declaring_fqcln) { continue; } $new_method_id = new \Psalm\Internal\MethodIdentifier($mixin->value, $method_name_lc); if ($codebase->methods->methodExists($new_method_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($source, $stmt->name) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath())) { $mixin_declaring_class_storage = $codebase->classlike_storage_provider->get($class_storage->mixin_declaring_fqcln); $mixin_class_template_params = \Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector::collect($codebase, $mixin_declaring_class_storage, $codebase->classlike_storage_provider->get($fq_class_name), null, $lhs_type_part, $lhs_var_id); $lhs_type_part = clone $mixin; $lhs_type_part->replaceTemplateTypesWithArgTypes(new \Psalm\Internal\Type\TemplateResult([], $mixin_class_template_params ?: []), $codebase); $lhs_type_expanded = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, new \Psalm\Type\Union([$lhs_type_part]), $mixin_declaring_class_storage->name, $fq_class_name, $class_storage->parent_class, \true, \false, $class_storage->final); $new_lhs_type_part = \array_values($lhs_type_expanded->getAtomicTypes())[0]; if ($new_lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $lhs_type_part = $new_lhs_type_part; } $mixin_class_storage = $codebase->classlike_storage_provider->get($mixin->value); $fq_class_name = $mixin_class_storage->name; $mixin_class_storage->mixin_declaring_fqcln = $class_storage->mixin_declaring_fqcln; $class_storage = $mixin_class_storage; $naive_method_exists = \true; $method_id = $new_method_id; } } } return [$lhs_type_part, $class_storage, $naive_method_exists, $method_id, $fq_class_name]; } } */ public $args; /** @var NodeDataProvider */ public $node_data; /** @param list $args */ public function __construct(\Psalm\Internal\MethodIdentifier $method_id, array $args, \Psalm\Internal\Provider\NodeDataProvider $node_data) { $this->method_id = $method_id; $this->args = $args; $this->node_data = $node_data; } } external_mutation_free && $statements_analyzer->node_data->isPureCompatible($stmt->var); if ($context->pure && !$method_storage->mutation_free && !$method_pure_compatible) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call a non-mutation-free method ' . $cased_method_id . ' from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($context->mutation_free && !$method_storage->mutation_free && !$method_pure_compatible) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call an possibly-mutating method ' . $cased_method_id . ' from a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($context->external_mutation_free && !$method_storage->mutation_free && $method_id->fq_class_name !== $context->self && !$method_pure_compatible) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call an possibly-mutating method ' . $cased_method_id . ' from a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif (($method_storage->mutation_free || $method_storage->external_mutation_free && (isset($stmt->var->external_mutation_free) || isset($stmt->var->pure))) && !$context->inside_unset) { if ($method_storage->mutation_free && (!$method_storage->mutation_free_inferred || $method_storage->final)) { if ($context->inside_conditional && !$method_storage->assertions && !$method_storage->if_true_assertions) { /** @psalm-suppress UndefinedPropertyAssignment */ $stmt->pure = \true; } $can_memoize = \true; } if ($codebase->find_unused_variables && !$context->inside_conditional && !$context->inside_use) { if (!$context->inside_assignment && !$context->inside_call) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnusedMethodCall('The call to ' . $cased_method_id . ' is not used', new \Psalm\CodeLocation($statements_analyzer, $stmt->name), (string) $method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif (!$method_storage->mutation_free_inferred) { /** @psalm-suppress UndefinedPropertyAssignment */ $stmt->pure = \true; } } } if ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations && !$method_storage->mutation_free && !$method_pure_compatible) { if (!$method_storage->mutation_free) { $statements_analyzer->getSource()->inferred_has_mutation = \true; } $statements_analyzer->getSource()->inferred_impure = \true; } if (!$config->remember_property_assignments_after_call && !$method_storage->mutation_free && !$method_pure_compatible) { $context->removeAllObjectVars(); } elseif ($method_storage->this_property_mutations) { foreach ($method_storage->this_property_mutations as $name => $_) { $mutation_var_id = $lhs_var_id . '->' . $name; $this_property_didnt_exist = $lhs_var_id === '$this' && isset($context->vars_in_scope[$mutation_var_id]) && !isset($class_storage->declaring_property_ids[$name]); $context->remove($mutation_var_id); if ($this_property_didnt_exist) { $context->vars_in_scope[$mutation_var_id] = \Psalm\Type::getMixed(); } } } return $can_memoize; } } getFileAnalyzer(); $codebase = $statements_analyzer->getCodebase(); $source = $statements_analyzer->getSource(); $config = $codebase->config; if ($stmt->class instanceof \_HumbugBoxd02f763d3c56\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 ($stmt->class->parts[0] === 'parent') { $child_fq_class_name = $context->self; $class_storage = $child_fq_class_name ? $codebase->classlike_storage_provider->get($child_fq_class_name) : null; if (!$class_storage || !$class_storage->parent_class) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParentNotFound('Cannot call method on parent as this class does not extend another', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } return \true; } $fq_class_name = $class_storage->parent_class; $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $fq_class_name = $class_storage->name; } elseif ($context->self) { if ($stmt->class->parts[0] === 'static' && isset($context->vars_in_scope['$this'])) { $fq_class_name = (string) $context->vars_in_scope['$this']; $lhs_type = clone $context->vars_in_scope['$this']; } else { $fq_class_name = $context->self; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NonStaticSelfCall('Cannot use ' . $stmt->class->parts[0] . ' outside class context', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } return \true; } if ($context->isPhantomClass($fq_class_name)) { return \true; } } elseif ($context->check_classes) { $aliases = $statements_analyzer->getAliases(); if ($context->calling_method_id && !$stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified) { $codebase->file_reference_provider->addMethodReferenceToClassMember($context->calling_method_id, 'use:' . $stmt->class->parts[0] . ':' . \md5($statements_analyzer->getFilePath())); } $fq_class_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($stmt->class, $aliases); if ($context->isPhantomClass($fq_class_name)) { return \true; } $does_class_exist = \false; if ($context->self) { $self_storage = $codebase->classlike_storage_provider->get($context->self); if (isset($self_storage->used_traits[\strtolower($fq_class_name)])) { $fq_class_name = $context->self; $does_class_exist = \true; } } if (!isset($context->phantom_classes[\strtolower($fq_class_name)]) && !$does_class_exist) { $does_class_exist = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_class_name, new \Psalm\CodeLocation($source, $stmt->class), !$context->collect_initializations && !$context->collect_mutations ? $context->self : null, !$context->collect_initializations && !$context->collect_mutations ? $context->calling_method_id : null, $statements_analyzer->getSuppressedIssues(), \false, \false, \false); } if (!$does_class_exist) { return $does_class_exist !== \false; } } if ($codebase->store_node_types && $fq_class_name && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->class, $fq_class_name); } if ($fq_class_name && !$lhs_type) { $lhs_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($fq_class_name)]); } } else { $was_inside_use = $context->inside_use; $context->inside_use = \true; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context); $context->inside_use = $was_inside_use; $lhs_type = $statements_analyzer->node_data->getType($stmt->class) ?: \Psalm\Type::getMixed(); } if (!$lhs_type) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context) === \false) { return \false; } return \true; } $has_mock = \false; $moved_call = \false; foreach ($lhs_type->getAtomicTypes() as $lhs_type_part) { $intersection_types = []; if ($lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $fq_class_name = $lhs_type_part->value; if (!\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_class_name, new \Psalm\CodeLocation($source, $stmt->class), !$context->collect_initializations && !$context->collect_mutations ? $context->self : null, !$context->collect_initializations && !$context->collect_mutations ? $context->calling_method_id : null, $statements_analyzer->getSuppressedIssues(), $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \count($stmt->class->parts) === 1 && \in_array(\strtolower($stmt->class->parts[0]), ['self', 'static'], \true))) { return \false; } $intersection_types = $lhs_type_part->extra_types; } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TClassString && $lhs_type_part->as_type) { $fq_class_name = $lhs_type_part->as_type->value; if (!\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_class_name, new \Psalm\CodeLocation($source, $stmt->class), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues(), \false)) { return \false; } $intersection_types = $lhs_type_part->as_type->extra_types; } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TDependentGetClass && !$lhs_type_part->as_type->hasObject()) { $fq_class_name = 'object'; if ($lhs_type_part->as_type->hasObjectType() && $lhs_type_part->as_type->isSingle()) { foreach ($lhs_type_part->as_type->getAtomicTypes() as $typeof_type_atomic) { if ($typeof_type_atomic instanceof \Psalm\Type\Atomic\TNamedObject) { $fq_class_name = $typeof_type_atomic->value; } } } if ($fq_class_name === 'object') { continue; } } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TLiteralClassString) { $fq_class_name = $lhs_type_part->value; if (!\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_class_name, new \Psalm\CodeLocation($source, $stmt->class), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues(), \false)) { return \false; } } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParam && !$lhs_type_part->as->isMixed() && !$lhs_type_part->as->hasObject()) { $fq_class_name = null; foreach ($lhs_type_part->as->getAtomicTypes() as $generic_param_type) { if (!$generic_param_type instanceof \Psalm\Type\Atomic\TNamedObject) { continue 2; } $fq_class_name = $generic_param_type->value; break; } if (!$fq_class_name) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedClass('Type ' . $lhs_type_part->as . ' cannot be called as a class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), (string) $lhs_type_part), $statements_analyzer->getSuppressedIssues())) { // fall through } continue; } } else { if ($lhs_type_part instanceof \Psalm\Type\Atomic\TMixed || $lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParam || $lhs_type_part instanceof \Psalm\Type\Atomic\TClassString) { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $codebase->analyzer->addMixedMemberName(\strtolower($stmt->name->name), $context->calling_method_id ?: $statements_analyzer->getFileName()); } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedMethodCall('Cannot call method on an unknown class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } continue; } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TString) { if ($config->allow_string_standin_for_class && !$lhs_type_part instanceof \Psalm\Type\Atomic\TNumericString) { continue; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidStringClass('String cannot be used as a class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } continue; } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TNull && $lhs_type->ignore_nullable_issues) { continue; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedClass('Type ' . $lhs_type_part . ' cannot be called as a class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), (string) $lhs_type_part), $statements_analyzer->getSuppressedIssues())) { // fall through } continue; } $fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name); $is_mock = \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::isMock($fq_class_name); $has_mock = $has_mock || $is_mock; if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && !$is_mock) { $method_name_lc = \strtolower($stmt->name->name); $method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, $method_name_lc); $cased_method_id = $fq_class_name . '::' . $stmt->name->name; if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentMapPopulator::recordArgumentPositions($statements_analyzer, $stmt, $codebase, (string) $method_id); } $args = $stmt->args; if ($intersection_types && !$codebase->methods->methodExists($method_id)) { foreach ($intersection_types as $intersection_type) { if (!$intersection_type instanceof \Psalm\Type\Atomic\TNamedObject) { continue; } $intersection_method_id = new \Psalm\Internal\MethodIdentifier($intersection_type->value, $method_name_lc); if ($codebase->methods->methodExists($intersection_method_id)) { $method_id = $intersection_method_id; $cased_method_id = $intersection_type->value . '::' . $stmt->name->name; $fq_class_name = $intersection_type->value; break; } } } $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $naive_method_exists = $codebase->methods->methodExists($method_id, !$context->collect_initializations && !$context->collect_mutations ? $context->calling_method_id : null, $codebase->collect_locations ? new \Psalm\CodeLocation($source, $stmt->name) : null, $statements_analyzer, $statements_analyzer->getFilePath(), \false); $fake_method_exists = \false; if (!$naive_method_exists && $codebase->methods->existence_provider->has($fq_class_name)) { $method_exists = $codebase->methods->existence_provider->doesMethodExist($fq_class_name, $method_id->method_name, $source, null); if ($method_exists) { $fake_method_exists = \true; } } if (!$naive_method_exists && $class_storage->mixin_declaring_fqcln && $class_storage->namedMixins) { foreach ($class_storage->namedMixins as $mixin) { $new_method_id = new \Psalm\Internal\MethodIdentifier($mixin->value, $method_name_lc); if ($codebase->methods->methodExists($new_method_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($source, $stmt->name) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath())) { $mixin_candidates = []; foreach ($class_storage->templatedMixins as $mixin_candidate) { $mixin_candidates[] = clone $mixin_candidate; } foreach ($class_storage->namedMixins as $mixin_candidate) { $mixin_candidates[] = clone $mixin_candidate; } $mixin_candidates_no_generic = \array_filter($mixin_candidates, function ($check) : bool { return !$check instanceof \Psalm\Type\Atomic\TGenericObject; }); // $mixin_candidates_no_generic will only be empty when there are TGenericObject entries. // In that case, Union will be initialized with an empty array but // replaced with non-empty types in the following loop. /** @psalm-suppress ArgumentTypeCoercion */ $mixin_candidate_type = new \Psalm\Type\Union($mixin_candidates_no_generic); foreach ($mixin_candidates as $tGenericMixin) { if (!$tGenericMixin instanceof \Psalm\Type\Atomic\TGenericObject) { continue; } $mixin_declaring_class_storage = $codebase->classlike_storage_provider->get($class_storage->mixin_declaring_fqcln); $new_mixin_candidate_type = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\AtomicPropertyFetchAnalyzer::localizePropertyType($codebase, new \Psalm\Type\Union([$lhs_type_part]), $tGenericMixin, $class_storage, $mixin_declaring_class_storage); foreach ($mixin_candidate_type->getAtomicTypes() as $type) { $new_mixin_candidate_type->addType($type); } $mixin_candidate_type = $new_mixin_candidate_type; } $new_lhs_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $mixin_candidate_type, $fq_class_name, $fq_class_name, $class_storage->parent_class, \true, \false, $class_storage->final); $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $context->vars_in_scope['$tmp_mixin_var'] = $new_lhs_type; $fake_method_call_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable('tmp_mixin_var', $stmt->class->getAttributes()), $stmt->name, $stmt->args, $stmt->getAttributes()); if (\Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_method_call_expr, $context) === \false) { return \false; } $fake_method_call_type = $statements_analyzer->node_data->getType($fake_method_call_expr); $statements_analyzer->node_data = $old_data_provider; $statements_analyzer->node_data->setType($stmt, $fake_method_call_type ?: \Psalm\Type::getMixed()); return \true; } } } if (!$naive_method_exists || !\Psalm\Internal\Analyzer\MethodAnalyzer::isMethodVisible($method_id, $context, $statements_analyzer->getSource()) || $fake_method_exists || isset($class_storage->pseudo_static_methods[$method_name_lc]) && ($config->use_phpdoc_method_without_magic_or_parent || $class_storage->parent_class)) { $callstatic_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, '__callstatic'); if ($codebase->methods->methodExists($callstatic_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($source, $stmt->name) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath())) { if ($codebase->methods->return_type_provider->has($fq_class_name)) { $return_type_candidate = $codebase->methods->return_type_provider->getReturnType($statements_analyzer, $method_id->fq_class_name, $method_id->method_name, $stmt->args, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->name), null, null, \strtolower($stmt->name->name)); if ($return_type_candidate) { \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::checkMethodArgs($method_id, $stmt->args, null, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer); $statements_analyzer->node_data->setType($stmt, $return_type_candidate); return \true; } } if (isset($class_storage->pseudo_static_methods[$method_name_lc])) { $pseudo_method_storage = $class_storage->pseudo_static_methods[$method_name_lc]; if (self::checkPseudoMethod($statements_analyzer, $stmt, $method_id, $fq_class_name, $args, $class_storage, $pseudo_method_storage, $context) === \false) { return \false; } if ($pseudo_method_storage->return_type) { return \true; } } else { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $args, null, null, \true, $context) === \false) { return \false; } } $array_values = \array_map(function (\_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg) : PhpParser\Node\Expr\ArrayItem { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($arg->value); }, $args); $args = [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_((string) $method_id)), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($array_values))]; $method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, '__callstatic'); } elseif (isset($class_storage->pseudo_static_methods[$method_name_lc]) && ($config->use_phpdoc_method_without_magic_or_parent || $class_storage->parent_class)) { $pseudo_method_storage = $class_storage->pseudo_static_methods[$method_name_lc]; if (self::checkPseudoMethod($statements_analyzer, $stmt, $method_id, $fq_class_name, $args, $class_storage, $pseudo_method_storage, $context) === \false) { return \false; } if ($pseudo_method_storage->return_type) { return \true; } } if (!$context->check_methods) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context) === \false) { return \false; } return \true; } } $does_method_exist = \Psalm\Internal\Analyzer\MethodAnalyzer::checkMethodExists($codebase, $method_id, new \Psalm\CodeLocation($source, $stmt), $statements_analyzer->getSuppressedIssues(), $context->calling_method_id); if (!$does_method_exist) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context) === \false) { return \false; } if ($codebase->alter_code && $fq_class_name && !$moved_call) { $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $stmt->class, $fq_class_name, $context->calling_method_id); } return \true; } $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); if ($class_storage->user_defined && $context->self && ($context->collect_mutations || $context->collect_initializations)) { $appearing_method_id = $codebase->methods->getAppearingMethodId($method_id); if (!$appearing_method_id) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedMethod('Method ' . $method_id . ' does not exist', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), (string) $method_id), $statements_analyzer->getSuppressedIssues())) { // } return \true; } $appearing_method_class_name = $appearing_method_id->fq_class_name; if ($codebase->classExtends($context->self, $appearing_method_class_name)) { $old_context_include_location = $context->include_location; $old_self = $context->self; $context->include_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $context->self = $appearing_method_class_name; if ($context->collect_mutations) { $file_analyzer->getMethodMutations($method_id, $context); } else { // collecting initializations $local_vars_in_scope = []; $local_vars_possibly_in_scope = []; foreach ($context->vars_in_scope as $var => $_) { if (\strpos($var, '$this->') !== 0 && $var !== '$this') { $local_vars_in_scope[$var] = $context->vars_in_scope[$var]; } } foreach ($context->vars_possibly_in_scope as $var => $_) { if (\strpos($var, '$this->') !== 0 && $var !== '$this') { $local_vars_possibly_in_scope[$var] = $context->vars_possibly_in_scope[$var]; } } if (!isset($context->initialized_methods[(string) $method_id])) { if ($context->initialized_methods === null) { $context->initialized_methods = []; } $context->initialized_methods[(string) $method_id] = \true; $file_analyzer->getMethodMutations($method_id, $context); foreach ($local_vars_in_scope as $var => $type) { $context->vars_in_scope[$var] = $type; } foreach ($local_vars_possibly_in_scope as $var => $type) { $context->vars_possibly_in_scope[$var] = $type; } } } $context->include_location = $old_context_include_location; $context->self = $old_self; } } if ($class_storage->deprecated && $fq_class_name !== $context->self) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedClass($fq_class_name . ' is marked deprecated', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $fq_class_name), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($context->self && !\Psalm\Internal\Analyzer\NamespaceAnalyzer::isWithin($context->self, $class_storage->internal)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InternalClass($fq_class_name . ' is internal to ' . $class_storage->internal . ' but called from ' . $context->self, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $fq_class_name), $statements_analyzer->getSuppressedIssues())) { // fall through } } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodVisibilityAnalyzer::analyze($method_id, $context, $statements_analyzer->getSource(), new \Psalm\CodeLocation($source, $stmt), $statements_analyzer->getSuppressedIssues()) === \false) { return \false; } if ((!$stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name || $stmt->class->parts[0] !== 'parent' || $statements_analyzer->isStatic()) && (!$context->self || $statements_analyzer->isStatic() || !$codebase->classExtends($context->self, $fq_class_name))) { if (\Psalm\Internal\Analyzer\MethodAnalyzer::checkStatic($method_id, $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->class->parts[0]) === 'self' || $context->self === $fq_class_name, !$statements_analyzer->isStatic(), $codebase, new \Psalm\CodeLocation($source, $stmt), $statements_analyzer->getSuppressedIssues(), $is_dynamic_this_method) === \false) { // fall through } if ($is_dynamic_this_method) { $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_method_call_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable('this', $stmt->class->getAttributes()), $stmt->name, $stmt->args, $stmt->getAttributes()); if (\Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_method_call_expr, $context) === \false) { return \false; } $fake_method_call_type = $statements_analyzer->node_data->getType($fake_method_call_expr); $statements_analyzer->node_data = $old_data_provider; if ($fake_method_call_type) { $statements_analyzer->node_data->setType($stmt, $fake_method_call_type); } return \true; } } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodCallProhibitionAnalyzer::analyze($codebase, $context, $method_id, $statements_analyzer->getNamespace(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues()) === \false) { // fall through } $found_generic_params = \Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector::collect($codebase, $class_storage, $class_storage, $method_name_lc, $lhs_type_part, null); if ($found_generic_params && $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->class->parts === ['parent'] && $context->self && ($self_class_storage = $codebase->classlike_storage_provider->get($context->self)) && $self_class_storage->template_type_extends) { foreach ($self_class_storage->template_type_extends as $template_fq_class_name => $extended_types) { foreach ($extended_types as $type_key => $extended_type) { if (!\is_string($type_key)) { continue; } if (isset($found_generic_params[$type_key][$template_fq_class_name])) { $found_generic_params[$type_key][$template_fq_class_name][0] = clone $extended_type; continue; } foreach ($extended_type->getAtomicTypes() as $t) { if ($t instanceof \Psalm\Type\Atomic\TTemplateParam && isset($found_generic_params[$t->param_name][$t->defining_class])) { $found_generic_params[$type_key][$template_fq_class_name] = [$found_generic_params[$t->param_name][$t->defining_class][0]]; } else { $found_generic_params[$type_key][$template_fq_class_name] = [clone $extended_type]; break; } } } } } $template_result = new \Psalm\Internal\Type\TemplateResult([], $found_generic_params ?: []); if (self::checkMethodArgs($method_id, $args, $template_result, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer) === \false) { return \false; } $fq_class_name = $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->class->parts === ['parent'] ? (string) $statements_analyzer->getFQCLN() : $fq_class_name; $self_fq_class_name = $fq_class_name; $return_type_candidate = null; if ($codebase->methods->return_type_provider->has($fq_class_name)) { $return_type_candidate = $codebase->methods->return_type_provider->getReturnType($statements_analyzer, $fq_class_name, $stmt->name->name, $stmt->args, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->name)); } $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if (!$return_type_candidate && $declaring_method_id && (string) $declaring_method_id !== (string) $method_id) { $declaring_fq_class_name = $declaring_method_id->fq_class_name; $declaring_method_name = $declaring_method_id->method_name; if ($codebase->methods->return_type_provider->has($declaring_fq_class_name)) { $return_type_candidate = $codebase->methods->return_type_provider->getReturnType($statements_analyzer, $declaring_fq_class_name, $declaring_method_name, $stmt->args, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->name), null, $fq_class_name, $stmt->name->name); } } if (!$return_type_candidate) { $return_type_candidate = $codebase->methods->getMethodReturnType($method_id, $self_fq_class_name, $statements_analyzer, $args); if ($return_type_candidate) { $return_type_candidate = clone $return_type_candidate; if ($template_result->template_types) { $bindable_template_types = $return_type_candidate->getTemplateTypes(); foreach ($bindable_template_types as $template_type) { if (!isset($template_result->upper_bounds[$template_type->param_name][$template_type->defining_class])) { if ($template_type->param_name === 'TFunctionArgCount') { $template_result->upper_bounds[$template_type->param_name] = ['fn-' . \strtolower((string) $method_id) => [\Psalm\Type::getInt(\false, \count($stmt->args)), 0]]; } else { $template_result->upper_bounds[$template_type->param_name] = [$template_type->defining_class => [\Psalm\Type::getEmpty(), 0]]; } } } } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $static_type = $lhs_type_part; } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $static_type = new \Psalm\Type\Atomic\TTemplateParam($lhs_type_part->param_name, $lhs_type_part->as_type ? new \Psalm\Type\Union([$lhs_type_part->as_type]) : \Psalm\Type::getObject(), $lhs_type_part->defining_class); } else { $static_type = $fq_class_name; } if ($template_result->upper_bounds) { $return_type_candidate = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type_candidate, null, null, null); $return_type_candidate->replaceTemplateTypesWithArgTypes($template_result, $codebase); } $return_type_candidate = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type_candidate, $self_fq_class_name, $static_type, $class_storage->parent_class, \true, \false, \is_string($static_type) && $static_type !== $context->self); $return_type_location = $codebase->methods->getMethodReturnTypeLocation($method_id, $secondary_return_type_location); if ($secondary_return_type_location) { $return_type_location = $secondary_return_type_location; } // only check the type locally if it's defined externally if ($return_type_location && !$config->isInProjectDirs($return_type_location->file_path)) { $return_type_candidate->check($statements_analyzer, new \Psalm\CodeLocation($source, $stmt), $statements_analyzer->getSuppressedIssues(), $context->phantom_classes, \true, \false, \false, $context->calling_method_id); } } } $method_storage = $codebase->methods->getUserMethodStorage($method_id); if ($method_storage) { if ($method_storage->abstract && $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && (!$context->self || !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $context->vars_in_scope['$this'] ?? new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($context->self)]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($method_id->fq_class_name)])))) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\AbstractMethodCall('Cannot call an abstract static method ' . $method_id . ' directly', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } return \true; } if (!$context->inside_throw) { if ($context->pure && !$method_storage->pure) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call an impure method from a pure context', new \Psalm\CodeLocation($source, $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($context->mutation_free && !$method_storage->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call an possibly-mutating method from a mutation-free context', new \Psalm\CodeLocation($source, $stmt->name)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations && !$method_storage->pure) { if (!$method_storage->mutation_free) { $statements_analyzer->getSource()->inferred_has_mutation = \true; } $statements_analyzer->getSource()->inferred_impure = \true; } } $generic_params = $template_result->upper_bounds; if ($method_storage->assertions) { self::applyAssertionsToContext($stmt->name, null, $method_storage->assertions, $stmt->args, $generic_params, $context, $statements_analyzer); } if ($method_storage->if_true_assertions) { $statements_analyzer->node_data->setIfTrueAssertions($stmt, \array_map(function (\Psalm\Storage\Assertion $assertion) use($generic_params) : Assertion { return $assertion->getUntemplatedCopy($generic_params, null); }, $method_storage->if_true_assertions)); } if ($method_storage->if_false_assertions) { $statements_analyzer->node_data->setIfFalseAssertions($stmt, \array_map(function (\Psalm\Storage\Assertion $assertion) use($generic_params) : Assertion { return $assertion->getUntemplatedCopy($generic_params, null); }, $method_storage->if_false_assertions)); } } if ($codebase->alter_code) { foreach ($codebase->call_transforms as $original_pattern => $transformation) { if ($declaring_method_id && \strtolower((string) $declaring_method_id) . '\\((.*\\))' === $original_pattern) { if (\strpos($transformation, '($1)') === \strlen($transformation) - 4 && $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $new_method_id = \substr($transformation, 0, -4); $old_declaring_fq_class_name = $declaring_method_id->fq_class_name; [$new_fq_class_name, $new_method_name] = \explode('::', $new_method_id); if ($codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $stmt->class, $new_fq_class_name, $context->calling_method_id, \strtolower($old_declaring_fq_class_name) !== \strtolower($new_fq_class_name), $stmt->class->parts[0] === 'self')) { $moved_call = \true; } $file_manipulations = []; $file_manipulations[] = new \Psalm\FileManipulation((int) $stmt->name->getAttribute('startFilePos'), (int) $stmt->name->getAttribute('endFilePos') + 1, $new_method_name); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } } } if ($config->after_method_checks) { $file_manipulations = []; $appearing_method_id = $codebase->methods->getAppearingMethodId($method_id); if ($appearing_method_id !== null && $declaring_method_id) { foreach ($config->after_method_checks as $plugin_fq_class_name) { $plugin_fq_class_name::afterMethodCallAnalysis($stmt, (string) $method_id, (string) $appearing_method_id, (string) $declaring_method_id, $context, $source, $codebase, $file_manipulations, $return_type_candidate); } } if ($file_manipulations) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } $return_type_candidate = $return_type_candidate ?: \Psalm\Type::getMixed(); self::taintReturnType($statements_analyzer, $stmt, $method_id, $cased_method_id, $return_type_candidate, $method_storage); if ($stmt_type = $statements_analyzer->node_data->getType($stmt)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::combineUnionTypes($stmt_type, $return_type_candidate)); } else { $statements_analyzer->node_data->setType($stmt, $return_type_candidate); } } else { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { $was_inside_use = $context->inside_use; $context->inside_use = \true; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->name, $context); $context->inside_use = $was_inside_use; } if (!$context->ignore_variable_method) { $codebase->analyzer->addMixedMemberName(\strtolower($fq_class_name) . '::', $context->calling_method_id ?: $statements_analyzer->getFileName()); } if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $stmt->args, null, null, \true, $context) === \false) { return \false; } } if ($codebase->alter_code && $fq_class_name && !$moved_call && $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && !\in_array($stmt->class->parts[0], ['parent', 'static'])) { $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $stmt->class, $fq_class_name, $context->calling_method_id, \false, $stmt->class->parts[0] === 'self'); } if ($codebase->store_node_types && $method_id && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->name, $method_id . '()'); } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations && ($stmt_type = $statements_analyzer->node_data->getType($stmt))) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt->name, $stmt_type->getId(), $stmt); } } if ($method_id === null) { return self::checkMethodArgs($method_id, $stmt->args, null, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer); } if (!$config->remember_property_assignments_after_call && !$context->collect_initializations) { $context->removeAllObjectVars(); } if (!$statements_analyzer->node_data->getType($stmt)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } return \true; } private static function taintReturnType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall $stmt, \Psalm\Internal\MethodIdentifier $method_id, string $cased_method_id, \Psalm\Type\Union $return_type_candidate, ?\Psalm\Storage\MethodStorage $method_storage) : void { if (!$statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph || \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { return; } $code_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $method_location = $method_storage ? $method_storage->signature_return_type_location ?: $method_storage->location : null; if ($method_storage && $method_storage->specialize_call) { $method_source = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodReturn((string) $method_id, $cased_method_id, $method_location, $code_location); } else { $method_source = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodReturn((string) $method_id, $cased_method_id, $method_location); } $statements_analyzer->data_flow_graph->addNode($method_source); $return_type_candidate->parent_nodes = [$method_source->id => $method_source]; if ($method_storage && $method_storage->taint_source_types) { $method_node = \Psalm\Internal\DataFlow\TaintSource::getForMethodReturn((string) $method_id, $cased_method_id, $method_storage->signature_return_type_location ?: $method_storage->location); $method_node->taints = $method_storage->taint_source_types; $statements_analyzer->data_flow_graph->addSource($method_node); } } /** * @param array $args * @return false|null */ private static function checkPseudoMethod(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall $stmt, \Psalm\Internal\MethodIdentifier $method_id, string $fq_class_name, array $args, \Psalm\Storage\ClassLikeStorage $class_storage, \Psalm\Storage\MethodStorage $pseudo_method_storage, \Psalm\Context $context) : ?bool { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $args, $pseudo_method_storage->params, (string) $method_id, \true, $context) === \false) { return \false; } $codebase = $statements_analyzer->getCodebase(); if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::checkArgumentsMatch($statements_analyzer, $args, $method_id, $pseudo_method_storage->params, $pseudo_method_storage, null, null, new \Psalm\CodeLocation($statements_analyzer, $stmt), $context) === \false) { return \false; } $method_storage = null; if ($statements_analyzer->data_flow_graph) { try { $method_storage = $codebase->methods->getStorage($method_id); \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::analyze($statements_analyzer, $args, $method_storage->params, (string) $method_id, \true, $context); \Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::checkArgumentsMatch($statements_analyzer, $args, $method_id, $method_storage->params, $method_storage, null, null, new \Psalm\CodeLocation($statements_analyzer, $stmt), $context); } catch (\Exception $e) { // do nothing } } if ($pseudo_method_storage->return_type) { $return_type_candidate = clone $pseudo_method_storage->return_type; $return_type_candidate = \Psalm\Internal\Type\TypeExpander::expandUnion($statements_analyzer->getCodebase(), $return_type_candidate, $fq_class_name, $fq_class_name, $class_storage->parent_class); if ($method_storage) { self::taintReturnType($statements_analyzer, $stmt, $method_id, (string) $method_id, $return_type_candidate, $method_storage); } $stmt_type = $statements_analyzer->node_data->getType($stmt); if (!$stmt_type) { $statements_analyzer->node_data->setType($stmt, $return_type_candidate); } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::combineUnionTypes($return_type_candidate, $stmt_type)); } } return null; } } > $class_generic_params * @return false|null */ public static function checkArgumentMatches(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, ?string $cased_method_id, ?string $self_fq_class_name, ?string $static_fq_class_name, \Psalm\CodeLocation $function_call_location, ?\Psalm\Storage\FunctionLikeParameter $function_param, int $argument_offset, int $unpacked_argument_offset, bool $allow_named_args, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg, ?\Psalm\Type\Union $arg_value_type, \Psalm\Context $context, array $class_generic_params, ?\Psalm\Internal\Type\TemplateResult $template_result, bool $specialize_taint, bool $in_call_map) : ?bool { $codebase = $statements_analyzer->getCodebase(); if (!$arg_value_type) { if ($function_param && !$function_param->by_ref) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } $param_type = $function_param->type; if ($function_param->is_variadic && $param_type && $param_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var TList|TArray */ $array_type = $param_type->getAtomicTypes()['array']; if ($array_type instanceof \Psalm\Type\Atomic\TList) { $param_type = $array_type->type_param; } else { $param_type = $array_type->type_params[1]; } } if ($param_type && !$param_type->hasMixed()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArgument('Argument ' . ($argument_offset + 1) . ' of ' . $cased_method_id . ' cannot be mixed, expecting ' . $param_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $arg->value), $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } return null; } if (!$function_param) { return null; } if ($function_param->expect_variable && $arg_value_type->isSingleStringLiteral() && !$arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst && !$arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { $values = \preg_split('//u', $arg_value_type->getSingleStringLiteral()->value, -1, \PREG_SPLIT_NO_EMPTY); $prev_ord = 0; $gt_count = 0; foreach ($values as $value) { /** * @var int * @psalm-suppress UnnecessaryVarAnnotation */ $ord = \mb_ord($value); if ($ord > $prev_ord) { $gt_count++; } $prev_ord = $ord; } if (\count($values) < 12 || $gt_count / \count($values) < 0.8) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidLiteralArgument('Argument ' . ($argument_offset + 1) . ' of ' . $cased_method_id . ' expects a non-literal value, ' . $arg_value_type->getId() . ' provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $arg->value), $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if (self::checkFunctionLikeTypeMatches($statements_analyzer, $codebase, $cased_method_id, $self_fq_class_name, $static_fq_class_name, $function_call_location, $function_param, $allow_named_args, $arg_value_type, $argument_offset, $unpacked_argument_offset, $arg, $context, $class_generic_params, $template_result, $specialize_taint, $in_call_map) === \false) { return \false; } return null; } /** * @param array> $class_generic_params * @param array> $generic_params * @param array> $template_types * @return false|null */ private static function checkFunctionLikeTypeMatches(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Codebase $codebase, ?string $cased_method_id, ?string $self_fq_class_name, ?string $static_fq_class_name, \Psalm\CodeLocation $function_call_location, \Psalm\Storage\FunctionLikeParameter $function_param, bool $allow_named_args, \Psalm\Type\Union $arg_type, int $argument_offset, int $unpacked_argument_offset, \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg $arg, \Psalm\Context $context, ?array $class_generic_params, ?\Psalm\Internal\Type\TemplateResult $template_result, bool $specialize_taint, bool $in_call_map) : ?bool { if (!$function_param->type) { if (!$codebase->infer_types_from_usage && !$statements_analyzer->data_flow_graph) { return null; } $param_type = \Psalm\Type::getMixed(); } else { $param_type = clone $function_param->type; } $bindable_template_params = []; if ($template_result) { $bindable_template_params = $param_type->getTemplateTypes(); } if ($class_generic_params) { $empty_generic_params = []; $empty_template_result = new \Psalm\Internal\Type\TemplateResult($class_generic_params, $empty_generic_params); $arg_value_type = $statements_analyzer->node_data->getType($arg->value); $param_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($param_type, $empty_template_result, $codebase, $statements_analyzer, $arg_value_type, $argument_offset, $context->self ?: 'fn-' . $context->calling_function_id); $arg_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($arg_type, $empty_template_result, $codebase, $statements_analyzer, $arg_value_type, $argument_offset, $context->self ?: 'fn-' . $context->calling_function_id); } if ($template_result && $template_result->template_types) { $arg_type_param = $arg_type; if ($arg->unpack) { $arg_type_param = null; foreach ($arg_type->getAtomicTypes() as $arg_atomic_type) { if ($arg_atomic_type instanceof \Psalm\Type\Atomic\TArray || $arg_atomic_type instanceof \Psalm\Type\Atomic\TList || $arg_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($arg_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $arg_type_param = $arg_atomic_type->getGenericValueType(); } elseif ($arg_atomic_type instanceof \Psalm\Type\Atomic\TList) { $arg_type_param = $arg_atomic_type->type_param; } else { $arg_type_param = $arg_atomic_type->type_params[1]; } } elseif ($arg_atomic_type instanceof \Psalm\Type\Atomic\TIterable) { $arg_type_param = $arg_atomic_type->type_params[1]; } elseif ($arg_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { \Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer::getKeyValueParamsForTraversableObject($arg_atomic_type, $codebase, $key_type, $arg_type_param); } } if (!$arg_type_param) { $arg_type_param = \Psalm\Type::getMixed(); $arg_type_param->parent_nodes = $arg_type->parent_nodes; } } $param_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($param_type, $template_result, $codebase, $statements_analyzer, $arg_type_param, $argument_offset, $context->self, $context->calling_method_id ?: $context->calling_function_id); foreach ($bindable_template_params as $template_type) { if (!isset($template_result->upper_bounds[$template_type->param_name][$template_type->defining_class]) && !isset($template_result->lower_bounds[$template_type->param_name][$template_type->defining_class])) { $template_result->upper_bounds[$template_type->param_name][$template_type->defining_class] = [clone $template_type->as, 0]; } } } $parent_class = null; $classlike_storage = null; $static_classlike_storage = null; if ($self_fq_class_name) { $classlike_storage = $codebase->classlike_storage_provider->get($self_fq_class_name); $parent_class = $classlike_storage->parent_class; $static_classlike_storage = $classlike_storage; if ($static_fq_class_name && $static_fq_class_name !== $self_fq_class_name) { $static_classlike_storage = $codebase->classlike_storage_provider->get($static_fq_class_name); } } $fleshed_out_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $param_type, $classlike_storage ? $classlike_storage->name : null, $static_classlike_storage ? $static_classlike_storage->name : null, $parent_class, \true, \false, $static_classlike_storage ? $static_classlike_storage->final : \false); $fleshed_out_signature_type = $function_param->signature_type ? \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $function_param->signature_type, $classlike_storage ? $classlike_storage->name : null, $static_classlike_storage ? $static_classlike_storage->name : null, $parent_class) : null; $unpacked_atomic_array = null; if ($arg->unpack) { if ($arg_type->hasMixed()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArgument('Argument ' . ($argument_offset + 1) . ' of ' . $cased_method_id . ' cannot be ' . $arg_type->getId() . ', expecting array', new \Psalm\CodeLocation($statements_analyzer->getSource(), $arg->value), $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } if ($cased_method_id) { $arg_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $arg->value); self::processTaintedness($statements_analyzer, $cased_method_id, $argument_offset, $arg_location, $function_call_location, $function_param, $arg_type, $arg->value, $context, $specialize_taint); } return null; } if ($arg_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var Type\Atomic\TArray|Type\Atomic\TList|Type\Atomic\TKeyedArray */ $unpacked_atomic_array = $arg_type->getAtomicTypes()['array']; if ($unpacked_atomic_array instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($function_param->is_variadic) { $arg_type = $unpacked_atomic_array->getGenericValueType(); } elseif ($codebase->php_major_version >= 8 && $allow_named_args && isset($unpacked_atomic_array->properties[$function_param->name])) { $arg_type = clone $unpacked_atomic_array->properties[$function_param->name]; } elseif ($unpacked_atomic_array->is_list && isset($unpacked_atomic_array->properties[$unpacked_argument_offset])) { $arg_type = clone $unpacked_atomic_array->properties[$unpacked_argument_offset]; } else { $arg_type = \Psalm\Type::getMixed(); } } elseif ($unpacked_atomic_array instanceof \Psalm\Type\Atomic\TList) { $arg_type = $unpacked_atomic_array->type_param; } else { $arg_type = $unpacked_atomic_array->type_params[1]; } } else { foreach ($arg_type->getAtomicTypes() as $atomic_type) { if (!$atomic_type->isIterable($codebase)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArgument('Argument ' . ($argument_offset + 1) . ' of ' . $cased_method_id . ' expects array, ' . $atomic_type->getId() . ' provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $arg->value), $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } continue; } } return null; } } if (self::verifyType($statements_analyzer, $arg_type, $fleshed_out_type, $fleshed_out_signature_type, $cased_method_id, $argument_offset, new \Psalm\CodeLocation($statements_analyzer->getSource(), $arg->value), $arg->value, $context, $function_param, $arg->unpack, $unpacked_atomic_array, $specialize_taint, $in_call_map, $function_call_location) === \false) { return \false; } return null; } /** * @param Type\Atomic\TKeyedArray|Type\Atomic\TArray|Type\Atomic\TList $unpacked_atomic_array * @return null|false */ public static function verifyType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Type\Union $input_type, \Psalm\Type\Union $param_type, ?\Psalm\Type\Union $signature_param_type, ?string $cased_method_id, int $argument_offset, \Psalm\CodeLocation $arg_location, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $input_expr, \Psalm\Context $context, \Psalm\Storage\FunctionLikeParameter $function_param, bool $unpack, ?\Psalm\Type\Atomic $unpacked_atomic_array, bool $specialize_taint, bool $in_call_map, \Psalm\CodeLocation $function_call_location) : ?bool { $codebase = $statements_analyzer->getCodebase(); if ($param_type->hasMixed()) { if ($codebase->infer_types_from_usage && !$input_type->hasMixed() && !$param_type->from_docblock && !$param_type->had_template && $cased_method_id && \strpos($cased_method_id, '::') && !\strpos($cased_method_id, '__')) { $method_parts = \explode('::', $cased_method_id); $method_id = new \Psalm\Internal\MethodIdentifier($method_parts[0], \strtolower($method_parts[1])); $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id); if ($declaring_method_id) { $id_lc = \strtolower((string) $declaring_method_id); if (!isset($codebase->analyzer->possible_method_param_types[$id_lc][$argument_offset])) { $codebase->analyzer->possible_method_param_types[$id_lc][$argument_offset] = clone $input_type; } else { $codebase->analyzer->possible_method_param_types[$id_lc][$argument_offset] = \Psalm\Type::combineUnionTypes($codebase->analyzer->possible_method_param_types[$id_lc][$argument_offset], clone $input_type, $codebase); } } } if ($cased_method_id) { self::processTaintedness($statements_analyzer, $cased_method_id, $argument_offset, $arg_location, $function_call_location, $function_param, $input_type, $input_expr, $context, $specialize_taint); } return null; } $method_identifier = $cased_method_id ? ' of ' . $cased_method_id : ''; if ($input_type->hasMixed()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArgument('Argument ' . ($argument_offset + 1) . $method_identifier . ' cannot be ' . $input_type->getId() . ', expecting ' . $param_type, $arg_location, $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } if ($input_type->isMixed()) { if (!$function_param->by_ref && !($function_param->is_variadic xor $unpack) && $cased_method_id !== 'echo' && $cased_method_id !== 'print' && (!$in_call_map || $context->strict_types)) { self::coerceValueAfterGatekeeperArgument($statements_analyzer, $input_type, \false, $input_expr, $param_type, $signature_param_type, $context, $unpack, $unpacked_atomic_array); } } if ($cased_method_id) { $input_type = self::processTaintedness($statements_analyzer, $cased_method_id, $argument_offset, $arg_location, $function_call_location, $function_param, $input_type, $input_expr, $context, $specialize_taint); } if ($input_type->isMixed()) { return null; } } if ($input_type->isNever()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NoValue('This function or method call never returns output', $arg_location), $statements_analyzer->getSuppressedIssues())) { // fall through } return null; } if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } if ($function_param->by_ref) { $param_type->possibly_undefined = \true; } if ($param_type->hasCallableType() && $param_type->isSingle() && $input_type->isSingleStringLiteral() && !\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($input_type->getSingleStringLiteral()->value)) { foreach ($input_type->getAtomicTypes() as $key => $atomic_type) { $candidate_callable = \Psalm\Internal\Type\Comparator\CallableTypeComparator::getCallableFromAtomic($codebase, $atomic_type, null, $statements_analyzer); if ($candidate_callable) { $input_type->removeType($key); $input_type->addType($candidate_callable); } } } $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $type_match_found = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_type, $param_type, \true, \true, $union_comparison_results); $replace_input_type = \false; if ($union_comparison_results->replacement_union_type) { $replace_input_type = \true; $input_type = $union_comparison_results->replacement_union_type; } if ($cased_method_id) { $old_input_type = $input_type; $input_type = self::processTaintedness($statements_analyzer, $cased_method_id, $argument_offset, $arg_location, $function_call_location, $function_param, $input_type, $input_expr, $context, $specialize_taint); if ($old_input_type !== $input_type) { $replace_input_type = \true; } } if ($type_match_found && $param_type->hasCallableType()) { $potential_method_ids = []; foreach ($input_type->getAtomicTypes() as $input_type_part) { if ($input_type_part instanceof \Psalm\Type\Atomic\TKeyedArray) { $potential_method_id = \Psalm\Internal\Type\Comparator\CallableTypeComparator::getCallableMethodIdFromTKeyedArray($input_type_part, $codebase, $context->calling_method_id, $statements_analyzer->getFilePath()); if ($potential_method_id && $potential_method_id !== 'not-callable') { $potential_method_ids[] = $potential_method_id; } } elseif ($input_type_part instanceof \Psalm\Type\Atomic\TLiteralString && \strpos($input_type_part->value, '::')) { $parts = \explode('::', $input_type_part->value); $potential_method_ids[] = new \Psalm\Internal\MethodIdentifier($parts[0], \strtolower($parts[1])); } } foreach ($potential_method_ids as $potential_method_id) { $codebase->methods->methodExists($potential_method_id, $context->calling_method_id, null, $statements_analyzer, $statements_analyzer->getFilePath()); } } if ($context->strict_types && !$input_type->hasArray() && !$param_type->from_docblock && $cased_method_id !== 'echo' && $cased_method_id !== 'print' && $cased_method_id !== 'sprintf') { $union_comparison_results->scalar_type_match_found = \false; if ($union_comparison_results->to_string_cast) { $union_comparison_results->to_string_cast = \false; $type_match_found = \false; } } if ($union_comparison_results->type_coerced && !$input_type->hasMixed()) { if ($union_comparison_results->type_coerced_from_mixed) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArgumentTypeCoercion('Argument ' . ($argument_offset + 1) . $method_identifier . ' expects ' . $param_type->getId() . ', parent type ' . $input_type->getId() . ' provided', $arg_location, $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ArgumentTypeCoercion('Argument ' . ($argument_offset + 1) . $method_identifier . ' expects ' . $param_type->getId() . ', parent type ' . $input_type->getId() . ' provided', $arg_location, $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } } if ($union_comparison_results->to_string_cast && $cased_method_id !== 'echo' && $cased_method_id !== 'print') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImplicitToStringCast('Argument ' . ($argument_offset + 1) . $method_identifier . ' expects ' . $param_type->getId() . ', ' . $input_type->getId() . ' provided with a __toString method', $arg_location), $statements_analyzer->getSuppressedIssues())) { // fall through } } if (!$type_match_found && !$union_comparison_results->type_coerced) { $types_can_be_identical = \Psalm\Internal\Type\Comparator\UnionTypeComparator::canBeContainedBy($codebase, $input_type, $param_type, \true, \true); if ($union_comparison_results->scalar_type_match_found) { if ($cased_method_id !== 'echo' && $cased_method_id !== 'print') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidScalarArgument('Argument ' . ($argument_offset + 1) . $method_identifier . ' expects ' . $param_type->getId() . ', ' . $input_type->getId() . ' provided', $arg_location, $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } elseif ($types_can_be_identical) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidArgument('Argument ' . ($argument_offset + 1) . $method_identifier . ' expects ' . $param_type->getId() . ', possibly different type ' . $input_type->getId() . ' provided', $arg_location, $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArgument('Argument ' . ($argument_offset + 1) . $method_identifier . ' expects ' . $param_type->getId() . ', ' . $input_type->getId() . ' provided', $arg_location, $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } return null; } if ($input_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $input_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ || $input_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { foreach ($param_type->getAtomicTypes() as $param_type_part) { if ($param_type_part instanceof \Psalm\Type\Atomic\TClassString && $input_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ && $param_type->isSingle()) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $input_expr->value, $arg_location, $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues()) === \false) { return null; } } elseif ($param_type_part instanceof \Psalm\Type\Atomic\TArray && $input_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_) { foreach ($param_type_part->type_params[1]->getAtomicTypes() as $param_array_type_part) { if ($param_array_type_part instanceof \Psalm\Type\Atomic\TClassString) { foreach ($input_expr->items as $item) { if ($item && $item->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $item->value->value, $arg_location, $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues()) === \false) { return null; } } } } } } elseif ($param_type_part instanceof \Psalm\Type\Atomic\TCallable) { $can_be_callable_like_array = \false; if ($param_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset */ $param_array_type = $param_type->getAtomicTypes()['array']; $row_type = null; if ($param_array_type instanceof \Psalm\Type\Atomic\TList) { $row_type = $param_array_type->type_param; } elseif ($param_array_type instanceof \Psalm\Type\Atomic\TArray) { $row_type = $param_array_type->type_params[1]; } elseif ($param_array_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $row_type = $param_array_type->getGenericArrayType()->type_params[1]; } if ($row_type && ($row_type->hasMixed() || $row_type->hasString())) { $can_be_callable_like_array = \true; } } if (!$can_be_callable_like_array) { $function_ids = \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::getFunctionIdsFromCallableArg($statements_analyzer, $input_expr); foreach ($function_ids as $function_id) { if (\strpos($function_id, '::') !== \false) { if ($function_id[0] === '$') { $function_id = \substr($function_id, 1); } $function_id_parts = \explode('&', $function_id); $non_existent_method_ids = []; $has_valid_method = \false; foreach ($function_id_parts as $function_id_part) { [$callable_fq_class_name, $method_name] = \explode('::', $function_id_part); switch ($callable_fq_class_name) { case 'self': case 'static': case 'parent': $container_class = $statements_analyzer->getFQCLN(); if ($callable_fq_class_name === 'parent') { $container_class = $statements_analyzer->getParentFQCLN(); } if (!$container_class) { continue 2; } $callable_fq_class_name = $container_class; } if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $callable_fq_class_name, $arg_location, $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues()) === \false) { return null; } $function_id_part = new \Psalm\Internal\MethodIdentifier($callable_fq_class_name, \strtolower($method_name)); $call_method_id = new \Psalm\Internal\MethodIdentifier($callable_fq_class_name, '__call'); if (!$codebase->classOrInterfaceExists($callable_fq_class_name)) { return null; } if (!$codebase->methods->methodExists($function_id_part) && !$codebase->methods->methodExists($call_method_id)) { $non_existent_method_ids[] = $function_id_part; } else { $has_valid_method = \true; } } if (!$has_valid_method && !$param_type->hasString() && !$param_type->hasArray()) { if (\Psalm\Internal\Analyzer\MethodAnalyzer::checkMethodExists($codebase, $non_existent_method_ids[0], $arg_location, $statements_analyzer->getSuppressedIssues()) === \false) { return null; } } } else { if (!$param_type->hasString() && !$param_type->hasArray() && \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::checkFunctionExists($statements_analyzer, $function_id, $arg_location, \false) === \false) { return null; } } } } } } } if (!$param_type->isNullable() && $cased_method_id !== 'echo' && $cased_method_id !== 'print') { if ($input_type->isNull()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullArgument('Argument ' . ($argument_offset + 1) . $method_identifier . ' cannot be null, ' . 'null value provided to parameter with type ' . $param_type->getId(), $arg_location, $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } return null; } if ($input_type->isNullable() && !$input_type->ignore_nullable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullArgument('Argument ' . ($argument_offset + 1) . $method_identifier . ' cannot be null, possibly ' . 'null value provided', $arg_location, $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if ($input_type->isFalsable() && !$param_type->hasBool() && !$param_type->hasScalar() && !$input_type->ignore_falsable_issues && $cased_method_id !== 'echo') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyFalseArgument('Argument ' . ($argument_offset + 1) . $method_identifier . ' cannot be false, possibly ' . 'false value provided', $arg_location, $cased_method_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } if (($type_match_found || $input_type->hasMixed()) && !$function_param->by_ref && !($function_param->is_variadic xor $unpack) && $cased_method_id !== 'echo' && $cased_method_id !== 'print' && (!$in_call_map || $context->strict_types)) { self::coerceValueAfterGatekeeperArgument($statements_analyzer, $input_type, $replace_input_type, $input_expr, $param_type, $signature_param_type, $context, $unpack, $unpacked_atomic_array); } return null; } /** * @param Type\Atomic\TKeyedArray|Type\Atomic\TArray|Type\Atomic\TList $unpacked_atomic_array */ private static function coerceValueAfterGatekeeperArgument(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Type\Union $input_type, bool $input_type_changed, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $input_expr, \Psalm\Type\Union $param_type, ?\Psalm\Type\Union $signature_param_type, \Psalm\Context $context, bool $unpack, ?\Psalm\Type\Atomic $unpacked_atomic_array) : void { if ($param_type->hasMixed()) { return; } if (!$input_type_changed && $param_type->from_docblock && !$input_type->hasMixed()) { $input_type = clone $input_type; foreach ($param_type->getAtomicTypes() as $param_atomic_type) { if ($param_atomic_type instanceof \Psalm\Type\Atomic\TGenericObject) { foreach ($input_type->getAtomicTypes() as $input_atomic_type) { if ($input_atomic_type instanceof \Psalm\Type\Atomic\TGenericObject && $input_atomic_type->value === $param_atomic_type->value) { foreach ($input_atomic_type->type_params as $i => $type_param) { if ($type_param->isEmpty() && isset($param_atomic_type->type_params[$i])) { $input_type_changed = \true; /** @psalm-suppress PropertyTypeCoercion */ $input_atomic_type->type_params[$i] = clone $param_atomic_type->type_params[$i]; } } } } } } if (!$input_type_changed) { return; } } $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($input_expr, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($var_id) { $was_cloned = \false; if ($input_type->isNullable() && !$param_type->isNullable()) { $input_type = clone $input_type; $was_cloned = \true; $input_type->removeType('null'); } if ($input_type->getId() === $param_type->getId()) { if (!$was_cloned) { $was_cloned = \true; $input_type = clone $input_type; } $input_type->from_docblock = \false; foreach ($input_type->getAtomicTypes() as $atomic_type) { $atomic_type->from_docblock = \false; } } elseif ($input_type->hasMixed() && $signature_param_type) { $was_cloned = \true; $parent_nodes = $input_type->parent_nodes; $by_ref = $input_type->by_ref; $input_type = clone $signature_param_type; if ($input_type->isNullable()) { $input_type->ignore_nullable_issues = \true; } $input_type->parent_nodes = $parent_nodes; $input_type->by_ref = $by_ref; } if ($context->inside_conditional && !isset($context->assigned_var_ids[$var_id])) { $context->assigned_var_ids[$var_id] = \false; } if ($was_cloned) { $context->removeVarFromConflictingClauses($var_id, null, $statements_analyzer); } if ($unpack) { if ($unpacked_atomic_array instanceof \Psalm\Type\Atomic\TList) { $unpacked_atomic_array = clone $unpacked_atomic_array; $unpacked_atomic_array->type_param = $input_type; $context->vars_in_scope[$var_id] = new \Psalm\Type\Union([$unpacked_atomic_array]); } elseif ($unpacked_atomic_array instanceof \Psalm\Type\Atomic\TArray) { $unpacked_atomic_array = clone $unpacked_atomic_array; /** @psalm-suppress PropertyTypeCoercion */ $unpacked_atomic_array->type_params[1] = $input_type; $context->vars_in_scope[$var_id] = new \Psalm\Type\Union([$unpacked_atomic_array]); } elseif ($unpacked_atomic_array instanceof \Psalm\Type\Atomic\TKeyedArray && $unpacked_atomic_array->is_list) { $unpacked_atomic_array = $unpacked_atomic_array->getList(); $unpacked_atomic_array->type_param = $input_type; $context->vars_in_scope[$var_id] = new \Psalm\Type\Union([$unpacked_atomic_array]); } else { $context->vars_in_scope[$var_id] = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $input_type])]); } } else { $context->vars_in_scope[$var_id] = $input_type; } } } private static function processTaintedness(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $cased_method_id, int $argument_offset, \Psalm\CodeLocation $arg_location, \Psalm\CodeLocation $function_call_location, \Psalm\Storage\FunctionLikeParameter $function_param, \Psalm\Type\Union $input_type, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr, \Psalm\Context $context, bool $specialize_taint) : \Psalm\Type\Union { $codebase = $statements_analyzer->getCodebase(); if (!$statements_analyzer->data_flow_graph || $statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { return $input_type; } if ($function_param->type && $function_param->type->isString() && !$input_type->isString()) { $cast_type = \Psalm\Internal\Analyzer\Statements\Expression\CastAnalyzer::castStringAttempt($statements_analyzer, $context, $input_type, $expr, \false); $input_type = clone $input_type; $input_type->parent_nodes += $cast_type->parent_nodes; } if ($specialize_taint) { $method_node = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodArgument($cased_method_id, $cased_method_id, $argument_offset, $function_param->location, $function_call_location); } else { $method_node = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodArgument($cased_method_id, $cased_method_id, $argument_offset, $function_param->location); if (\strpos($cased_method_id, '::')) { [$fq_classlike_name, $cased_method_name] = \explode('::', $cased_method_id); $method_name = \strtolower($cased_method_name); $class_storage = $codebase->classlike_storage_provider->get($fq_classlike_name); foreach ($class_storage->dependent_classlikes as $dependent_classlike_lc => $_) { $dependent_classlike_storage = $codebase->classlike_storage_provider->get($dependent_classlike_lc); $new_sink = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodArgument($dependent_classlike_lc . '::' . $method_name, $dependent_classlike_storage->name . '::' . $cased_method_name, $argument_offset, $arg_location, null); $statements_analyzer->data_flow_graph->addNode($new_sink); $statements_analyzer->data_flow_graph->addPath($method_node, $new_sink, 'arg'); } if (isset($class_storage->overridden_method_ids[$method_name])) { foreach ($class_storage->overridden_method_ids[$method_name] as $parent_method_id) { $new_sink = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodArgument((string) $parent_method_id, $codebase->methods->getCasedMethodId($parent_method_id), $argument_offset, $arg_location, null); $statements_analyzer->data_flow_graph->addNode($new_sink); $statements_analyzer->data_flow_graph->addPath($method_node, $new_sink, 'arg'); } } } } $statements_analyzer->data_flow_graph->addNode($method_node); $argument_value_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment('call to ' . $cased_method_id, $arg_location); $statements_analyzer->data_flow_graph->addNode($argument_value_node); $statements_analyzer->data_flow_graph->addPath($argument_value_node, $method_node, 'arg'); if ($function_param->sinks && $statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph) { if ($specialize_taint) { $sink = \Psalm\Internal\DataFlow\TaintSink::getForMethodArgument($cased_method_id, $cased_method_id, $argument_offset, $function_param->location, $function_call_location); } else { $sink = \Psalm\Internal\DataFlow\TaintSink::getForMethodArgument($cased_method_id, $cased_method_id, $argument_offset, $function_param->location); } $sink->taints = $function_param->sinks; $statements_analyzer->data_flow_graph->addSink($sink); } foreach ($input_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addNode($method_node); $statements_analyzer->data_flow_graph->addPath($parent_node, $argument_value_node, 'arg'); } if ($function_param->assert_untainted) { $input_type = clone $input_type; $input_type->parent_nodes = []; } return $input_type; } } file_provider->getContents($statements_analyzer->getFilePath()); // Find opening paren $first_argument = $stmt->args[0] ?? null; $first_argument_character = $first_argument !== null ? $first_argument->getStartFilePos() : $stmt->getEndFilePos(); $method_name_and_first_paren_source_code_length = $first_argument_character - $stmt->getStartFilePos(); // FIXME: There are weird ::__construct calls in the AST for `extends` if ($method_name_and_first_paren_source_code_length <= 0) { return; } $method_name_and_first_paren_source_code = \substr($file_content, $stmt->getStartFilePos(), $method_name_and_first_paren_source_code_length); $method_name_and_first_paren_tokens = \token_get_all('getStartFilePos()) { return; } // Record ranges of the source code that need to be tokenized to find commas /** @var array{0: int, 1: int}[] $ranges */ $ranges = []; // Add range between opening paren and first argument $first_argument = $stmt->args[0] ?? null; $first_argument_starting_position = $first_argument !== null ? $first_argument->getStartFilePos() : $stmt->getEndFilePos(); $first_range_starting_position = $opening_paren_position + 1; if ($first_range_starting_position !== $first_argument_starting_position) { $ranges[] = [$first_range_starting_position, $first_argument_starting_position]; } // Add range between arguments foreach ($stmt->args as $i => $argument) { $range_start = $argument->getEndFilePos() + 1; $next_argument = $stmt->args[$i + 1] ?? null; $range_end = $next_argument !== null ? $next_argument->getStartFilePos() : $stmt->getEndFilePos(); if ($range_start !== $range_end) { $ranges[] = [$range_start, $range_end]; } } $commas = []; foreach ($ranges as $range) { $position = $range[0]; $length = $range[1] - $position; if ($length > 0) { $range_source_code = \substr($file_content, $position, $length); $range_tokens = \token_get_all('analyzer->addNodeArgument($statements_analyzer->getFilePath(), $argument_start_position, $comma, $function_reference, $argument_number); ++$argument_number; $argument_start_position = $comma + 1; } $codebase->analyzer->addNodeArgument($statements_analyzer->getFilePath(), $argument_start_position, $stmt->getEndFilePos(), $function_reference, $argument_number); } } $invalid_fetch_types $invalid_fetch_types */ public static function analyze(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch $stmt, \Psalm\Context $context, bool $in_assignment, ?string $var_id, ?string $stmt_var_id, \Psalm\Type\Union $stmt_var_type, \Psalm\Type\Atomic $lhs_type_part, string $prop_name, bool &$has_valid_fetch_type, array &$invalid_fetch_types) : void { if ($lhs_type_part instanceof \Psalm\Type\Atomic\TNull) { return; } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $extra_types = $lhs_type_part->extra_types; $lhs_type_part = \array_values($lhs_type_part->as->getAtomicTypes())[0]; $lhs_type_part->from_docblock = \true; if ($lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $lhs_type_part->extra_types = $extra_types; } } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TMixed) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); return; } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TFalse && $stmt_var_type->ignore_falsable_issues) { return; } if (!$lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject && !$lhs_type_part instanceof \Psalm\Type\Atomic\TObject) { $invalid_fetch_types[] = (string) $lhs_type_part; return; } $has_valid_fetch_type = \true; if ($lhs_type_part instanceof \Psalm\Type\Atomic\TObjectWithProperties && isset($lhs_type_part->properties[$prop_name])) { if ($stmt_type = $statements_analyzer->node_data->getType($stmt)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::combineUnionTypes($lhs_type_part->properties[$prop_name], $stmt_type)); } else { $statements_analyzer->node_data->setType($stmt, $lhs_type_part->properties[$prop_name]); } return; } // stdClass and SimpleXMLElement are special cases where we cannot infer the return types // but we don't want to throw an error // Hack has a similar issue: https://github.com/facebook/hhvm/issues/5164 if ($lhs_type_part instanceof \Psalm\Type\Atomic\TObject || \in_array(\strtolower($lhs_type_part->value), \Psalm\Config::getInstance()->getUniversalObjectCrates(), \true)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); return; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::isMock($lhs_type_part->value)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); return; } $intersection_types = $lhs_type_part->getIntersectionTypes() ?: []; $fq_class_name = $lhs_type_part->value; $override_property_visibility = \false; $has_magic_getter = \false; $class_exists = \false; $interface_exists = \false; $codebase = $statements_analyzer->getCodebase(); if (!$codebase->classExists($lhs_type_part->value)) { if ($codebase->interfaceExists($lhs_type_part->value)) { $interface_exists = \true; $interface_storage = $codebase->classlike_storage_provider->get($lhs_type_part->value); $override_property_visibility = $interface_storage->override_property_visibility; foreach ($intersection_types as $intersection_type) { if ($intersection_type instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classExists($intersection_type->value)) { $fq_class_name = $intersection_type->value; $class_exists = \true; break; } } if (!$class_exists) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NoInterfaceProperties('Interfaces cannot have properties', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $lhs_type_part->value), $statements_analyzer->getSuppressedIssues())) { return; } if (!$codebase->methodExists($fq_class_name . '::__set')) { return; } } } if (!$class_exists && !$interface_exists) { if ($lhs_type_part->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedDocblockClass('Cannot set properties of undefined docblock class ' . $lhs_type_part->value, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $lhs_type_part->value), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedClass('Cannot set properties of undefined class ' . $lhs_type_part->value, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $lhs_type_part->value), $statements_analyzer->getSuppressedIssues())) { // fall through } } return; } } else { $class_exists = \true; } $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $property_id = $fq_class_name . '::$' . $prop_name; $naive_property_exists = $codebase->properties->propertyExists($property_id, \true, $statements_analyzer, $context, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null); // add method before changing fq_class_name $get_method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, '__get'); if (!$naive_property_exists && $class_storage->namedMixins) { foreach ($class_storage->namedMixins as $mixin) { $new_property_id = $mixin->value . '::$' . $prop_name; try { $new_class_storage = $codebase->classlike_storage_provider->get($mixin->value); } catch (\InvalidArgumentException $e) { $new_class_storage = null; } if ($new_class_storage && ($codebase->properties->propertyExists($new_property_id, \true, $statements_analyzer, $context, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null) || isset($new_class_storage->pseudo_property_get_types['$' . $prop_name]))) { $fq_class_name = $mixin->value; $lhs_type_part = clone $mixin; $class_storage = $new_class_storage; if (!isset($new_class_storage->pseudo_property_get_types['$' . $prop_name])) { $naive_property_exists = \true; } $property_id = $new_property_id; } } } $declaring_property_class = $codebase->properties->getDeclaringClassForProperty($property_id, \true, $statements_analyzer); if ((!$naive_property_exists || $stmt_var_id !== '$this' && $fq_class_name !== $context->self && \Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkPropertyVisibility($property_id, $context, $statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues(), \false) !== \true) && $codebase->methods->methodExists($get_method_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath())) { $has_magic_getter = \true; if (isset($class_storage->pseudo_property_get_types['$' . $prop_name])) { $stmt_type = clone $class_storage->pseudo_property_get_types['$' . $prop_name]; if ($class_storage->template_types) { if (!$lhs_type_part instanceof \Psalm\Type\Atomic\TGenericObject) { $type_params = []; foreach ($class_storage->template_types as $type_map) { $type_params[] = clone \array_values($type_map)[0][0]; } $lhs_type_part = new \Psalm\Type\Atomic\TGenericObject($lhs_type_part->value, $type_params); } $stmt_type = self::localizePropertyType($codebase, $stmt_type, $lhs_type_part, $class_storage, $declaring_property_class ? $codebase->classlike_storage_provider->get($declaring_property_class) : $class_storage); } $statements_analyzer->node_data->setType($stmt, $stmt_type); self::processTaints($statements_analyzer, $stmt, $stmt_type, $property_id, $class_storage, $in_assignment); return; } $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($stmt->var, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('__get', $stmt->name->getAttributes()), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($prop_name, $stmt->name->getAttributes()))]); $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('PossiblyNullReference', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyNullReference']); } if (!\in_array('InternalMethod', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['InternalMethod']); } \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_method_call, $context, \false); if (!\in_array('PossiblyNullReference', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyNullReference']); } if (!\in_array('InternalMethod', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['InternalMethod']); } $fake_method_call_type = $statements_analyzer->node_data->getType($fake_method_call); $statements_analyzer->node_data = $old_data_provider; if ($fake_method_call_type) { $statements_analyzer->node_data->setType($stmt, $fake_method_call_type); } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } $property_id = $lhs_type_part->value . '::$' . $prop_name; /* * If we have an explicit list of all allowed magic properties on the class, and we're * not in that list, fall through */ if (!$class_storage->sealed_properties && !$override_property_visibility) { return; } if (!$class_exists) { $property_id = $lhs_type_part->value . '::$' . $prop_name; if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedMagicPropertyFetch('Magic instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } return; } } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->name, $property_id); } $config = $statements_analyzer->getProjectAnalyzer()->getConfig(); if (!$naive_property_exists) { if ($config->use_phpdoc_property_without_magic_or_parent && isset($class_storage->pseudo_property_get_types['$' . $prop_name])) { $stmt_type = clone $class_storage->pseudo_property_get_types['$' . $prop_name]; if ($class_storage->template_types) { if (!$lhs_type_part instanceof \Psalm\Type\Atomic\TGenericObject) { $type_params = []; foreach ($class_storage->template_types as $type_map) { $type_params[] = clone \array_values($type_map)[0][0]; } $lhs_type_part = new \Psalm\Type\Atomic\TGenericObject($lhs_type_part->value, $type_params); } $stmt_type = self::localizePropertyType($codebase, $stmt_type, $lhs_type_part, $class_storage, $declaring_property_class ? $codebase->classlike_storage_provider->get($declaring_property_class) : $class_storage); } $statements_analyzer->node_data->setType($stmt, $stmt_type); self::processTaints($statements_analyzer, $stmt, $stmt_type, $property_id, $class_storage, $in_assignment); return; } if ($fq_class_name !== $context->self && $context->self && $codebase->classlikes->classExtends($fq_class_name, $context->self) && $codebase->properties->propertyExists($context->self . '::$' . $prop_name, \true, $statements_analyzer, $context, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null)) { $property_id = $context->self . '::$' . $prop_name; } else { self::handleUndefinedProperty($context, $statements_analyzer, $stmt, $stmt_var_id, $property_id, $has_magic_getter, $var_id); return; } } if (!$override_property_visibility) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkPropertyVisibility($property_id, $context, $statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues()) === \false) { return; } } $declaring_property_class = $codebase->properties->getDeclaringClassForProperty($property_id, \true, $statements_analyzer); if ($declaring_property_class === null) { return; } if ($codebase->properties_to_rename) { $declaring_property_id = \strtolower($declaring_property_class) . '::$' . $prop_name; foreach ($codebase->properties_to_rename as $original_property_id => $new_property_name) { if ($declaring_property_id === $original_property_id) { $file_manipulations = [new \Psalm\FileManipulation((int) $stmt->name->getAttribute('startFilePos'), (int) $stmt->name->getAttribute('endFilePos') + 1, $new_property_name)]; \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } } $declaring_class_storage = $codebase->classlike_storage_provider->get($declaring_property_class); if (isset($declaring_class_storage->properties[$prop_name])) { $property_storage = $declaring_class_storage->properties[$prop_name]; if ($property_storage->deprecated) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedProperty($property_id . ' is marked deprecated', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($context->self && !\Psalm\Internal\Analyzer\NamespaceAnalyzer::isWithin($context->self, $property_storage->internal)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InternalProperty($property_id . ' is internal to ' . $property_storage->internal . ' but called from ' . $context->self, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($context->inside_unset) { \Psalm\Internal\Analyzer\Statements\Expression\Assignment\InstancePropertyAssignmentAnalyzer::trackPropertyImpurity($statements_analyzer, $stmt, $property_id, $property_storage, $declaring_class_storage, $context); } } $class_property_type = $codebase->properties->getPropertyType($property_id, \false, $statements_analyzer, $context); if (!$class_property_type) { if ($declaring_class_storage->location && $config->isInProjectDirs($declaring_class_storage->location->file_path)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingPropertyType('Property ' . $fq_class_name . '::$' . $prop_name . ' does not have a declared type', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } $class_property_type = \Psalm\Type::getMixed(); } else { $class_property_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, clone $class_property_type, $declaring_class_storage->name, $declaring_class_storage->name, $declaring_class_storage->parent_class); if ($declaring_class_storage->template_types) { if (!$lhs_type_part instanceof \Psalm\Type\Atomic\TGenericObject) { $type_params = []; foreach ($declaring_class_storage->template_types as $type_map) { $type_params[] = clone \array_values($type_map)[0][0]; } $lhs_type_part = new \Psalm\Type\Atomic\TGenericObject($lhs_type_part->value, $type_params); } $class_property_type = self::localizePropertyType($codebase, $class_property_type, $lhs_type_part, $class_storage, $declaring_class_storage); } elseif ($lhs_type_part instanceof \Psalm\Type\Atomic\TGenericObject) { $class_property_type = self::localizePropertyType($codebase, $class_property_type, $lhs_type_part, $class_storage, $declaring_class_storage); } } if (!$context->collect_mutations && !$context->collect_initializations && !($class_storage->external_mutation_free && $class_property_type->allow_mutations)) { if ($context->pure) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpurePropertyFetch('Cannot access a property on a mutable object from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_impure = \true; } } self::processTaints($statements_analyzer, $stmt, $class_property_type, $property_id, $class_storage, $in_assignment); if ($stmt_type = $statements_analyzer->node_data->getType($stmt)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::combineUnionTypes($class_property_type, $stmt_type)); } else { $statements_analyzer->node_data->setType($stmt, $class_property_type); } } public static function localizePropertyType(\Psalm\Codebase $codebase, \Psalm\Type\Union $class_property_type, \Psalm\Type\Atomic\TGenericObject $lhs_type_part, \Psalm\Storage\ClassLikeStorage $calling_class_storage, \Psalm\Storage\ClassLikeStorage $declaring_class_storage) : \Psalm\Type\Union { $template_types = \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::getTemplateTypesForCall($codebase, $declaring_class_storage, $declaring_class_storage->name, $calling_class_storage, $calling_class_storage->template_types ?: []); $extended_types = $calling_class_storage->template_type_extends; if ($template_types) { if ($calling_class_storage->template_types) { foreach ($lhs_type_part->type_params as $param_offset => $lhs_param_type) { $i = -1; foreach ($calling_class_storage->template_types as $calling_param_name => $_) { $i++; if ($i === $param_offset) { $template_types[$calling_param_name][$calling_class_storage->name] = [$lhs_param_type, 0]; break; } } } } foreach ($template_types as $type_name => $_) { if (isset($extended_types[$declaring_class_storage->name][$type_name])) { $mapped_type = $extended_types[$declaring_class_storage->name][$type_name]; foreach ($mapped_type->getAtomicTypes() as $mapped_type_atomic) { if (!$mapped_type_atomic instanceof \Psalm\Type\Atomic\TTemplateParam) { continue; } $param_name = $mapped_type_atomic->param_name; $position = \false; if (isset($calling_class_storage->template_types[$param_name])) { $position = \array_search($param_name, \array_keys($calling_class_storage->template_types)); } if ($position !== \false && isset($lhs_type_part->type_params[$position])) { $template_types[$type_name][$declaring_class_storage->name] = [$lhs_type_part->type_params[$position], 0]; } } } } $class_property_type->replaceTemplateTypesWithArgTypes(new \Psalm\Internal\Type\TemplateResult([], $template_types), $codebase); } return $class_property_type; } public static function processTaints(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch $stmt, \Psalm\Type\Union $type, string $property_id, \Psalm\Storage\ClassLikeStorage $class_storage, bool $in_assignment) : void { if (!$statements_analyzer->data_flow_graph) { return; } $data_flow_graph = $statements_analyzer->data_flow_graph; $var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var); $property_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); if ($class_storage->specialize_instance) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->var, null, $statements_analyzer); $var_property_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt, null, $statements_analyzer); if ($var_id) { $var_type = $statements_analyzer->node_data->getType($stmt->var); if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && $var_type && \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $var_type->parent_nodes = []; return; } $var_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_id, $var_location); $data_flow_graph->addNode($var_node); $property_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_property_id ?: $var_id . '->$property', $property_location); $data_flow_graph->addNode($property_node); $data_flow_graph->addPath($var_node, $property_node, 'property-fetch' . ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier ? '-' . $stmt->name : '')); if ($var_type && $var_type->parent_nodes) { foreach ($var_type->parent_nodes as $parent_node) { $data_flow_graph->addPath($parent_node, $var_node, '='); } } $type->parent_nodes = [$property_node->id => $property_node]; } } else { $code_location = new \Psalm\CodeLocation($statements_analyzer, $stmt->name); $localized_property_node = new \Psalm\Internal\DataFlow\DataFlowNode($property_id . '-' . $code_location->file_name . ':' . $code_location->raw_file_start, $property_id, $code_location, null); $data_flow_graph->addNode($localized_property_node); $property_node = new \Psalm\Internal\DataFlow\DataFlowNode($property_id, $property_id, null, null); $data_flow_graph->addNode($property_node); if ($in_assignment) { $data_flow_graph->addPath($localized_property_node, $property_node, 'property-assignment'); } else { $data_flow_graph->addPath($property_node, $localized_property_node, 'property-fetch'); } $type->parent_nodes[$localized_property_node->id] = $localized_property_node; } } private static function handleUndefinedProperty(\Psalm\Context $context, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch $stmt, ?string $stmt_var_id, string $property_id, bool $has_magic_getter, ?string $var_id) : void { if ($context->inside_isset || $context->collect_initializations) { if ($context->pure) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpurePropertyFetch('Cannot access a property on a mutable object from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($context->inside_isset && $statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_impure = \true; } return; } if ($stmt_var_id === '$this') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedThisPropertyFetch('Instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if ($has_magic_getter) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedMagicPropertyFetch('Magic instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedPropertyFetch('Instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } $stmt_type = \Psalm\Type::getMixed(); $statements_analyzer->node_data->setType($stmt, $stmt_type); if ($var_id) { $context->vars_in_scope[$var_id] = $stmt_type; } } } name->parts); switch (\strtolower($const_name)) { case 'null': $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getNull()); break; case 'false': // false is a subtype of bool $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getFalse()); break; case 'true': $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getTrue()); break; case 'stdin': $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getResource()); break; default: $const_type = self::getConstType($statements_analyzer, $const_name, $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified, $context); if ($const_type) { $statements_analyzer->node_data->setType($stmt, clone $const_type); } elseif ($context->check_consts) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedConstant('Const ' . $const_name . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } public static function getGlobalConstType(\Psalm\Codebase $codebase, ?string $fq_const_name, string $const_name) : ?\Psalm\Type\Union { if ($const_name === 'STDERR' || $const_name === 'STDOUT' || $const_name === 'STDIN') { return \Psalm\Type::getResource(); } if ($fq_const_name) { $stubbed_const_type = $codebase->getStubbedConstantType($fq_const_name); if ($stubbed_const_type) { return $stubbed_const_type; } } $stubbed_const_type = $codebase->getStubbedConstantType($const_name); if ($stubbed_const_type) { return $stubbed_const_type; } $predefined_constants = $codebase->config->getPredefinedConstants(); if ($fq_const_name && \array_key_exists($fq_const_name, $predefined_constants) || \array_key_exists($const_name, $predefined_constants)) { switch ($const_name) { case 'PHP_VERSION': case 'DIRECTORY_SEPARATOR': case 'PATH_SEPARATOR': case 'PEAR_EXTENSION_DIR': case 'PEAR_INSTALL_DIR': case 'PHP_BINARY': case 'PHP_BINDIR': case 'PHP_CONFIG_FILE_PATH': case 'PHP_CONFIG_FILE_SCAN_DIR': case 'PHP_DATADIR': case 'PHP_EOL': case 'PHP_EXTENSION_DIR': case 'PHP_EXTRA_VERSION': case 'PHP_LIBDIR': case 'PHP_LOCALSTATEDIR': case 'PHP_MANDIR': case 'PHP_OS': case 'PHP_OS_FAMILY': case 'PHP_PREFIX': case 'PHP_SAPI': case 'PHP_SYSCONFDIR': return \Psalm\Type::getString(); case 'PHP_MAJOR_VERSION': case 'PHP_MINOR_VERSION': case 'PHP_RELEASE_VERSION': case 'PHP_DEBUG': case 'PHP_FLOAT_DIG': case 'PHP_INT_MAX': case 'PHP_INT_MIN': case 'PHP_INT_SIZE': case 'PHP_MAXPATHLEN': case 'PHP_VERSION_ID': case 'PHP_ZTS': return \Psalm\Type::getInt(); case 'PHP_FLOAT_EPSILON': case 'PHP_FLOAT_MAX': case 'PHP_FLOAT_MIN': return \Psalm\Type::getFloat(); } if ($fq_const_name && \array_key_exists($fq_const_name, $predefined_constants)) { return \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getTypeFromValue($predefined_constants[$fq_const_name]); } return \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getTypeFromValue($predefined_constants[$const_name]); } return null; } public static function getConstType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $const_name, bool $is_fully_qualified, ?\Psalm\Context $context) : ?\Psalm\Type\Union { $aliased_constants = $statements_analyzer->getAliases()->constants; if (isset($aliased_constants[$const_name])) { $fq_const_name = $aliased_constants[$const_name]; } elseif ($is_fully_qualified) { $fq_const_name = $const_name; } else { $fq_const_name = \Psalm\Type::getFQCLNFromString($const_name, $statements_analyzer->getAliases()); } if ($fq_const_name) { $const_name_parts = \explode('\\', $fq_const_name); $const_name = \array_pop($const_name_parts); $namespace_name = \implode('\\', $const_name_parts); $namespace_constants = \Psalm\Internal\Analyzer\NamespaceAnalyzer::getConstantsForNamespace($namespace_name, \ReflectionProperty::IS_PUBLIC); if (isset($namespace_constants[$const_name])) { return $namespace_constants[$const_name]; } } if ($context && $context->hasVariable($fq_const_name)) { return $context->vars_in_scope[$fq_const_name]; } $file_path = $statements_analyzer->getRootFilePath(); $codebase = $statements_analyzer->getCodebase(); $file_storage_provider = $codebase->file_storage_provider; $file_storage = $file_storage_provider->get($file_path); if (isset($file_storage->declaring_constants[$const_name])) { $constant_file_path = $file_storage->declaring_constants[$const_name]; return $file_storage_provider->get($constant_file_path)->constants[$const_name]; } if (isset($file_storage->declaring_constants[$fq_const_name])) { $constant_file_path = $file_storage->declaring_constants[$fq_const_name]; return $file_storage_provider->get($constant_file_path)->constants[$fq_const_name]; } return \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::getGlobalConstType($codebase, $fq_const_name, $const_name) ?? \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::getGlobalConstType($codebase, $const_name, $const_name); } public static function setConstType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $const_name, \Psalm\Type\Union $const_type, \Psalm\Context $context) : void { $context->vars_in_scope[$const_name] = $const_type; $context->constants[$const_name] = $const_type; $source = $statements_analyzer->getSource(); if ($source instanceof \Psalm\Internal\Analyzer\NamespaceAnalyzer) { $source->setConstType($const_name, $const_type); } } public static function getConstName(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $first_arg_value, \Psalm\Internal\Provider\NodeDataProvider $type_provider, \Psalm\Codebase $codebase, \Psalm\Aliases $aliases) : ?string { $const_name = null; if ($first_arg_value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $const_name = $first_arg_value->value; } elseif ($first_arg_type = $type_provider->getType($first_arg_value)) { if ($first_arg_type->isSingleStringLiteral()) { $const_name = $first_arg_type->getSingleStringLiteral()->value; } } else { $simple_type = \Psalm\Internal\Analyzer\Statements\Expression\SimpleTypeInferer::infer($codebase, $type_provider, $first_arg_value, $aliases); if ($simple_type && $simple_type->isSingleStringLiteral()) { $const_name = $simple_type->getSingleStringLiteral()->value; } } return $const_name; } public static function analyzeConstAssignment(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_ $stmt, \Psalm\Context $context) : void { foreach ($stmt->consts as $const) { \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $const->value, $context); self::setConstType($statements_analyzer, $const->name->name, $statements_analyzer->node_data->getType($const->value) ?: \Psalm\Type::getMixed(), $context); } } } getFileAnalyzer()->project_analyzer; $codebase = $statements_analyzer->getCodebase(); if ($stmt->name === 'this') { if ($statements_analyzer->isStatic()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidScope('Invalid reference to $this in a static context', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } return \true; } if (!isset($context->vars_in_scope['$this'])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidScope('Invalid reference to $this in a non-class context', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } $context->vars_in_scope['$this'] = \Psalm\Type::getMixed(); $context->vars_possibly_in_scope['$this'] = \true; return \true; } $statements_analyzer->node_data->setType($stmt, clone $context->vars_in_scope['$this']); if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations && ($stmt_type = $statements_analyzer->node_data->getType($stmt))) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt, $stmt_type->getId()); } if (!$context->collect_mutations && !$context->collect_initializations) { if ($context->pure) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureVariable('Cannot reference $this in a pure context', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_impure = \true; } } return \true; } if (!$context->check_variables) { if (\is_string($stmt->name)) { $var_name = '$' . $stmt->name; if (!$context->hasVariable($var_name)) { $context->vars_in_scope[$var_name] = \Psalm\Type::getMixed(); $context->vars_possibly_in_scope[$var_name] = \true; $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } else { $stmt_type = clone $context->vars_in_scope[$var_name]; $statements_analyzer->node_data->setType($stmt, $stmt_type); self::addDataFlowToVariable($statements_analyzer, $stmt, $var_name, $stmt_type, $context); } } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } return \true; } if (\is_string($stmt->name) && self::isSuperGlobal('$' . $stmt->name)) { $var_name = '$' . $stmt->name; if (isset($context->vars_in_scope[$var_name])) { $type = clone $context->vars_in_scope[$var_name]; self::taintVariable($statements_analyzer, $var_name, $type, $stmt); $statements_analyzer->node_data->setType($stmt, $type); return \true; } $type = self::getGlobalType($var_name); self::taintVariable($statements_analyzer, $var_name, $type, $stmt); $statements_analyzer->node_data->setType($stmt, $type); $context->vars_in_scope[$var_name] = clone $type; $context->vars_possibly_in_scope[$var_name] = \true; return \true; } if (!\is_string($stmt->name)) { if ($context->pure) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureVariable('Cannot reference an unknown variable in a pure context', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_impure = \true; } $was_inside_use = $context->inside_use; $context->inside_use = \true; $expr_result = \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->name, $context); $context->inside_use = $was_inside_use; return $expr_result; } if ($passed_by_reference && $by_ref_type) { \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::assignByRefParam($statements_analyzer, $stmt, $by_ref_type, $by_ref_type, $context); return \true; } $var_name = '$' . $stmt->name; if (!$context->hasVariable($var_name)) { if (!isset($context->vars_possibly_in_scope[$var_name]) || !$statements_analyzer->getFirstAppearance($var_name)) { if ($array_assignment) { // if we're in an array assignment, let's assign the variable // because PHP allows it $context->vars_in_scope[$var_name] = \Psalm\Type::getArray(); $context->vars_possibly_in_scope[$var_name] = \true; // it might have been defined first in another if/else branch if (!$statements_analyzer->hasVariable($var_name)) { $statements_analyzer->registerVariable($var_name, new \Psalm\CodeLocation($statements_analyzer, $stmt), $context->branch_point); } } elseif (!$context->inside_isset || $statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) { if ($context->is_global || $from_global) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedGlobalVariable('Cannot find referenced variable ' . $var_name . ' in global scope', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $var_name), $statements_analyzer->getSuppressedIssues())) { // fall through } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); return \true; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedVariable('Cannot find referenced variable ' . $var_name, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); return \true; } } $first_appearance = $statements_analyzer->getFirstAppearance($var_name); if ($first_appearance && !$context->inside_isset && !$context->inside_unset) { if ($context->is_global) { if ($codebase->alter_code) { if (!isset($project_analyzer->getIssuesToFix()['PossiblyUndefinedGlobalVariable'])) { return \true; } $branch_point = $statements_analyzer->getBranchPoint($var_name); if ($branch_point) { $statements_analyzer->addVariableInitialization($var_name, $branch_point); } return \true; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedGlobalVariable('Possibly undefined global variable ' . $var_name . ', first seen on line ' . $first_appearance->getLineNumber(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $var_name), $statements_analyzer->getSuppressedIssues(), (bool) $statements_analyzer->getBranchPoint($var_name))) { // fall through } } else { if ($codebase->alter_code) { if (!isset($project_analyzer->getIssuesToFix()['PossiblyUndefinedVariable'])) { return \true; } $branch_point = $statements_analyzer->getBranchPoint($var_name); if ($branch_point) { $statements_analyzer->addVariableInitialization($var_name, $branch_point); } return \true; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedVariable('Possibly undefined variable ' . $var_name . ', first seen on line ' . $first_appearance->getLineNumber(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues(), (bool) $statements_analyzer->getBranchPoint($var_name))) { // fall through } } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt, $first_appearance->raw_file_start . '-' . $first_appearance->raw_file_end . ':mixed'); } $stmt_type = \Psalm\Type::getMixed(); $statements_analyzer->node_data->setType($stmt, $stmt_type); self::addDataFlowToVariable($statements_analyzer, $stmt, $var_name, $stmt_type, $context); $statements_analyzer->registerPossiblyUndefinedVariable($var_name, $stmt); return \true; } } else { $stmt_type = clone $context->vars_in_scope[$var_name]; $statements_analyzer->node_data->setType($stmt, $stmt_type); self::addDataFlowToVariable($statements_analyzer, $stmt, $var_name, $stmt_type, $context); if ($stmt_type->possibly_undefined_from_try && !$context->inside_isset) { if ($context->is_global) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedGlobalVariable('Possibly undefined global variable ' . $var_name . ' defined in try block', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $var_name), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedVariable('Possibly undefined variable ' . $var_name . ' defined in try block', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt, $stmt_type->getId()); } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $first_appearance = $statements_analyzer->getFirstAppearance($var_name); if ($first_appearance) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt, $first_appearance->raw_file_start . '-' . $first_appearance->raw_file_end . ':' . $stmt_type->getId()); } } } return \true; } private static function addDataFlowToVariable(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable $stmt, string $var_name, \Psalm\Type\Union $stmt_type, \Psalm\Context $context) : void { $codebase = $statements_analyzer->getCodebase(); if ($statements_analyzer->data_flow_graph && $codebase->find_unused_variables && ($context->inside_call || $context->inside_conditional || $context->inside_use || $context->inside_isset)) { if (!$stmt_type->parent_nodes) { $assignment_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_name, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)); $stmt_type->parent_nodes = [$assignment_node->id => $assignment_node]; } foreach ($stmt_type->parent_nodes as $parent_node) { if ($context->inside_call) { $statements_analyzer->data_flow_graph->addPath($parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'use-inside-call'); } elseif ($context->inside_conditional) { $statements_analyzer->data_flow_graph->addPath($parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'use-inside-conditional'); } elseif ($context->inside_isset) { $statements_analyzer->data_flow_graph->addPath($parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'use-inside-isset'); } else { $statements_analyzer->data_flow_graph->addPath($parent_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'variable-use'); } } } } private static function taintVariable(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, string $var_name, \Psalm\Type\Union $type, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable $stmt) : void { if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { if ($var_name === '$_GET' || $var_name === '$_POST' || $var_name === '$_COOKIE' || $var_name === '$_REQUEST') { $taint_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $server_taint_source = new \Psalm\Internal\DataFlow\TaintSource($var_name . ':' . $taint_location->file_name . ':' . $taint_location->raw_file_start, $var_name, null, null, \Psalm\Type\TaintKindGroup::ALL_INPUT); $statements_analyzer->data_flow_graph->addSource($server_taint_source); $type->parent_nodes = [$server_taint_source->id => $server_taint_source]; } } } /** * @psalm-pure */ public static function isSuperGlobal(string $var_id) : bool { return \in_array($var_id, self::SUPER_GLOBALS, \true); } public static function getGlobalType(string $var_id) : \Psalm\Type\Union { $config = \Psalm\Config::getInstance(); if (isset($config->globals[$var_id])) { return \Psalm\Type::parseString($config->globals[$var_id]); } if ($var_id === '$argv') { return new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), \Psalm\Type::getString()])]); } if ($var_id === '$argc') { return \Psalm\Type::getInt(); } if (self::isSuperGlobal($var_id)) { $type = \Psalm\Type::getArray(); return $type; } return \Psalm\Type::getMixed(); } } inside_use; $context->inside_use = \true; if (!$stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->name, $context) === \false) { return \false; } } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $prop_name = $stmt->name->name; } elseif (($stmt_name_type = $statements_analyzer->node_data->getType($stmt->name)) && $stmt_name_type->isSingleStringLiteral()) { $prop_name = $stmt_name_type->getSingleStringLiteral()->value; } else { $prop_name = null; } $codebase = $statements_analyzer->getCodebase(); $stmt_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->var, $statements_analyzer->getFQCLN(), $statements_analyzer); $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($var_id && $context->hasVariable($var_id)) { self::handleScopedProperty($context, $var_id, $statements_analyzer, $stmt, $codebase, $stmt_var_id, $in_assignment); return \true; } if ($stmt_var_id && $context->hasVariable($stmt_var_id)) { $stmt_var_type = $context->vars_in_scope[$stmt_var_id]; } else { $stmt_var_type = $statements_analyzer->node_data->getType($stmt->var); } if (!$stmt_var_type) { return \true; } if ($stmt_var_type->isNull()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullPropertyFetch('Cannot get property on null variable ' . $stmt_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } return \true; } if ($stmt_var_type->isEmpty()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedPropertyFetch('Cannot fetch property on empty var ' . $stmt_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } return \true; } if ($stmt_var_type->hasMixed()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $codebase->analyzer->addMixedMemberName('$' . $stmt->name->name, $context->calling_method_id ?: $statements_analyzer->getFileName()); } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedPropertyFetch('Cannot fetch property on mixed var ' . $stmt_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt->name, $stmt_var_type->getId()); } } if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getRootFilePath()); } if ($stmt_var_type->isNullable() && !$stmt_var_type->ignore_nullable_issues) { if (!$context->inside_isset) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullPropertyFetch('Cannot get property on possibly null variable ' . $stmt_var_id . ' of type ' . $stmt_var_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getNull()); } } if (!$prop_name) { if ($stmt_var_type->hasObjectType() && !$context->ignore_variable_property) { foreach ($stmt_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TNamedObject) { $codebase->analyzer->addMixedMemberName(\strtolower($type->value) . '::$', $context->calling_method_id ?: $statements_analyzer->getFileName()); } } } return \true; } $invalid_fetch_types = []; $has_valid_fetch_type = \false; foreach ($stmt_var_type->getAtomicTypes() as $lhs_type_part) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\AtomicPropertyFetchAnalyzer::analyze($statements_analyzer, $stmt, $context, $in_assignment, $var_id, $stmt_var_id, $stmt_var_type, $lhs_type_part, $prop_name, $has_valid_fetch_type, $invalid_fetch_types); } $stmt_type = $statements_analyzer->node_data->getType($stmt); if ($stmt_var_type->isNullable() && !$context->inside_isset && $stmt_type) { $stmt_type->addType(new \Psalm\Type\Atomic\TNull()); if ($stmt_var_type->ignore_nullable_issues) { $stmt_type->ignore_nullable_issues = \true; } } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations && ($stmt_type = $statements_analyzer->node_data->getType($stmt))) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt->name, $stmt_type->getId()); } if ($invalid_fetch_types) { $lhs_type_part = $invalid_fetch_types[0]; if ($has_valid_fetch_type) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidPropertyFetch('Cannot fetch property on possible non-object ' . $stmt_var_id . ' of type ' . $lhs_type_part, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidPropertyFetch('Cannot fetch property on non-object ' . $stmt_var_id . ' of type ' . $lhs_type_part, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if ($var_id) { $context->vars_in_scope[$var_id] = $statements_analyzer->node_data->getType($stmt) ?: \Psalm\Type::getMixed(); } return \true; } private static function handleScopedProperty(\Psalm\Context $context, string $var_id, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch $stmt, \Psalm\Codebase $codebase, ?string $stmt_var_id, bool $in_assignment) : void { $stmt_type = $context->vars_in_scope[$var_id]; // we don't need to check anything $statements_analyzer->node_data->setType($stmt, $stmt_type); if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt->name, $stmt_type->getId()); } if ($stmt_var_id === '$this' && !$stmt_type->initialized && $context->collect_initializations && ($stmt_var_type = $statements_analyzer->node_data->getType($stmt->var)) && $stmt_var_type->hasObjectType() && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $source = $statements_analyzer->getSource(); $property_id = null; foreach ($stmt_var_type->getAtomicTypes() as $lhs_type_part) { if ($lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { if (!$codebase->classExists($lhs_type_part->value)) { continue; } $property_id = $lhs_type_part->value . '::$' . $stmt->name->name; } } if ($property_id && $source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $source->getMethodName() === '__construct' && !$context->inside_unset) { if ($context->inside_isset || $context->inside_assignment && isset($context->vars_in_scope[$var_id]) && $context->vars_in_scope[$var_id]->isNullable()) { $stmt_type->initialized = \true; } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UninitializedProperty('Cannot use uninitialized property ' . $var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $var_id), $statements_analyzer->getSuppressedIssues())) { // fall through } $stmt_type->addType(new \Psalm\Type\Atomic\TNull()); } } } if (($stmt_var_type = $statements_analyzer->node_data->getType($stmt->var)) && $stmt_var_type->hasObjectType() && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { // log the appearance foreach ($stmt_var_type->getAtomicTypes() as $lhs_type_part) { if ($lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { if (!$codebase->classExists($lhs_type_part->value)) { continue; } $property_id = $lhs_type_part->value . '::$' . $stmt->name->name; $class_storage = $codebase->classlike_storage_provider->get($lhs_type_part->value); \Psalm\Internal\Analyzer\Statements\Expression\Fetch\AtomicPropertyFetchAnalyzer::processTaints($statements_analyzer, $stmt, $stmt_type, $property_id, $class_storage, $in_assignment); $codebase->properties->propertyExists($property_id, \true, $statements_analyzer, $context, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null); if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->name, $property_id); } if (!$context->collect_mutations && !$context->collect_initializations && !($class_storage->external_mutation_free && $stmt_type->allow_mutations)) { if ($context->pure) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpurePropertyFetch('Cannot access a property on a mutable object from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_impure = \true; } } } } } } } class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { self::analyzeVariableStaticPropertyFetch($statements_analyzer, $stmt->class, $stmt, $context); return \true; } $codebase = $statements_analyzer->getCodebase(); if (\count($stmt->class->parts) === 1 && \in_array(\strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], \true)) { if ($stmt->class->parts[0] === 'parent') { $fq_class_name = $statements_analyzer->getParentFQCLN(); if ($fq_class_name === null) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParentNotFound('Cannot check property fetch on parent as this class does not extend another', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } return \true; } } else { $fq_class_name = (string) $context->self; } if ($context->isPhantomClass($fq_class_name)) { return \true; } } else { $aliases = $statements_analyzer->getAliases(); if ($context->calling_method_id && !$stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified) { $codebase->file_reference_provider->addMethodReferenceToClassMember($context->calling_method_id, 'use:' . $stmt->class->parts[0] . ':' . \md5($statements_analyzer->getFilePath())); } $fq_class_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($stmt->class, $aliases); if ($context->isPhantomClass($fq_class_name)) { return \true; } if ($context->check_classes) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_class_name, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->class), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues(), \false) !== \true) { return \false; } } } if ($fq_class_name && $codebase->methods_to_move && $context->calling_method_id && isset($codebase->methods_to_move[$context->calling_method_id])) { $destination_method_id = $codebase->methods_to_move[$context->calling_method_id]; $codebase->classlikes->airliftClassLikeReference($fq_class_name, \explode('::', $destination_method_id)[0], $statements_analyzer->getFilePath(), (int) $stmt->class->getAttribute('startFilePos'), (int) $stmt->class->getAttribute('endFilePos') + 1); } if ($fq_class_name) { $statements_analyzer->node_data->setType($stmt->class, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($fq_class_name)])); } if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\VarLikeIdentifier) { $prop_name = $stmt->name->name; } elseif (($stmt_name_type = $statements_analyzer->node_data->getType($stmt->name)) && $stmt_name_type->isSingleStringLiteral()) { $prop_name = $stmt_name_type->getSingleStringLiteral()->value; } else { $prop_name = null; } if (!$prop_name) { if ($fq_class_name) { $codebase->analyzer->addMixedMemberName(\strtolower($fq_class_name) . '::$', $context->calling_method_id ?: $statements_analyzer->getFileName()); } return \true; } if (!$fq_class_name || !$context->check_classes || !$context->check_variables || \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::isMock($fq_class_name)) { return \true; } $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($stmt, $context->self ?: $statements_analyzer->getFQCLN(), $statements_analyzer); $property_id = $fq_class_name . '::$' . $prop_name; if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->name, $property_id); } if ($context->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureStaticProperty('Cannot use a static property in a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } if ($var_id && $context->hasVariable($var_id)) { $stmt_type = $context->vars_in_scope[$var_id]; // we don't need to check anything $statements_analyzer->node_data->setType($stmt, $stmt_type); if ($codebase->collect_references) { // log the appearance $codebase->properties->propertyExists($property_id, \true, $statements_analyzer, $context, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null); } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations && ($stmt_type = $statements_analyzer->node_data->getType($stmt))) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt->name, $stmt_type->getId()); } return \true; } if (!$codebase->properties->propertyExists($property_id, \true, $statements_analyzer, $context, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null)) { if ($context->inside_isset) { return \true; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedPropertyFetch('Static property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } return \true; } if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkPropertyVisibility($property_id, $context, $statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues()) === \false) { return \false; } $declaring_property_class = $codebase->properties->getDeclaringClassForProperty($fq_class_name . '::$' . $prop_name, \true, $statements_analyzer); if ($declaring_property_class === null) { return \false; } $declaring_property_id = \strtolower($declaring_property_class) . '::$' . $prop_name; if ($codebase->alter_code) { $moved_class = $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $stmt->class, $fq_class_name, $context->calling_method_id); if (!$moved_class) { foreach ($codebase->property_transforms as $original_pattern => $transformation) { if ($declaring_property_id === $original_pattern) { [$old_declaring_fq_class_name] = \explode('::$', $declaring_property_id); [$new_fq_class_name, $new_property_name] = \explode('::$', $transformation); $file_manipulations = []; if (\strtolower($new_fq_class_name) !== \strtolower($old_declaring_fq_class_name)) { $file_manipulations[] = new \Psalm\FileManipulation((int) $stmt->class->getAttribute('startFilePos'), (int) $stmt->class->getAttribute('endFilePos') + 1, \Psalm\Type::getStringFromFQCLN($new_fq_class_name, $statements_analyzer->getNamespace(), $statements_analyzer->getAliasedClassesFlipped(), null)); } $file_manipulations[] = new \Psalm\FileManipulation((int) $stmt->name->getAttribute('startFilePos'), (int) $stmt->name->getAttribute('endFilePos') + 1, '$' . $new_property_name); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } } } $class_storage = $codebase->classlike_storage_provider->get($declaring_property_class); $property = $class_storage->properties[$prop_name]; if ($var_id) { if ($property->type) { $context->vars_in_scope[$var_id] = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, clone $property->type, $class_storage->name, $class_storage->name, $class_storage->parent_class); } else { $context->vars_in_scope[$var_id] = \Psalm\Type::getMixed(); } $stmt_type = clone $context->vars_in_scope[$var_id]; $statements_analyzer->node_data->setType($stmt, $stmt_type); if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt->name, $stmt_type->getId()); } } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } return \true; } private static function analyzeVariableStaticPropertyFetch(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt_class, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch $stmt, \Psalm\Context $context) : void { $was_inside_use = $context->inside_use; $context->inside_use = \true; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt_class, $context); $context->inside_use = $was_inside_use; $stmt_class_type = $statements_analyzer->node_data->getType($stmt_class) ?: \Psalm\Type::getMixed(); $old_data_provider = $statements_analyzer->node_data; $stmt_type = null; $codebase = $statements_analyzer->getCodebase(); foreach ($stmt_class_type->getAtomicTypes() as $class_atomic_type) { $statements_analyzer->node_data = clone $statements_analyzer->node_data; $string_type = $class_atomic_type instanceof \Psalm\Type\Atomic\TClassString && $class_atomic_type->as_type !== null ? $class_atomic_type->as_type->value : ($class_atomic_type instanceof \Psalm\Type\Atomic\TLiteralString ? $class_atomic_type->value : null); if ($string_type) { $new_stmt_name = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($string_type, $stmt_class->getAttributes()); $fake_static_property = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch($new_stmt_name, $stmt->name, $stmt->getAttributes()); self::analyze($statements_analyzer, $fake_static_property, $context); $fake_stmt_type = $statements_analyzer->node_data->getType($fake_static_property) ?: \Psalm\Type::getMixed(); } else { $fake_var_name = '__fake_var_' . (string) $stmt->getAttribute('startFilePos'); $fake_var = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($fake_var_name, $stmt_class->getAttributes()); $context->vars_in_scope['$' . $fake_var_name] = new \Psalm\Type\Union([$class_atomic_type]); $fake_instance_property = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($fake_var, $stmt->name, $stmt->getAttributes()); \Psalm\Internal\Analyzer\Statements\Expression\Fetch\InstancePropertyFetchAnalyzer::analyze($statements_analyzer, $fake_instance_property, $context); $fake_stmt_type = $statements_analyzer->node_data->getType($fake_instance_property) ?: \Psalm\Type::getMixed(); } $stmt_type = $stmt_type ? \Psalm\Type::combineUnionTypes($stmt_type, $fake_stmt_type, $codebase) : $fake_stmt_type; $statements_analyzer->node_data = $old_data_provider; } $statements_analyzer->node_data->setType($stmt, $stmt_type); } } var, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($stmt->dim) { $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->dim, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; } $keyed_array_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt, $statements_analyzer->getFQCLN(), $statements_analyzer); $dim_var_id = null; $new_offset_type = null; if ($stmt->dim) { $used_key_type = $statements_analyzer->node_data->getType($stmt->dim) ?: \Psalm\Type::getMixed(); $dim_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->dim, $statements_analyzer->getFQCLN(), $statements_analyzer); } else { $used_key_type = \Psalm\Type::getInt(); } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === \false) { return \false; } $stmt_var_type = $statements_analyzer->node_data->getType($stmt->var); $codebase = $statements_analyzer->getCodebase(); if ($keyed_array_var_id && $context->hasVariable($keyed_array_var_id) && !$context->vars_in_scope[$keyed_array_var_id]->possibly_undefined && $stmt_var_type && !$stmt_var_type->hasClassStringMap()) { $stmt_type = clone $context->vars_in_scope[$keyed_array_var_id]; $statements_analyzer->node_data->setType($stmt, $stmt_type); self::taintArrayFetch($statements_analyzer, $stmt->var, $keyed_array_var_id, $stmt_type, $used_key_type); return \true; } $can_store_result = \false; if ($stmt_var_type) { if ($stmt_var_type->isNull()) { if (!$context->inside_isset) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullArrayAccess('Cannot access array value on null variable ' . $array_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($stmt_type = $statements_analyzer->node_data->getType($stmt)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::combineUnionTypes($stmt_type, \Psalm\Type::getNull())); } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getNull()); } return \true; } $stmt_type = self::getArrayAccessTypeGivenOffset($statements_analyzer, $stmt, $stmt_var_type, $used_key_type, \false, $array_var_id, $context, null); if ($stmt->dim && $stmt_var_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var TArray|TKeyedArray|TList|Type\Atomic\TClassStringMap */ $array_type = $stmt_var_type->getAtomicTypes()['array']; if ($array_type instanceof \Psalm\Type\Atomic\TClassStringMap) { $array_value_type = \Psalm\Type::getMixed(); } elseif ($array_type instanceof \Psalm\Type\Atomic\TArray) { $array_value_type = $array_type->type_params[1]; } elseif ($array_type instanceof \Psalm\Type\Atomic\TList) { $array_value_type = $array_type->type_param; } else { $array_value_type = $array_type->getGenericValueType(); } if ($context->inside_assignment || !$array_value_type->isMixed()) { $can_store_result = \true; } } $statements_analyzer->node_data->setType($stmt, $stmt_type); if ($context->inside_isset && $stmt->dim && ($stmt_dim_type = $statements_analyzer->node_data->getType($stmt->dim)) && $stmt_var_type->hasArray() && ($stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || $stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch)) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var TArray|TKeyedArray|TList */ $array_type = $stmt_var_type->getAtomicTypes()['array']; if ($array_type instanceof \Psalm\Type\Atomic\TArray) { $const_array_key_type = $array_type->type_params[0]; } elseif ($array_type instanceof \Psalm\Type\Atomic\TList) { $const_array_key_type = \Psalm\Type::getInt(); } else { $const_array_key_type = $array_type->getGenericKeyType(); } if ($dim_var_id && !$const_array_key_type->hasMixed() && !$stmt_dim_type->hasMixed()) { $new_offset_type = clone $stmt_dim_type; $const_array_key_atomic_types = $const_array_key_type->getAtomicTypes(); foreach ($new_offset_type->getAtomicTypes() as $offset_key => $offset_atomic_type) { if ($offset_atomic_type instanceof \Psalm\Type\Atomic\TString || $offset_atomic_type instanceof \Psalm\Type\Atomic\TInt) { if (!isset($const_array_key_atomic_types[$offset_key]) && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, new \Psalm\Type\Union([$offset_atomic_type]), $const_array_key_type)) { $new_offset_type->removeType($offset_key); } } elseif (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $const_array_key_type, new \Psalm\Type\Union([$offset_atomic_type]))) { $new_offset_type->removeType($offset_key); } } } } } if ($keyed_array_var_id && $context->hasVariable($keyed_array_var_id) && (!($stmt_type = $statements_analyzer->node_data->getType($stmt)) || $stmt_type->isVanillaMixed())) { $statements_analyzer->node_data->setType($stmt, $context->vars_in_scope[$keyed_array_var_id]); } if (!($stmt_type = $statements_analyzer->node_data->getType($stmt))) { $stmt_type = \Psalm\Type::getMixed(); $statements_analyzer->node_data->setType($stmt, $stmt_type); } else { if ($stmt_type->possibly_undefined && !$context->inside_isset && !$context->inside_unset && ($stmt_var_type && !$stmt_var_type->hasMixed())) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedArrayOffset('Possibly undefined array key ' . $keyed_array_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $stmt_type->possibly_undefined = \false; } if ($context->inside_isset && $dim_var_id && $new_offset_type && $new_offset_type->getAtomicTypes()) { $context->vars_in_scope[$dim_var_id] = $new_offset_type; } if ($keyed_array_var_id && !$context->inside_isset && $can_store_result) { $context->vars_in_scope[$keyed_array_var_id] = $stmt_type; $context->vars_possibly_in_scope[$keyed_array_var_id] = \true; // reference the variable too $context->hasVariable($keyed_array_var_id); } self::taintArrayFetch($statements_analyzer, $stmt->var, $keyed_array_var_id, $stmt_type, $used_key_type); return \true; } /** * Used to create a path between a variable $foo and $foo["a"] */ public static function taintArrayFetch(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $var, ?string $keyed_array_var_id, \Psalm\Type\Union $stmt_type, \Psalm\Type\Union $offset_type) : void { if ($statements_analyzer->data_flow_graph && ($stmt_var_type = $statements_analyzer->node_data->getType($var)) && $stmt_var_type->parent_nodes) { if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $stmt_var_type->parent_nodes = []; return; } $var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $var); $new_parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($keyed_array_var_id ?: 'array-fetch', $var_location); $statements_analyzer->data_flow_graph->addNode($new_parent_node); $dim_value = $offset_type->isSingleStringLiteral() ? $offset_type->getSingleStringLiteral()->value : ($offset_type->isSingleIntLiteral() ? $offset_type->getSingleIntLiteral()->value : null); foreach ($stmt_var_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $new_parent_node, 'array-fetch' . ($dim_value !== null ? '-\'' . $dim_value . '\'' : '')); if ($stmt_type->by_ref) { $statements_analyzer->data_flow_graph->addPath($new_parent_node, $parent_node, 'array-assignment' . ($dim_value !== null ? '-\'' . $dim_value . '\'' : '')); } } $stmt_type->parent_nodes = [$new_parent_node->id => $new_parent_node]; } } public static function getArrayAccessTypeGivenOffset(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch $stmt, \Psalm\Type\Union $array_type, \Psalm\Type\Union $offset_type, bool $in_assignment, ?string $array_var_id, \Psalm\Context $context, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $assign_value = null, \Psalm\Type\Union $replacement_type = null) : \Psalm\Type\Union { $codebase = $statements_analyzer->getCodebase(); $has_array_access = \false; $non_array_types = []; $has_valid_offset = \false; $expected_offset_types = []; $key_values = []; if ($stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $key_values[] = $stmt->dim->value; } elseif ($stmt->dim && ($stmt_dim_type = $statements_analyzer->node_data->getType($stmt->dim))) { $string_literals = $stmt_dim_type->getLiteralStrings(); $int_literals = $stmt_dim_type->getLiteralInts(); $all_atomic_types = $stmt_dim_type->getAtomicTypes(); if (\count($string_literals) + \count($int_literals) === \count($all_atomic_types)) { foreach ($string_literals as $string_literal) { $key_values[] = $string_literal->value; } foreach ($int_literals as $int_literal) { $key_values[] = $int_literal->value; } } } $array_access_type = null; if ($offset_type->isNull()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullArrayOffset('Cannot access value on variable ' . $array_var_id . ' using null offset', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } if ($in_assignment) { $offset_type->removeType('null'); $offset_type->addType(new \Psalm\Type\Atomic\TLiteralInt(0)); } } if ($offset_type->isNullable() && !$context->inside_isset) { if (!$offset_type->ignore_nullable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullArrayOffset('Cannot access value on variable ' . $array_var_id . ' using possibly null offset ' . $offset_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($in_assignment) { $offset_type->removeType('null'); if (!$offset_type->ignore_nullable_issues) { $offset_type->addType(new \Psalm\Type\Atomic\TLiteralInt(0)); } } } foreach ($array_type->getAtomicTypes() as $type_string => $type) { $original_type = $type; if ($type instanceof \Psalm\Type\Atomic\TMixed || $type instanceof \Psalm\Type\Atomic\TTemplateParam || $type instanceof \Psalm\Type\Atomic\TEmpty) { if (!$type instanceof \Psalm\Type\Atomic\TTemplateParam || $type->as->isMixed() || !$type->as->isSingle()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if (!$context->inside_isset) { if ($in_assignment) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArrayAssignment('Cannot access array value on mixed variable ' . $array_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArrayAccess('Cannot access array value on mixed variable ' . $array_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } $has_valid_offset = \true; if (!$array_access_type) { $array_access_type = \Psalm\Type::getMixed($type instanceof \Psalm\Type\Atomic\TEmpty); } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, \Psalm\Type::getMixed($type instanceof \Psalm\Type\Atomic\TEmpty)); } continue; } $type = clone \array_values($type->as->getAtomicTypes())[0]; } if ($type instanceof \Psalm\Type\Atomic\TNull) { if ($array_type->ignore_nullable_issues) { continue; } if ($in_assignment) { if ($replacement_type) { if ($array_access_type) { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, $replacement_type); } else { $array_access_type = clone $replacement_type; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullArrayAssignment('Cannot access array value on possibly null variable ' . $array_var_id . ' of type ' . $array_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } $array_access_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()]); } } else { if (!$context->inside_isset) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullArrayAccess('Cannot access array value on possibly null variable ' . $array_var_id . ' of type ' . $array_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($array_access_type) { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, \Psalm\Type::getNull()); } else { $array_access_type = \Psalm\Type::getNull(); } } continue; } if ($type instanceof \Psalm\Type\Atomic\TArray || $type instanceof \Psalm\Type\Atomic\TKeyedArray || $type instanceof \Psalm\Type\Atomic\TList || $type instanceof \Psalm\Type\Atomic\TClassStringMap) { $has_array_access = \true; if ($in_assignment && $type instanceof \Psalm\Type\Atomic\TArray && ($type->type_params[0]->isEmpty() && $type->type_params[1]->isEmpty() || $type->type_params[1]->hasMixed() && \count($key_values) === 1 && \is_string($key_values[0]))) { $from_empty_array = $type->type_params[0]->isEmpty() && $type->type_params[1]->isEmpty(); if (\count($key_values) === 1) { $from_mixed_array = $type->type_params[1]->isMixed(); [$previous_key_type, $previous_value_type] = $type->type_params; // ok, type becomes an TKeyedArray $array_type->removeType($type_string); $type = new \Psalm\Type\Atomic\TKeyedArray([$key_values[0] => $from_mixed_array ? \Psalm\Type::getMixed() : \Psalm\Type::getEmpty()]); $type->sealed = $from_empty_array; if (!$from_empty_array) { $type->previous_value_type = clone $previous_value_type; $type->previous_key_type = clone $previous_key_type; } $array_type->addType($type); } elseif (!$stmt->dim && $from_empty_array && $replacement_type) { $array_type->removeType($type_string); $array_type->addType(new \Psalm\Type\Atomic\TNonEmptyList($replacement_type)); continue; } } elseif ($in_assignment && $type instanceof \Psalm\Type\Atomic\TKeyedArray && $type->previous_value_type && $type->previous_value_type->isMixed() && \count($key_values) === 1) { $type->properties[$key_values[0]] = \Psalm\Type::getMixed(); } $offset_type = self::replaceOffsetTypeWithInts($offset_type); if ($type instanceof \Psalm\Type\Atomic\TList && ($in_assignment && $stmt->dim || $original_type instanceof \Psalm\Type\Atomic\TTemplateParam || !$offset_type->isInt())) { $type = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $type->type_param]); } if ($type instanceof \Psalm\Type\Atomic\TArray) { // if we're assigning to an empty array with a key offset, refashion that array if ($in_assignment) { if ($type->type_params[0]->isEmpty()) { $type->type_params[0] = $offset_type->isMixed() ? \Psalm\Type::getArrayKey() : $offset_type; } } elseif (!$type->type_params[0]->isEmpty()) { $expected_offset_type = $type->type_params[0]->hasMixed() ? new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArrayKey()]) : $type->type_params[0]; $templated_offset_type = null; foreach ($offset_type->getAtomicTypes() as $offset_atomic_type) { if ($offset_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $templated_offset_type = $offset_atomic_type; } } $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if ($original_type instanceof \Psalm\Type\Atomic\TTemplateParam && $templated_offset_type) { foreach ($templated_offset_type->as->getAtomicTypes() as $offset_as) { if ($offset_as instanceof \Psalm\Type\Atomic\TTemplateKeyOf && $offset_as->param_name === $original_type->param_name && $offset_as->defining_class === $original_type->defining_class) { /** @psalm-suppress PropertyTypeCoercion */ $type->type_params[1] = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateIndexedAccess($offset_as->param_name, $templated_offset_type->param_name, $offset_as->defining_class)]); $has_valid_offset = \true; } } } else { $offset_type_contained_by_expected = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $offset_type, $expected_offset_type, \true, $offset_type->ignore_falsable_issues, $union_comparison_results); if ($codebase->config->ensure_array_string_offsets_exist && $offset_type_contained_by_expected) { self::checkLiteralStringArrayOffset($offset_type, $expected_offset_type, $array_var_id, $stmt, $context, $statements_analyzer); } if ($codebase->config->ensure_array_int_offsets_exist && $offset_type_contained_by_expected) { self::checkLiteralIntArrayOffset($offset_type, $expected_offset_type, $array_var_id, $stmt, $context, $statements_analyzer); } if (!$offset_type_contained_by_expected && !$union_comparison_results->type_coerced_from_scalar || $union_comparison_results->to_string_cast) { if ($union_comparison_results->type_coerced_from_mixed && !$offset_type->isMixed()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArrayTypeCoercion('Coercion from array offset type \'' . $offset_type->getId() . '\' ' . 'to the expected type \'' . $expected_offset_type->getId() . '\'', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { $expected_offset_types[] = $expected_offset_type->getId(); } if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $offset_type, $expected_offset_type)) { $has_valid_offset = \true; } } else { $has_valid_offset = \true; } } } if (!$stmt->dim && $type instanceof \Psalm\Type\Atomic\TNonEmptyArray && $type->count !== null) { $type->count++; } if ($in_assignment && $replacement_type) { /** @psalm-suppress PropertyTypeCoercion */ $type->type_params[1] = \Psalm\Type::combineUnionTypes($type->type_params[1], $replacement_type, $codebase); } if (!$array_access_type) { $array_access_type = $type->type_params[1]; } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, $type->type_params[1]); } if ($array_access_type->isEmpty() && !$array_type->hasMixed() && !$in_assignment && !$context->inside_isset) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\EmptyArrayAccess('Cannot access value on empty array variable ' . $array_var_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \Psalm\Type::getMixed(\true); } if (!\Psalm\IssueBuffer::isRecording()) { $array_access_type = \Psalm\Type::getMixed(\true); } } } elseif ($type instanceof \Psalm\Type\Atomic\TList) { // if we're assigning to an empty array with a key offset, refashion that array if (!$in_assignment) { if (!$type instanceof \Psalm\Type\Atomic\TNonEmptyList || \count($key_values) === 1 && \is_int($key_values[0]) && $key_values[0] > 0 && $key_values[0] > $type->count - 1) { $expected_offset_type = \Psalm\Type::getInt(); if ($codebase->config->ensure_array_int_offsets_exist) { self::checkLiteralIntArrayOffset($offset_type, $expected_offset_type, $array_var_id, $stmt, $context, $statements_analyzer); } } $has_valid_offset = \true; } if ($in_assignment && $type instanceof \Psalm\Type\Atomic\TNonEmptyList && $type->count !== null) { $type->count++; } if ($in_assignment && $replacement_type) { $type->type_param = \Psalm\Type::combineUnionTypes($type->type_param, $replacement_type, $codebase); } if (!$array_access_type) { $array_access_type = $type->type_param; } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, $type->type_param); } } elseif ($type instanceof \Psalm\Type\Atomic\TClassStringMap) { $offset_type_parts = \array_values($offset_type->getAtomicTypes()); foreach ($offset_type_parts as $offset_type_part) { if ($offset_type_part instanceof \Psalm\Type\Atomic\TClassString) { if ($offset_type_part instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $template_result_get = new \Psalm\Internal\Type\TemplateResult([], [$type->param_name => ['class-string-map' => [new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParam($offset_type_part->param_name, $offset_type_part->as_type ? new \Psalm\Type\Union([$offset_type_part->as_type]) : \Psalm\Type::getObject(), $offset_type_part->defining_class)])]]]); $template_result_set = new \Psalm\Internal\Type\TemplateResult([], [$offset_type_part->param_name => [$offset_type_part->defining_class => [new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParam($type->param_name, $type->as_type ? new \Psalm\Type\Union([$type->as_type]) : \Psalm\Type::getObject(), 'class-string-map')])]]]); } else { $template_result_get = new \Psalm\Internal\Type\TemplateResult([], [$type->param_name => ['class-string-map' => [new \Psalm\Type\Union([$offset_type_part->as_type ?: new \Psalm\Type\Atomic\TObject()])]]]); $template_result_set = new \Psalm\Internal\Type\TemplateResult([], []); } $expected_value_param_get = clone $type->value_param; $expected_value_param_get->replaceTemplateTypesWithArgTypes($template_result_get, $codebase); if ($replacement_type) { $expected_value_param_set = clone $type->value_param; $replacement_type->replaceTemplateTypesWithArgTypes($template_result_set, $codebase); $type->value_param = \Psalm\Type::combineUnionTypes($replacement_type, $expected_value_param_set, $codebase); } if (!$array_access_type) { $array_access_type = $expected_value_param_get; } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, $expected_value_param_get, $codebase); } } } } else { $generic_key_type = $type->getGenericKeyType(); if (!$stmt->dim && $type->sealed && $type->is_list) { $key_values[] = \count($type->properties); } if ($key_values) { foreach ($key_values as $key_value) { if (isset($type->properties[$key_value]) || $replacement_type) { $has_valid_offset = \true; if ($replacement_type) { if (isset($type->properties[$key_value])) { $type->properties[$key_value] = \Psalm\Type::combineUnionTypes($type->properties[$key_value], $replacement_type); } else { $type->properties[$key_value] = $replacement_type; } } if (!$array_access_type) { $array_access_type = clone $type->properties[$key_value]; } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, $type->properties[$key_value]); } } elseif ($in_assignment) { $type->properties[$key_value] = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()]); if (!$array_access_type) { $array_access_type = clone $type->properties[$key_value]; } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, $type->properties[$key_value]); } } elseif ($type->previous_value_type) { if ($codebase->config->ensure_array_string_offsets_exist) { self::checkLiteralStringArrayOffset($offset_type, $type->getGenericKeyType(), $array_var_id, $stmt, $context, $statements_analyzer); } if ($codebase->config->ensure_array_int_offsets_exist) { self::checkLiteralIntArrayOffset($offset_type, $type->getGenericKeyType(), $array_var_id, $stmt, $context, $statements_analyzer); } $type->properties[$key_value] = clone $type->previous_value_type; $array_access_type = clone $type->previous_value_type; } elseif ($array_type->hasMixed()) { $has_valid_offset = \true; $array_access_type = \Psalm\Type::getMixed(); } else { if ($type->sealed || !$context->inside_isset) { $object_like_keys = \array_keys($type->properties); if (\count($object_like_keys) === 1) { $expected_keys_string = '\'' . $object_like_keys[0] . '\''; } else { $last_key = \array_pop($object_like_keys); $expected_keys_string = '\'' . \implode('\', \'', $object_like_keys) . '\' or \'' . $last_key . '\''; } $expected_offset_types[] = $expected_keys_string; } $array_access_type = \Psalm\Type::getMixed(); } } } else { $key_type = $generic_key_type->hasMixed() ? \Psalm\Type::getArrayKey() : $generic_key_type; $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $is_contained = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $offset_type, $key_type, \true, $offset_type->ignore_falsable_issues, $union_comparison_results); if ($context->inside_isset && !$is_contained) { $is_contained = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $key_type, $offset_type, \true, $offset_type->ignore_falsable_issues) || \Psalm\Internal\Type\Comparator\UnionTypeComparator::canBeContainedBy($codebase, $offset_type, $key_type, \true, $offset_type->ignore_falsable_issues); } if (($is_contained || $union_comparison_results->type_coerced_from_scalar || $union_comparison_results->type_coerced_from_mixed || $in_assignment) && !$union_comparison_results->to_string_cast) { if ($replacement_type) { $generic_params = \Psalm\Type::combineUnionTypes($type->getGenericValueType(), $replacement_type); $new_key_type = \Psalm\Type::combineUnionTypes($generic_key_type, $offset_type->isMixed() ? \Psalm\Type::getArrayKey() : $offset_type); $property_count = $type->sealed ? \count($type->properties) : null; if (!$stmt->dim && $property_count) { ++$property_count; $array_type->removeType($type_string); $type = new \Psalm\Type\Atomic\TNonEmptyArray([$new_key_type, $generic_params]); $array_type->addType($type); $type->count = $property_count; } else { $array_type->removeType($type_string); if (!$stmt->dim && $type->is_list) { $type = new \Psalm\Type\Atomic\TList($generic_params); } else { $type = new \Psalm\Type\Atomic\TArray([$new_key_type, $generic_params]); } $array_type->addType($type); } if (!$array_access_type) { $array_access_type = clone $generic_params; } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, $generic_params); } } else { if (!$array_access_type) { $array_access_type = $type->getGenericValueType(); } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, $type->getGenericValueType()); } } $has_valid_offset = \true; } else { if (!$context->inside_isset || $type->sealed && !$union_comparison_results->type_coerced) { $expected_offset_types[] = $generic_key_type->getId(); } $array_access_type = \Psalm\Type::getMixed(); } } } continue; } if ($type instanceof \Psalm\Type\Atomic\TString) { if ($in_assignment && $replacement_type) { if ($replacement_type->hasMixed()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedStringOffsetAssignment('Right-hand-side of string offset assignment cannot be mixed', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } } } if ($type instanceof \Psalm\Type\Atomic\TSingleLetter) { $valid_offset_type = \Psalm\Type::getInt(\false, 0); } elseif ($type instanceof \Psalm\Type\Atomic\TLiteralString) { if (!\strlen($type->value)) { $valid_offset_type = \Psalm\Type::getEmpty(); } elseif (\strlen($type->value) < 10) { $valid_offsets = []; for ($i = -\strlen($type->value), $l = \strlen($type->value); $i < $l; $i++) { $valid_offsets[] = new \Psalm\Type\Atomic\TLiteralInt($i); } if (!$valid_offsets) { throw new \UnexpectedValueException('This is weird'); } $valid_offset_type = new \Psalm\Type\Union($valid_offsets); } else { $valid_offset_type = \Psalm\Type::getInt(); } } else { $valid_offset_type = \Psalm\Type::getInt(); } if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $offset_type, $valid_offset_type, \true)) { $expected_offset_types[] = $valid_offset_type->getId(); $array_access_type = \Psalm\Type::getMixed(); } else { $has_valid_offset = \true; if (!$array_access_type) { $array_access_type = \Psalm\Type::getSingleLetter(); } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, \Psalm\Type::getSingleLetter()); } } continue; } if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } if ($type instanceof \Psalm\Type\Atomic\TFalse && $array_type->ignore_falsable_issues) { continue; } if ($type instanceof \Psalm\Type\Atomic\TNamedObject) { if (\strtolower($type->value) === 'simplexmlelement') { $call_array_access_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject('SimpleXMLElement')]); } elseif (\strtolower($type->value) === 'domnodelist' && $stmt->dim) { $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($stmt->var, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('item', $stmt->var->getAttributes()), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($stmt->dim)]); $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('MixedMethodCall', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['MixedMethodCall']); } \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_method_call, $context); if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('MixedMethodCall', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['MixedMethodCall']); } $call_array_access_type = $statements_analyzer->node_data->getType($fake_method_call) ?: \Psalm\Type::getMixed(); $statements_analyzer->node_data = $old_data_provider; } else { $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('MixedMethodCall', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['MixedMethodCall']); } if ($in_assignment) { $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_set_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($stmt->var, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('offsetSet', $stmt->var->getAttributes()), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($stmt->dim ? $stmt->dim : new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('null'), $stmt->var->getAttributes())), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($assign_value ?: new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('null'), $stmt->var->getAttributes()))]); \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_set_method_call, $context); $statements_analyzer->node_data = $old_node_data; } if ($stmt->dim) { $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_get_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($stmt->var, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('offsetGet', $stmt->var->getAttributes()), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($stmt->dim)]); \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_get_method_call, $context); $call_array_access_type = $statements_analyzer->node_data->getType($fake_get_method_call) ?: \Psalm\Type::getMixed(); $statements_analyzer->node_data = $old_node_data; } else { $call_array_access_type = \Psalm\Type::getVoid(); } $has_array_access = \true; if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('MixedMethodCall', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['MixedMethodCall']); } } if (!$array_access_type) { $array_access_type = $call_array_access_type; } else { $array_access_type = \Psalm\Type::combineUnionTypes($array_access_type, $call_array_access_type); } } elseif (!$array_type->hasMixed()) { $non_array_types[] = (string) $type; } } if ($non_array_types) { if ($has_array_access) { if ($in_assignment) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidArrayAssignment('Cannot access array value on non-array variable ' . $array_var_id . ' of type ' . $non_array_types[0], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // do nothing } } elseif (!$context->inside_isset) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidArrayAccess('Cannot access array value on non-array variable ' . $array_var_id . ' of type ' . $non_array_types[0], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // do nothing } } } else { if ($in_assignment) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArrayAssignment('Cannot access array value on non-array variable ' . $array_var_id . ' of type ' . $non_array_types[0], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArrayAccess('Cannot access array value on non-array variable ' . $array_var_id . ' of type ' . $non_array_types[0], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $array_access_type = \Psalm\Type::getMixed(); } } if ($offset_type->hasMixed()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedArrayOffset('Cannot access value on variable ' . $array_var_id . ' using mixed offset', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } if ($expected_offset_types) { $invalid_offset_type = $expected_offset_types[0]; $used_offset = 'using a ' . $offset_type->getId() . ' offset'; if ($key_values) { $used_offset = 'using offset value of ' . (\is_int($key_values[0]) ? $key_values[0] : '\'' . $key_values[0] . '\''); } if ($has_valid_offset && $context->inside_isset) { // do nothing } elseif ($has_valid_offset) { if (!$context->inside_unset) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidArrayOffset('Cannot access value on variable ' . $array_var_id . ' ' . $used_offset . ', expecting ' . $invalid_offset_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArrayOffset('Cannot access value on variable ' . $array_var_id . ' ' . $used_offset . ', expecting ' . $invalid_offset_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } if ($array_access_type === null) { // shouldn’t happen, but don’t crash return \Psalm\Type::getMixed(); } if ($array_type->by_ref) { $array_access_type->by_ref = \true; } if ($in_assignment) { $array_type->bustCache(); } return $array_access_type; } private static function checkLiteralIntArrayOffset(\Psalm\Type\Union $offset_type, \Psalm\Type\Union $expected_offset_type, ?string $array_var_id, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch $stmt, \Psalm\Context $context, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer) : void { if ($context->inside_isset || $context->inside_unset) { return; } if ($offset_type->hasLiteralInt()) { $found_match = \false; foreach ($offset_type->getAtomicTypes() as $offset_type_part) { if ($array_var_id && $offset_type_part instanceof \Psalm\Type\Atomic\TLiteralInt && isset($context->vars_in_scope[$array_var_id . '[' . $offset_type_part->value . ']']) && !$context->vars_in_scope[$array_var_id . '[' . $offset_type_part->value . ']']->possibly_undefined) { $found_match = \true; break; } } if (!$found_match) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedIntArrayOffset('Possibly undefined array offset \'' . $offset_type->getId() . '\' ' . 'is risky given expected type \'' . $expected_offset_type->getId() . '\'.' . ' Consider using isset beforehand.', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } private static function checkLiteralStringArrayOffset(\Psalm\Type\Union $offset_type, \Psalm\Type\Union $expected_offset_type, ?string $array_var_id, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch $stmt, \Psalm\Context $context, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer) : void { if ($context->inside_isset || $context->inside_unset) { return; } if ($offset_type->hasLiteralString() && !$expected_offset_type->hasLiteralClassString()) { $found_match = \false; foreach ($offset_type->getAtomicTypes() as $offset_type_part) { if ($array_var_id && $offset_type_part instanceof \Psalm\Type\Atomic\TLiteralString && isset($context->vars_in_scope[$array_var_id . '[\'' . $offset_type_part->value . '\']']) && !$context->vars_in_scope[$array_var_id . '[\'' . $offset_type_part->value . '\']']->possibly_undefined) { $found_match = \true; break; } } if (!$found_match) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyUndefinedStringArrayOffset('Possibly undefined array offset \'' . $offset_type->getId() . '\' ' . 'is risky given expected type \'' . $expected_offset_type->getId() . '\'.' . ' Consider using isset beforehand.', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } public static function replaceOffsetTypeWithInts(\Psalm\Type\Union $offset_type) : \Psalm\Type\Union { $offset_types = $offset_type->getAtomicTypes(); $cloned = \false; foreach ($offset_types as $key => $offset_type_part) { if ($offset_type_part instanceof \Psalm\Type\Atomic\TLiteralString) { if (\preg_match('/^(0|[1-9][0-9]*)$/', $offset_type_part->value)) { if (!$cloned) { $offset_type = clone $offset_type; $cloned = \true; } $offset_type->addType(new \Psalm\Type\Atomic\TLiteralInt((int) $offset_type_part->value)); $offset_type->removeType($key); } } elseif ($offset_type_part instanceof \Psalm\Type\Atomic\TBool) { if (!$cloned) { $offset_type = clone $offset_type; $cloned = \true; } if ($offset_type_part instanceof \Psalm\Type\Atomic\TFalse) { if (!$offset_type->ignore_falsable_issues) { $offset_type->addType(new \Psalm\Type\Atomic\TLiteralInt(0)); $offset_type->removeType($key); } } elseif ($offset_type_part instanceof \Psalm\Type\Atomic\TTrue) { $offset_type->addType(new \Psalm\Type\Atomic\TLiteralInt(1)); $offset_type->removeType($key); } else { $offset_type->addType(new \Psalm\Type\Atomic\TLiteralInt(0)); $offset_type->addType(new \Psalm\Type\Atomic\TLiteralInt(1)); $offset_type->removeType($key); } } } return $offset_type; } } getCodebase(); if ($stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $first_part_lc = \strtolower($stmt->class->parts[0]); if ($first_part_lc === 'self' || $first_part_lc === 'static') { if (!$context->self) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NonStaticSelfCall('Cannot use ' . $first_part_lc . ' outside class context', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } return \true; } $fq_class_name = $context->self; } elseif ($first_part_lc === 'parent') { $fq_class_name = $statements_analyzer->getParentFQCLN(); if ($fq_class_name === null) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParentNotFound('Cannot check property fetch on parent as this class does not extend another', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } return \true; } } else { $fq_class_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($stmt->class, $statements_analyzer->getAliases()); if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { if ((!$context->inside_class_exists || $stmt->name->name !== 'class') && !isset($context->phantom_classes[\strtolower($fq_class_name)])) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_class_name, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->class), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues(), \false, \true) === \false) { return \true; } } } } $moved_class = \false; if ($codebase->alter_code && !\in_array($stmt->class->parts[0], ['parent', 'static'])) { $moved_class = $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $stmt->class, $fq_class_name, $context->calling_method_id, \false, $stmt->class->parts[0] === 'self'); } if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $stmt->name->name === 'class') { if ($codebase->classlikes->classExists($fq_class_name)) { $fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name); $const_class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $fq_class_name = $const_class_storage->name; if ($const_class_storage->deprecated && $fq_class_name !== $context->self) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedClass('Class ' . $fq_class_name . ' is deprecated', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $fq_class_name), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if ($first_part_lc === 'static') { $static_named_object = new \Psalm\Type\Atomic\TNamedObject($fq_class_name); $static_named_object->was_static = \true; $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClassString($fq_class_name, $static_named_object)])); } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getLiteralClassString($fq_class_name)); } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->class, $fq_class_name); } return \true; } // if we're ignoring that the class doesn't exist, exit anyway if (!$codebase->classlikes->classOrInterfaceExists($fq_class_name)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); return \true; } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->class, $fq_class_name); } if (!$stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { return \true; } $const_id = $fq_class_name . '::' . $stmt->name; if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->name, $const_id); } if ($fq_class_name === $context->self || $statements_analyzer->getSource()->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer && $fq_class_name === $statements_analyzer->getSource()->getFQCLN()) { $class_visibility = \ReflectionProperty::IS_PRIVATE; } elseif ($context->self && ($codebase->classlikes->classExtends($context->self, $fq_class_name) || $codebase->classlikes->classExtends($fq_class_name, $context->self))) { $class_visibility = \ReflectionProperty::IS_PROTECTED; } else { $class_visibility = \ReflectionProperty::IS_PUBLIC; } try { $class_constant_type = $codebase->classlikes->getClassConstantType($fq_class_name, $stmt->name->name, $class_visibility, $statements_analyzer); } catch (\InvalidArgumentException $_) { return \true; } catch (\Psalm\Exception\CircularReferenceException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\CircularReference('Constant ' . $const_id . ' contains a circular reference', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } return \true; } if (!$class_constant_type) { if ($fq_class_name !== $context->self) { $class_constant_type = $codebase->classlikes->getClassConstantType($fq_class_name, $stmt->name->name, \ReflectionProperty::IS_PRIVATE, $statements_analyzer); } if ($class_constant_type) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleClassConstant('Constant ' . $const_id . ' is not visible in this context', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($context->check_consts) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedConstant('Constant ' . $const_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } return \true; } if ($context->calling_method_id) { $codebase->file_reference_provider->addMethodReferenceToClassMember($context->calling_method_id, \strtolower($fq_class_name) . '::' . $stmt->name->name); } $declaring_const_id = \strtolower($fq_class_name) . '::' . $stmt->name->name; if ($codebase->alter_code && !$moved_class) { foreach ($codebase->class_constant_transforms as $original_pattern => $transformation) { if ($declaring_const_id === $original_pattern) { [$new_fq_class_name, $new_const_name] = \explode('::', $transformation); $file_manipulations = []; if (\strtolower($new_fq_class_name) !== \strtolower($fq_class_name)) { $file_manipulations[] = new \Psalm\FileManipulation((int) $stmt->class->getAttribute('startFilePos'), (int) $stmt->class->getAttribute('endFilePos') + 1, \Psalm\Type::getStringFromFQCLN($new_fq_class_name, $statements_analyzer->getNamespace(), $statements_analyzer->getAliasedClassesFlipped(), null)); } $file_manipulations[] = new \Psalm\FileManipulation((int) $stmt->name->getAttribute('startFilePos'), (int) $stmt->name->getAttribute('endFilePos') + 1, $new_const_name); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } } $const_class_storage = $codebase->classlike_storage_provider->get($fq_class_name); if ($context->self && !$context->collect_initializations && !$context->collect_mutations && $const_class_storage->internal && !\Psalm\Internal\Analyzer\NamespaceAnalyzer::isWithin($context->self, $const_class_storage->internal)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InternalClass($fq_class_name . ' is internal to ' . $const_class_storage->internal . ' but called from ' . $context->self, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $fq_class_name), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($const_class_storage->deprecated && $fq_class_name !== $context->self) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedClass('Class ' . $fq_class_name . ' is deprecated', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $fq_class_name), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($const_class_storage->constants[$stmt->name->name]->deprecated) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedConstant('Constant ' . $const_id . ' is deprecated', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($first_part_lc !== 'static' || $const_class_storage->final) { $stmt_type = clone $class_constant_type; $statements_analyzer->node_data->setType($stmt, $stmt_type); $context->vars_in_scope[$const_id] = $stmt_type; } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } return \true; } if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $stmt->name->name === 'class') { $was_inside_use = $context->inside_use; $context->inside_use = \true; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context); $context->inside_use = $was_inside_use; $lhs_type = $statements_analyzer->node_data->getType($stmt->class); $class_string_types = []; $has_mixed_or_object = \false; if ($lhs_type) { foreach ($lhs_type->getAtomicTypes() as $lhs_atomic_type) { if ($lhs_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $class_string_types[] = new \Psalm\Type\Atomic\TClassString($lhs_atomic_type->value, clone $lhs_atomic_type); } elseif ($lhs_atomic_type instanceof \Psalm\Type\Atomic\TObject || $lhs_atomic_type instanceof \Psalm\Type\Atomic\TMixed) { $has_mixed_or_object = \true; } } } if ($has_mixed_or_object) { $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TClassString()])); } elseif ($class_string_types) { $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union($class_string_types)); } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); } return \true; } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getMixed()); $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; return \true; } public static function analyzeClassConstAssignment(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst $stmt, \Psalm\Context $context) : void { foreach ($stmt->consts as $const) { \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $const->value, $context); } } } >> */ public static function scrapeAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $conditional, ?string $this_class_name, \Psalm\FileSource $source, ?\Psalm\Codebase $codebase = null, bool $inside_negation = \false, bool $cache = \true, bool $inside_conditional = \true) : array { $if_types = []; if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_) { $instanceof_types = self::getInstanceOfTypes($conditional, $this_class_name, $source); if ($instanceof_types) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->expr, $this_class_name, $source); if ($var_name) { $if_types[$var_name] = [$instanceof_types]; $var_type = $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer ? $source->node_data->getType($conditional->expr) : null; foreach ($instanceof_types as $instanceof_type) { if ($instanceof_type[0] === '=') { $instanceof_type = \substr($instanceof_type, 1); } if ($codebase && $var_type && $inside_negation && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { if ($codebase->interfaceExists($instanceof_type)) { continue; } $instanceof_type = \Psalm\Type::parseString($instanceof_type, null, $source->getTemplateTypeMap() ?: []); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $instanceof_type, $var_type)) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType($var_type->getId() . ' does not contain ' . $instanceof_type->getId(), new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' ' . $instanceof_type->getId()), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition($var_type->getId() . ' cannot be identical to ' . $instanceof_type->getId(), new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' ' . $instanceof_type->getId()), $source->getSuppressedIssues())) { // fall through } } } } } } } return $if_types; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->var, $this_class_name, $source); $candidate_if_types = $inside_conditional ? self::scrapeAssertions($conditional->expr, $this_class_name, $source, $codebase, $inside_negation, $cache, $inside_conditional) : []; if ($var_name) { if ($candidate_if_types) { $if_types[$var_name] = [['>' . \json_encode($candidate_if_types)]]; } else { $if_types[$var_name] = [['!falsy']]; } } return $if_types; } $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional, $this_class_name, $source); if ($var_name) { $if_types[$var_name] = [['!falsy']]; if (!$conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall && !$conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall) { return $if_types; } } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot) { $expr_assertions = null; if ($cache && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $expr_assertions = $source->node_data->getAssertions($conditional->expr); } if ($expr_assertions === null) { $expr_assertions = self::scrapeAssertions($conditional->expr, $this_class_name, $source, $codebase, !$inside_negation, $cache, $inside_conditional); if ($cache && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $source->node_data->setAssertions($conditional->expr, $expr_assertions); } } if (\count($expr_assertions) !== 1) { return []; } $if_types = \Psalm\Type\Algebra::negateTypes($expr_assertions); return $if_types; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal) { $if_types = self::scrapeEqualityAssertions($conditional, $this_class_name, $source, $codebase, \false, $cache, $inside_conditional); return $if_types; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotEqual) { $if_types = self::scrapeInequalityAssertions($conditional, $this_class_name, $source, $codebase, \false, $cache, $inside_conditional); return $if_types; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual) { $min_count = null; $count_equality_position = self::hasNonEmptyCountEqualityCheck($conditional, $min_count); $min_comparison = null; $positive_number_position = self::hasPositiveNumberCheck($conditional, $min_comparison); $max_count = null; $count_inequality_position = self::hasLessThanCountEqualityCheck($conditional, $max_count); if ($count_equality_position) { if ($count_equality_position === self::ASSIGNMENT_TO_RIGHT) { $counted_expr = $conditional->left; } else { throw new \UnexpectedValueException('$count_equality_position value'); } /** @var PhpParser\Node\Expr\FuncCall $counted_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($counted_expr->args[0]->value, $this_class_name, $source); if ($var_name) { if (self::hasReconcilableNonEmptyCountEqualityCheck($conditional)) { $if_types[$var_name] = [['non-empty-countable']]; } else { if ($min_count) { $if_types[$var_name] = [['=has-at-least-' . $min_count]]; } else { $if_types[$var_name] = [['=non-empty-countable']]; } } } return $if_types; } if ($count_inequality_position) { if ($count_inequality_position === self::ASSIGNMENT_TO_LEFT) { $count_expr = $conditional->right; } else { throw new \UnexpectedValueException('$count_inequality_position value'); } /** @var PhpParser\Node\Expr\FuncCall $count_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($count_expr->args[0]->value, $this_class_name, $source); if ($var_name) { if ($max_count) { $if_types[$var_name] = [['!has-at-least-' . ($max_count + 1)]]; } else { $if_types[$var_name] = [['!non-empty-countable']]; } } return $if_types; } if ($positive_number_position) { if ($positive_number_position === self::ASSIGNMENT_TO_RIGHT) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->left, $this_class_name, $source); $value_node = $conditional->left; } else { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->right, $this_class_name, $source); $value_node = $conditional->right; } if ($codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($var_type = $source->node_data->getType($value_node)) && $var_type->isSingle() && $var_type->hasBool() && $min_comparison > 1) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($var_type . ' cannot be greater than ' . $min_comparison, new \Psalm\CodeLocation($source, $conditional), null), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType($var_type . ' cannot be greater than ' . $min_comparison, new \Psalm\CodeLocation($source, $conditional), null), $source->getSuppressedIssues())) { // fall through } } } if ($var_name) { $if_types[$var_name] = [[($min_comparison === 1 ? '' : '=') . 'positive-numeric']]; } return $if_types; } return []; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual) { $min_count = null; $count_equality_position = self::hasNonEmptyCountEqualityCheck($conditional, $min_count); $typed_value_position = self::hasTypedValueComparison($conditional, $source); $max_count = null; $count_inequality_position = self::hasLessThanCountEqualityCheck($conditional, $max_count); if ($count_equality_position) { if ($count_equality_position === self::ASSIGNMENT_TO_LEFT) { $count_expr = $conditional->right; } else { throw new \UnexpectedValueException('$count_equality_position value'); } /** @var PhpParser\Node\Expr\FuncCall $count_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($count_expr->args[0]->value, $this_class_name, $source); if ($var_name) { if ($min_count) { $if_types[$var_name] = [['=has-at-least-' . $min_count]]; } else { $if_types[$var_name] = [['=non-empty-countable']]; } } return $if_types; } if ($count_inequality_position) { if ($count_inequality_position === self::ASSIGNMENT_TO_RIGHT) { $count_expr = $conditional->left; } else { throw new \UnexpectedValueException('$count_inequality_position value'); } /** @var PhpParser\Node\Expr\FuncCall $count_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($count_expr->args[0]->value, $this_class_name, $source); if ($var_name) { if ($max_count) { $if_types[$var_name] = [['!has-at-least-' . ($max_count + 1)]]; } else { $if_types[$var_name] = [['!non-empty-countable']]; } } return $if_types; } if ($typed_value_position) { if ($typed_value_position === self::ASSIGNMENT_TO_RIGHT) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->left, $this_class_name, $source); $expr = $conditional->right; } elseif ($typed_value_position === self::ASSIGNMENT_TO_LEFT) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->right, $this_class_name, $source); $expr = $conditional->left; } else { throw new \UnexpectedValueException('$typed_value_position value'); } $expr_type = $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer ? $source->node_data->getType($expr) : null; if ($var_name && $expr_type && $expr_type->isSingleIntLiteral() && $expr_type->getSingleIntLiteral()->value === 0) { $if_types[$var_name] = [['=isset']]; } return $if_types; } return []; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { $if_types = self::processFunctionCall($conditional, $this_class_name, $source, $codebase, \false); return $if_types; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall) { $custom_assertions = self::processCustomAssertion($conditional, $this_class_name, $source, \false); if ($custom_assertions) { return $custom_assertions; } return $if_types; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Empty_) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->expr, $this_class_name, $source); if ($var_name) { $if_types[$var_name] = [['empty']]; } return $if_types; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Isset_) { foreach ($conditional->vars as $isset_var) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($isset_var, $this_class_name, $source); if ($var_name) { $if_types[$var_name] = [['isset']]; } else { // look for any variables we *can* use for an isset assertion $array_root = $isset_var; while ($array_root instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch && !$var_name) { $array_root = $array_root->var; $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($array_root, $this_class_name, $source); } if ($var_name) { $if_types[$var_name] = [['=isset']]; } } } return $if_types; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Coalesce) { return self::scrapeAssertions(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Isset_([$conditional->left]), $conditional->left, $conditional->right, $conditional->getAttributes()), $this_class_name, $source, $codebase, $inside_negation, \false, $inside_conditional); } return []; } /** * @param PhpParser\Node\Expr\BinaryOp\Identical|PhpParser\Node\Expr\BinaryOp\Equal $conditional * * @return array>> */ private static function scrapeEqualityAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional, ?string $this_class_name, \Psalm\FileSource $source, ?\Psalm\Codebase $codebase = null, bool $inside_negation = \false, bool $cache = \true, bool $inside_conditional = \true) : array { $if_types = []; $null_position = self::hasNullVariable($conditional, $source); $false_position = self::hasFalseVariable($conditional); $true_position = self::hasTrueVariable($conditional); $empty_array_position = self::hasEmptyArrayVariable($conditional); $gettype_position = self::hasGetTypeCheck($conditional); $get_debug_type_position = self::hasGetDebugTypeCheck($conditional); $min_count = null; $count_equality_position = self::hasNonEmptyCountEqualityCheck($conditional, $min_count); if ($null_position !== null) { if ($null_position === self::ASSIGNMENT_TO_RIGHT) { $base_conditional = $conditional->left; } elseif ($null_position === self::ASSIGNMENT_TO_LEFT) { $base_conditional = $conditional->right; } else { throw new \UnexpectedValueException('$null_position value'); } $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($base_conditional, $this_class_name, $source); if ($var_name && $base_conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { $var_name = '=' . $var_name; } if ($var_name) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { $if_types[$var_name] = [['null']]; } else { $if_types[$var_name] = [['falsy']]; } } if ($codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional)) && $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { $null_type = \Psalm\Type::getNull(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $var_type, $null_type) && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $null_type, $var_type)) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($var_type . ' does not contain null', new \Psalm\CodeLocation($source, $conditional), $var_type . ' null'), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainNull($var_type . ' does not contain null', new \Psalm\CodeLocation($source, $conditional), $var_type->getId()), $source->getSuppressedIssues())) { // fall through } } } } return $if_types; } if ($true_position) { if ($true_position === self::ASSIGNMENT_TO_RIGHT) { $base_conditional = $conditional->left; } elseif ($true_position === self::ASSIGNMENT_TO_LEFT) { $base_conditional = $conditional->right; } else { throw new \UnexpectedValueException('Unrecognised position'); } if ($base_conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { $if_types = self::processFunctionCall($base_conditional, $this_class_name, $source, $codebase, \false); } else { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($base_conditional, $this_class_name, $source); if ($var_name) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { $if_types[$var_name] = [['true']]; } else { $if_types[$var_name] = [['!falsy']]; } } else { $base_assertions = null; if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && $cache) { $base_assertions = $source->node_data->getAssertions($base_conditional); } if ($base_assertions === null) { $base_assertions = self::scrapeAssertions($base_conditional, $this_class_name, $source, $codebase, $inside_negation, $cache); if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && $cache) { $source->node_data->setAssertions($base_conditional, $base_assertions); } } $if_types = $base_assertions; } } if ($codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional))) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { $config = $source->getCodebase()->config; if ($config->strict_binary_operands && $var_type->isSingle() && $var_type->hasBool() && !$var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantIdentityWithTrue('The "=== true" part of this comparison is redundant', new \Psalm\CodeLocation($source, $conditional)), $source->getSuppressedIssues())) { // fall through } } $true_type = \Psalm\Type::getTrue(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $true_type, $var_type)) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($var_type . ' does not contain true', new \Psalm\CodeLocation($source, $conditional), $var_type . ' true'), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType($var_type . ' does not contain true', new \Psalm\CodeLocation($source, $conditional), $var_type . ' true'), $source->getSuppressedIssues())) { // fall through } } } } } return $if_types; } if ($false_position) { if ($false_position === self::ASSIGNMENT_TO_RIGHT) { $base_conditional = $conditional->left; } elseif ($false_position === self::ASSIGNMENT_TO_LEFT) { $base_conditional = $conditional->right; } else { throw new \UnexpectedValueException('$false_position value'); } if ($base_conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { $if_types = self::processFunctionCall($base_conditional, $this_class_name, $source, $codebase, \true); } else { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($base_conditional, $this_class_name, $source); if ($var_name) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { $if_types[$var_name] = [['false']]; } else { $if_types[$var_name] = [['falsy']]; } } else { $base_assertions = null; if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && $cache) { $base_assertions = $source->node_data->getAssertions($base_conditional); } if ($base_assertions === null) { $base_assertions = self::scrapeAssertions($base_conditional, $this_class_name, $source, $codebase, $inside_negation, $cache, $inside_conditional); if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && $cache) { $source->node_data->setAssertions($base_conditional, $base_assertions); } } $notif_types = $base_assertions; if (\count($notif_types) === 1) { $if_types = \Psalm\Type\Algebra::negateTypes($notif_types); } } } if ($codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional))) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { $false_type = \Psalm\Type::getFalse(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $false_type, $var_type)) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($var_type . ' does not contain false', new \Psalm\CodeLocation($source, $conditional), $var_type . ' false'), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType($var_type . ' does not contain false', new \Psalm\CodeLocation($source, $conditional), $var_type . ' false'), $source->getSuppressedIssues())) { // fall through } } } } } return $if_types; } if ($empty_array_position !== null) { if ($empty_array_position === self::ASSIGNMENT_TO_RIGHT) { $base_conditional = $conditional->left; } elseif ($empty_array_position === self::ASSIGNMENT_TO_LEFT) { $base_conditional = $conditional->right; } else { throw new \UnexpectedValueException('$empty_array_position value'); } $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($base_conditional, $this_class_name, $source); if ($var_name) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { $if_types[$var_name] = [['!non-empty-countable']]; } else { $if_types[$var_name] = [['falsy']]; } } if ($codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional)) && $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { $empty_array_type = \Psalm\Type::getEmptyArray(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $empty_array_type, $var_type)) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($var_type . ' does not contain an empty array', new \Psalm\CodeLocation($source, $conditional), null), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType($var_type . ' does not contain empty array', new \Psalm\CodeLocation($source, $conditional), null), $source->getSuppressedIssues())) { // fall through } } } } return $if_types; } if ($gettype_position) { if ($gettype_position === self::ASSIGNMENT_TO_RIGHT) { $string_expr = $conditional->left; $gettype_expr = $conditional->right; } elseif ($gettype_position === self::ASSIGNMENT_TO_LEFT) { $string_expr = $conditional->right; $gettype_expr = $conditional->left; } else { throw new \UnexpectedValueException('$gettype_position value'); } /** @var PhpParser\Node\Expr\FuncCall $gettype_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($gettype_expr->args[0]->value, $this_class_name, $source); /** @var PhpParser\Node\Scalar\String_ $string_expr */ $var_type = $string_expr->value; if (!isset(\Psalm\Internal\Analyzer\ClassLikeAnalyzer::GETTYPE_TYPES[$var_type])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnevaluatedCode('gettype cannot return this value', new \Psalm\CodeLocation($source, $string_expr)))) { // fall through } } else { if ($var_name && $var_type) { $if_types[$var_name] = [[$var_type]]; } } return $if_types; } if ($get_debug_type_position) { if ($get_debug_type_position === self::ASSIGNMENT_TO_RIGHT) { $whichclass_expr = $conditional->left; $get_debug_type_expr = $conditional->right; } elseif ($get_debug_type_position === self::ASSIGNMENT_TO_LEFT) { $whichclass_expr = $conditional->right; $get_debug_type_expr = $conditional->left; } else { throw new \UnexpectedValueException('$gettype_position value'); } /** @var PhpParser\Node\Expr\FuncCall $get_debug_type_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($get_debug_type_expr->args[0]->value, $this_class_name, $source); if ($whichclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $var_type = $whichclass_expr->value; } elseif ($whichclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $whichclass_expr->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $var_type = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($whichclass_expr->class, $source->getAliases()); } else { throw new \UnexpectedValueException('Shouldn’t get here'); } if ($var_name && $var_type) { if ($var_type === 'class@anonymous') { $if_types[$var_name] = [['=object']]; } elseif ($var_type === 'resource (closed)') { $if_types[$var_name] = [['closed-resource']]; } elseif (\substr($var_type, 0, 10) === 'resource (') { $if_types[$var_name] = [['=resource']]; } else { $if_types[$var_name] = [[$var_type]]; } } return $if_types; } if ($count_equality_position) { if ($count_equality_position === self::ASSIGNMENT_TO_RIGHT) { $count_expr = $conditional->left; } elseif ($count_equality_position === self::ASSIGNMENT_TO_LEFT) { $count_expr = $conditional->right; } else { throw new \UnexpectedValueException('$count_equality_position value'); } /** @var PhpParser\Node\Expr\FuncCall $count_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($count_expr->args[0]->value, $this_class_name, $source); if ($var_name) { if ($min_count) { $if_types[$var_name] = [['=has-at-least-' . $min_count]]; } else { $if_types[$var_name] = [['=non-empty-countable']]; } } return $if_types; } if (!$source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return []; } $getclass_position = self::hasGetClassCheck($conditional, $source); if ($getclass_position) { if ($getclass_position === self::ASSIGNMENT_TO_RIGHT) { $whichclass_expr = $conditional->left; $getclass_expr = $conditional->right; } elseif ($getclass_position === self::ASSIGNMENT_TO_LEFT) { $whichclass_expr = $conditional->right; $getclass_expr = $conditional->left; } else { throw new \UnexpectedValueException('$getclass_position value'); } if ($getclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && isset($getclass_expr->args[0])) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($getclass_expr->args[0]->value, $this_class_name, $source); } else { $var_name = '$this'; } if ($whichclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $whichclass_expr->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $var_type = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($whichclass_expr->class, $source->getAliases()); if ($var_type === 'self' || $var_type === 'static') { $var_type = $this_class_name; } elseif ($var_type === 'parent') { $var_type = null; } if ($var_type) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($source, $var_type, new \Psalm\CodeLocation($source, $whichclass_expr), null, null, $source->getSuppressedIssues(), \true) === \false) { return $if_types; } } if ($var_name && $var_type) { $if_types[$var_name] = [['=getclass-' . $var_type]]; } } else { $type = $source->node_data->getType($whichclass_expr); if ($type && $var_name) { foreach ($type->getAtomicTypes() as $type_part) { if ($type_part instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $if_types[$var_name] = [['=' . $type_part->param_name]]; } } } } return $if_types; } $typed_value_position = self::hasTypedValueComparison($conditional, $source); if ($typed_value_position) { if ($typed_value_position === self::ASSIGNMENT_TO_RIGHT) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->left, $this_class_name, $source); $other_type = $source->node_data->getType($conditional->left); $var_type = $source->node_data->getType($conditional->right); } elseif ($typed_value_position === self::ASSIGNMENT_TO_LEFT) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->right, $this_class_name, $source); $var_type = $source->node_data->getType($conditional->left); $other_type = $source->node_data->getType($conditional->right); } else { throw new \UnexpectedValueException('$typed_value_position value'); } if ($var_name && $var_type) { $identical = $conditional instanceof \_HumbugBoxd02f763d3c56\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()); if ($identical) { $if_types[$var_name] = [['=' . $var_type->getAssertionString()]]; } else { $if_types[$var_name] = [['~' . $var_type->getAssertionString()]]; } } if ($codebase && $other_type && $var_type && ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $other_type->isString() && $var_type->isString())) { $parent_source = $source->getSource(); if ($parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer && ($var_type->isSingleStringLiteral() && $var_type->getSingleStringLiteral()->value === $this_class_name || $other_type->isSingleStringLiteral() && $other_type->getSingleStringLiteral()->value === $this_class_name)) { // do nothing } elseif (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $other_type, $var_type)) { if ($var_type->from_docblock || $other_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($var_type->getId() . ' does not contain ' . $other_type->getId(), new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' ' . $other_type->getId()), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType($var_type->getId() . ' cannot be identical to ' . $other_type->getId(), new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' ' . $other_type->getId()), $source->getSuppressedIssues())) { // fall through } } } } return $if_types; } $var_type = $source->node_data->getType($conditional->left); $other_type = $source->node_data->getType($conditional->right); if ($codebase && $var_type && $other_type && $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $var_type, $other_type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType($var_type->getId() . ' cannot be identical to ' . $other_type->getId(), new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' ' . $other_type->getId()), $source->getSuppressedIssues())) { // fall through } } } return []; } /** * @param PhpParser\Node\Expr\BinaryOp\NotIdentical|PhpParser\Node\Expr\BinaryOp\NotEqual $conditional * * @return array>> */ private static function scrapeInequalityAssertions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional, ?string $this_class_name, \Psalm\FileSource $source, ?\Psalm\Codebase $codebase = null, bool $inside_negation = \false, bool $cache = \true, bool $inside_conditional = \true) : array { $if_types = []; $null_position = self::hasNullVariable($conditional, $source); $false_position = self::hasFalseVariable($conditional); $true_position = self::hasTrueVariable($conditional); $empty_array_position = self::hasEmptyArrayVariable($conditional); $gettype_position = self::hasGetTypeCheck($conditional); $get_debug_type_position = self::hasGetDebugTypeCheck($conditional); $count = null; $count_inequality_position = self::hasNotCountEqualityCheck($conditional, $count); if ($null_position !== null) { if ($null_position === self::ASSIGNMENT_TO_RIGHT) { $base_conditional = $conditional->left; } elseif ($null_position === self::ASSIGNMENT_TO_LEFT) { $base_conditional = $conditional->right; } else { throw new \UnexpectedValueException('Bad null variable position'); } $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($base_conditional, $this_class_name, $source); if ($var_name) { if ($base_conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { $var_name = '=' . $var_name; } if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) { $if_types[$var_name] = [['!null']]; } else { $if_types[$var_name] = [['!falsy']]; } } if ($codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional))) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) { $null_type = \Psalm\Type::getNull(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $var_type, $null_type) && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $null_type, $var_type)) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType('Docblock-defined type ' . $var_type . ' can never contain null', new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' null'), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition($var_type . ' can never contain null', new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' null'), $source->getSuppressedIssues())) { // fall through } } } } } return $if_types; } if ($false_position) { if ($false_position === self::ASSIGNMENT_TO_RIGHT) { $base_conditional = $conditional->left; } elseif ($false_position === self::ASSIGNMENT_TO_LEFT) { $base_conditional = $conditional->right; } else { throw new \UnexpectedValueException('Bad false variable position'); } $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($base_conditional, $this_class_name, $source); if ($var_name) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) { $if_types[$var_name] = [['!false']]; } else { $if_types[$var_name] = [['!falsy']]; } } else { $base_assertions = null; if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && $cache) { $base_assertions = $source->node_data->getAssertions($base_conditional); } if ($base_assertions === null) { $base_assertions = self::scrapeAssertions($base_conditional, $this_class_name, $source, $codebase, $inside_negation, $cache, $inside_conditional); if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && $cache) { $source->node_data->setAssertions($base_conditional, $base_assertions); } } $notif_types = $base_assertions; if (\count($notif_types) === 1) { $if_types = \Psalm\Type\Algebra::negateTypes($notif_types); } } if ($codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional))) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) { $false_type = \Psalm\Type::getFalse(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $var_type, $false_type) && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $false_type, $var_type)) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType('Docblock-defined type ' . $var_type . ' can never contain false', new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' false'), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition($var_type . ' can never contain false', new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' false'), $source->getSuppressedIssues())) { // fall through } } } } } return $if_types; } if ($true_position) { if ($true_position === self::ASSIGNMENT_TO_RIGHT) { $base_conditional = $conditional->left; } elseif ($true_position === self::ASSIGNMENT_TO_LEFT) { $base_conditional = $conditional->right; } else { throw new \UnexpectedValueException('Bad null variable position'); } if ($base_conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { $if_types = self::processFunctionCall($base_conditional, $this_class_name, $source, $codebase, \true); } else { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($base_conditional, $this_class_name, $source); if ($var_name) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) { $if_types[$var_name] = [['!true']]; } else { $if_types[$var_name] = [['falsy']]; } } else { $base_assertions = null; if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && $cache) { $base_assertions = $source->node_data->getAssertions($base_conditional); } if ($base_assertions === null) { $base_assertions = self::scrapeAssertions($base_conditional, $this_class_name, $source, $codebase, $inside_negation, $cache, $inside_conditional); if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && $cache) { $source->node_data->setAssertions($base_conditional, $base_assertions); } } $notif_types = $base_assertions; if (\count($notif_types) === 1) { $if_types = \Psalm\Type\Algebra::negateTypes($notif_types); } } } if ($codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional))) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) { $true_type = \Psalm\Type::getTrue(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $var_type, $true_type) && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $true_type, $var_type)) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType('Docblock-defined type ' . $var_type . ' can never contain true', new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' true'), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition($var_type . ' can never contain ' . $true_type, new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' true'), $source->getSuppressedIssues())) { // fall through } } } } } return $if_types; } if ($count_inequality_position) { if ($count_inequality_position === self::ASSIGNMENT_TO_RIGHT) { $count_expr = $conditional->left; } elseif ($count_inequality_position === self::ASSIGNMENT_TO_LEFT) { $count_expr = $conditional->right; } else { throw new \UnexpectedValueException('$count_equality_position value'); } /** @var PhpParser\Node\Expr\FuncCall $count_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($count_expr->args[0]->value, $this_class_name, $source); if ($var_name) { if ($count) { $if_types[$var_name] = [['!has-exactly-' . $count]]; } else { $if_types[$var_name] = [['non-empty-countable']]; } } return $if_types; } if ($empty_array_position !== null) { if ($empty_array_position === self::ASSIGNMENT_TO_RIGHT) { $base_conditional = $conditional->left; } elseif ($empty_array_position === self::ASSIGNMENT_TO_LEFT) { $base_conditional = $conditional->right; } else { throw new \UnexpectedValueException('Bad empty array variable position'); } $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($base_conditional, $this_class_name, $source); if ($var_name) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) { $if_types[$var_name] = [['non-empty-countable']]; } else { $if_types[$var_name] = [['!falsy']]; } } if ($codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($var_type = $source->node_data->getType($base_conditional))) { if ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) { $empty_array_type = \Psalm\Type::getEmptyArray(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $var_type, $empty_array_type) && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $empty_array_type, $var_type)) { if ($var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType('Docblock-defined type ' . $var_type->getId() . ' can never contain null', new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' null'), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition($var_type->getId() . ' can never contain null', new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' null'), $source->getSuppressedIssues())) { // fall through } } } } } return $if_types; } if ($gettype_position) { if ($gettype_position === self::ASSIGNMENT_TO_RIGHT) { $whichclass_expr = $conditional->left; $gettype_expr = $conditional->right; } elseif ($gettype_position === self::ASSIGNMENT_TO_LEFT) { $whichclass_expr = $conditional->right; $gettype_expr = $conditional->left; } else { throw new \UnexpectedValueException('$gettype_position value'); } /** @var PhpParser\Node\Expr\FuncCall $gettype_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($gettype_expr->args[0]->value, $this_class_name, $source); if ($whichclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $var_type = $whichclass_expr->value; } elseif ($whichclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $whichclass_expr->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $var_type = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($whichclass_expr->class, $source->getAliases()); } else { throw new \UnexpectedValueException('Shouldn’t get here'); } if (!isset(\Psalm\Internal\Analyzer\ClassLikeAnalyzer::GETTYPE_TYPES[$var_type])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnevaluatedCode('gettype cannot return this value', new \Psalm\CodeLocation($source, $whichclass_expr)))) { // fall through } } else { if ($var_name && $var_type) { $if_types[$var_name] = [['!' . $var_type]]; } } return $if_types; } if ($get_debug_type_position) { if ($get_debug_type_position === self::ASSIGNMENT_TO_RIGHT) { $whichclass_expr = $conditional->left; $get_debug_type_expr = $conditional->right; } elseif ($get_debug_type_position === self::ASSIGNMENT_TO_LEFT) { $whichclass_expr = $conditional->right; $get_debug_type_expr = $conditional->left; } else { throw new \UnexpectedValueException('$gettype_position value'); } /** @var PhpParser\Node\Expr\FuncCall $get_debug_type_expr */ $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($get_debug_type_expr->args[0]->value, $this_class_name, $source); if ($whichclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $var_type = $whichclass_expr->value; } elseif ($whichclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $whichclass_expr->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $var_type = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($whichclass_expr->class, $source->getAliases()); } else { throw new \UnexpectedValueException('Shouldn’t get here'); } if ($var_name && $var_type) { if ($var_type === 'class@anonymous') { $if_types[$var_name] = [['!=object']]; } elseif ($var_type === 'resource (closed)') { $if_types[$var_name] = [['!closed-resource']]; } elseif (\substr($var_type, 0, 10) === 'resource (') { $if_types[$var_name] = [['!=resource']]; } else { $if_types[$var_name] = [['!' . $var_type]]; } } return $if_types; } if (!$source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return []; } $getclass_position = self::hasGetClassCheck($conditional, $source); $typed_value_position = self::hasTypedValueComparison($conditional, $source); if ($getclass_position) { if ($getclass_position === self::ASSIGNMENT_TO_RIGHT) { $whichclass_expr = $conditional->left; $getclass_expr = $conditional->right; } elseif ($getclass_position === self::ASSIGNMENT_TO_LEFT) { $whichclass_expr = $conditional->right; $getclass_expr = $conditional->left; } else { throw new \UnexpectedValueException('$getclass_position value'); } if ($getclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($getclass_expr->args[0]->value, $this_class_name, $source); } else { $var_name = '$this'; } if ($whichclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $var_type = $whichclass_expr->value; } elseif ($whichclass_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $whichclass_expr->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $var_type = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($whichclass_expr->class, $source->getAliases()); if ($var_type === 'self' || $var_type === 'static') { $var_type = $this_class_name; } elseif ($var_type === 'parent') { $var_type = null; } } else { $type = $source->node_data->getType($whichclass_expr); if ($type && $var_name) { foreach ($type->getAtomicTypes() as $type_part) { if ($type_part instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $if_types[$var_name] = [['!=' . $type_part->param_name]]; } } } return $if_types; } if ($var_type && \Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($source, $var_type, new \Psalm\CodeLocation($source, $whichclass_expr), null, null, $source->getSuppressedIssues(), \false) === \false) { // fall through } else { if ($var_name && $var_type) { $if_types[$var_name] = [['!=getclass-' . $var_type]]; } } return $if_types; } if ($typed_value_position) { if ($typed_value_position === self::ASSIGNMENT_TO_RIGHT) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->left, $this_class_name, $source); $other_type = $source->node_data->getType($conditional->left); $var_type = $source->node_data->getType($conditional->right); } elseif ($typed_value_position === self::ASSIGNMENT_TO_LEFT) { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($conditional->right, $this_class_name, $source); $var_type = $source->node_data->getType($conditional->left); $other_type = $source->node_data->getType($conditional->right); } else { throw new \UnexpectedValueException('$typed_value_position value'); } if ($var_type) { if ($var_name) { $not_identical = $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical || $other_type && ($var_type->isString() && $other_type->isString() || $var_type->isInt() && $other_type->isInt() || $var_type->isFloat() && $other_type->isFloat()); if ($not_identical) { $if_types[$var_name] = [['!=' . $var_type->getAssertionString()]]; } else { $if_types[$var_name] = [['!~' . $var_type->getAssertionString()]]; } } if ($codebase && $other_type && $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\NotIdentical) { $parent_source = $source->getSource(); if ($parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer && ($var_type->isSingleStringLiteral() && $var_type->getSingleStringLiteral()->value === $this_class_name || $other_type->isSingleStringLiteral() && $other_type->getSingleStringLiteral()->value === $this_class_name)) { // do nothing } elseif (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::canExpressionTypesBeIdentical($codebase, $other_type, $var_type)) { if ($var_type->from_docblock || $other_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($var_type . ' can never contain ' . $other_type->getId(), new \Psalm\CodeLocation($source, $conditional), $var_type . ' ' . $other_type), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition($var_type->getId() . ' can never contain ' . $other_type->getId(), new \Psalm\CodeLocation($source, $conditional), $var_type->getId() . ' ' . $other_type->getId()), $source->getSuppressedIssues())) { // fall through } } } } } return $if_types; } return []; } /** * @return array>> */ public static function processFunctionCall(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $expr, ?string $this_class_name, \Psalm\FileSource $source, ?\Psalm\Codebase $codebase = null, bool $negate = \false) : array { $prefix = $negate ? '!' : ''; $first_var_name = isset($expr->args[0]->value) ? \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($expr->args[0]->value, $this_class_name, $source) : null; $if_types = []; $first_var_type = isset($expr->args[0]->value) && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer ? $source->node_data->getType($expr->args[0]->value) : null; if (self::hasNullCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'null']]; } } elseif ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && self::hasIsACheck($expr, $source)) { if ($expr->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $expr->args[0]->value->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($expr->args[0]->value->name->name) === 'class' && $expr->args[0]->value->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \count($expr->args[0]->value->class->parts) === 1 && \strtolower($expr->args[0]->value->class->parts[0]) === 'static') { $first_var_name = '$this'; } if ($first_var_name) { $first_arg = $expr->args[0]->value; $second_arg = $expr->args[1]->value; $third_arg = isset($expr->args[2]->value) ? $expr->args[2]->value : null; if ($third_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { if (!\in_array(\strtolower($third_arg->name->parts[0]), ['true', 'false'])) { return $if_types; } $third_arg_value = \strtolower($third_arg->name->parts[0]); } else { $third_arg_value = $expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($expr->name->parts[0]) === 'is_subclass_of' ? 'true' : 'false'; } $is_a_prefix = $third_arg_value === 'true' ? 'isa-string-' : 'isa-'; if ($first_arg && ($first_arg_type = $source->node_data->getType($first_arg)) && $first_arg_type->isSingleStringLiteral() && $source->getSource()->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer && $first_arg_type->getSingleStringLiteral()->value === $this_class_name) { // do nothing } else { if ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $fq_class_name = $second_arg->value; if ($fq_class_name[0] === '\\') { $fq_class_name = \substr($fq_class_name, 1); } $if_types[$first_var_name] = [[$prefix . $is_a_prefix . $fq_class_name]]; } elseif ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $second_arg->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $second_arg->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($second_arg->name->name) === 'class') { $class_node = $second_arg->class; if ($class_node->parts === ['static']) { if ($this_class_name) { $if_types[$first_var_name] = [[$prefix . $is_a_prefix . $this_class_name . '&static']]; } } elseif ($class_node->parts === ['self']) { if ($this_class_name) { $if_types[$first_var_name] = [[$prefix . $is_a_prefix . $this_class_name]]; } } elseif ($class_node->parts === ['parent']) { // do nothing } else { $if_types[$first_var_name] = [[$prefix . $is_a_prefix . \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($class_node, $source->getAliases())]]; } } elseif (($second_arg_type = $source->node_data->getType($second_arg)) && $second_arg_type->hasString()) { $vals = []; foreach ($second_arg_type->getAtomicTypes() as $second_arg_atomic_type) { if ($second_arg_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $vals[] = [$prefix . $is_a_prefix . $second_arg_atomic_type->param_name]; } } if ($vals) { $if_types[$first_var_name] = $vals; } } } } } elseif (self::hasArrayCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'array']]; } elseif ($first_var_type && $codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { self::processIrreconcilableFunctionCall($first_var_type, \Psalm\Type::getArray(), $expr, $source, $codebase, $negate); } } elseif (self::hasBoolCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'bool']]; } elseif ($first_var_type && $codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { self::processIrreconcilableFunctionCall($first_var_type, \Psalm\Type::getBool(), $expr, $source, $codebase, $negate); } } elseif (self::hasStringCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'string']]; } elseif ($first_var_type && $codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { self::processIrreconcilableFunctionCall($first_var_type, \Psalm\Type::getString(), $expr, $source, $codebase, $negate); } } elseif (self::hasObjectCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'object']]; } elseif ($first_var_type && $codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { self::processIrreconcilableFunctionCall($first_var_type, \Psalm\Type::getObject(), $expr, $source, $codebase, $negate); } } elseif (self::hasNumericCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'numeric']]; } elseif ($first_var_type && $codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { self::processIrreconcilableFunctionCall($first_var_type, \Psalm\Type::getNumeric(), $expr, $source, $codebase, $negate); } } elseif (self::hasIntCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'int']]; } elseif ($first_var_type && $codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { self::processIrreconcilableFunctionCall($first_var_type, \Psalm\Type::getInt(), $expr, $source, $codebase, $negate); } } elseif (self::hasFloatCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'float']]; } elseif ($first_var_type && $codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { self::processIrreconcilableFunctionCall($first_var_type, \Psalm\Type::getFloat(), $expr, $source, $codebase, $negate); } } elseif (self::hasResourceCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'resource']]; } elseif ($first_var_type && $codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { self::processIrreconcilableFunctionCall($first_var_type, \Psalm\Type::getResource(), $expr, $source, $codebase, $negate); } } elseif (self::hasScalarCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'scalar']]; } elseif ($first_var_type && $codebase && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { self::processIrreconcilableFunctionCall($first_var_type, \Psalm\Type::getScalar(), $expr, $source, $codebase, $negate); } } elseif (self::hasCallableCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'callable']]; } elseif ($expr->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ && isset($expr->args[0]->value->items[0], $expr->args[0]->value->items[1]) && $expr->args[0]->value->items[1]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $first_var_name_in_array_argument = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($expr->args[0]->value->items[0]->value, $this_class_name, $source); if ($first_var_name_in_array_argument) { $if_types[$first_var_name_in_array_argument] = [[$prefix . 'hasmethod-' . $expr->args[0]->value->items[1]->value->value]]; } } } elseif (self::hasIterableCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'iterable']]; } } elseif (self::hasCountableCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'countable']]; } } elseif ($class_exists_check_type = self::hasClassExistsCheck($expr)) { if ($first_var_name) { if ($class_exists_check_type === 2 || $prefix) { $if_types[$first_var_name] = [[$prefix . 'class-string']]; } else { $if_types[$first_var_name] = [['=class-string']]; } } } elseif ($class_exists_check_type = self::hasTraitExistsCheck($expr)) { if ($first_var_name) { if ($class_exists_check_type === 2 || $prefix) { $if_types[$first_var_name] = [[$prefix . 'trait-string']]; } else { $if_types[$first_var_name] = [['=trait-string']]; } } } elseif (self::hasInterfaceExistsCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'interface-string']]; } } elseif (self::hasFunctionExistsCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'callable-string']]; } } elseif ($expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($expr->name->parts[0]) === 'method_exists' && isset($expr->args[1]) && $expr->args[1]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'hasmethod-' . $expr->args[1]->value->value]]; } } elseif (self::hasInArrayCheck($expr) && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { if ($first_var_name && ($second_arg_type = $source->node_data->getType($expr->args[1]->value))) { foreach ($second_arg_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TArray || $atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $atomic_type = $atomic_type->getGenericArrayType(); } $array_literal_types = \array_merge($atomic_type->type_params[1]->getLiteralStrings(), $atomic_type->type_params[1]->getLiteralInts(), $atomic_type->type_params[1]->getLiteralFloats()); if ($array_literal_types && \count($atomic_type->type_params[1]->getAtomicTypes())) { $literal_assertions = []; foreach ($array_literal_types as $array_literal_type) { $literal_assertions[] = '=' . $array_literal_type->getId(); } if ($atomic_type->type_params[1]->isFalsable()) { $literal_assertions[] = 'false'; } if ($atomic_type->type_params[1]->isNullable()) { $literal_assertions[] = 'null'; } if ($negate) { $if_types = \Psalm\Type\Algebra::negateTypes([$first_var_name => [$literal_assertions]]); } else { $if_types[$first_var_name] = [$literal_assertions]; } } } } } } elseif (self::hasArrayKeyExistsCheck($expr)) { $array_root = isset($expr->args[1]->value) ? \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($expr->args[1]->value, $this_class_name, $source) : null; if ($first_var_name === null && isset($expr->args[0])) { $first_arg = $expr->args[0]; if ($first_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $first_var_name = '\'' . $first_arg->value->value . '\''; } elseif ($first_arg->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $first_var_name = (string) $first_arg->value->value; } } if ($expr->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $expr->args[0]->value->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $expr->args[0]->value->name->name !== 'class') { $const_type = null; if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $const_type = $source->node_data->getType($expr->args[0]->value); } if ($const_type) { if ($const_type->isSingleStringLiteral()) { $first_var_name = $const_type->getSingleStringLiteral()->value; } elseif ($const_type->isSingleIntLiteral()) { $first_var_name = (string) $const_type->getSingleIntLiteral()->value; } else { $first_var_name = null; } } else { $first_var_name = null; } } if ($first_var_name !== null && $array_root && !\strpos($first_var_name, '->') && !\strpos($first_var_name, '[')) { $if_types[$array_root . '[' . $first_var_name . ']'] = [[$prefix . 'array-key-exists']]; } } elseif (self::hasNonEmptyCountCheck($expr)) { if ($first_var_name) { $if_types[$first_var_name] = [[$prefix . 'non-empty-countable']]; } } else { $if_types = self::processCustomAssertion($expr, $this_class_name, $source, $negate); } return $if_types; } private static function processIrreconcilableFunctionCall(\Psalm\Type\Union $first_var_type, \Psalm\Type\Union $expected_type, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr, \Psalm\Internal\Analyzer\StatementsAnalyzer $source, \Psalm\Codebase $codebase, bool $negate) : void { if ($first_var_type->hasMixed()) { return; } if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $first_var_type, $expected_type)) { return; } if (!$negate) { if ($first_var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType('Docblock type ' . $first_var_type . ' always contains ' . $expected_type, new \Psalm\CodeLocation($source, $expr), $first_var_type . ' ' . $expected_type), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition($first_var_type . ' always contains ' . $expected_type, new \Psalm\CodeLocation($source, $expr), $first_var_type . ' ' . $expected_type), $source->getSuppressedIssues())) { // fall through } } } else { if ($first_var_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction($first_var_type . ' does not contain ' . $expected_type, new \Psalm\CodeLocation($source, $expr), $first_var_type . ' ' . $expected_type), $source->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType($first_var_type . ' does not contain ' . $expected_type, new \Psalm\CodeLocation($source, $expr), $first_var_type . ' ' . $expected_type), $source->getSuppressedIssues())) { // fall through } } } } /** * @param PhpParser\Node\Expr\FuncCall|PhpParser\Node\Expr\MethodCall|PhpParser\Node\Expr\StaticCall $expr * * @return array>> */ protected static function processCustomAssertion(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr, ?string $this_class_name, \Psalm\FileSource $source, bool $negate = \false) : array { if (!$source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return []; } $if_true_assertions = $source->node_data->getIfTrueAssertions($expr); $if_false_assertions = $source->node_data->getIfFalseAssertions($expr); if ($if_true_assertions === null && $if_false_assertions === null) { return []; } $prefix = $negate ? '!' : ''; $first_var_name = isset($expr->args[0]->value) ? \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($expr->args[0]->value, $this_class_name, $source) : null; $if_types = []; if ($if_true_assertions) { foreach ($if_true_assertions as $assertion) { $assertion = clone $assertion; foreach ($assertion->rule as $i => $and_rules) { foreach ($and_rules as $j => $rule) { if (\strpos($rule, 'scalar-class-constant(') === 0) { $codebase = $source->getCodebase(); $assertion->rule[$i][$j] = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, \Psalm\Type::parseString(\substr($rule, 22, -1)), null, null, null)->getId(); } } } if (\is_int($assertion->var_id) && isset($expr->args[$assertion->var_id])) { if ($assertion->var_id === 0) { $var_name = $first_var_name; } else { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($expr->args[$assertion->var_id]->value, $this_class_name, $source); } if ($var_name) { if ($prefix === $assertion->rule[0][0][0]) { $if_types[$var_name] = [[\substr($assertion->rule[0][0], 1)]]; } else { $if_types[$var_name] = [[$prefix . $assertion->rule[0][0]]]; } } } elseif ($assertion->var_id === '$this' && $expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($expr->var, $this_class_name, $source); if ($var_id) { if ($prefix === $assertion->rule[0][0][0]) { $if_types[$var_id] = [[\substr($assertion->rule[0][0], 1)]]; } else { $if_types[$var_id] = [[$prefix . $assertion->rule[0][0]]]; } } } elseif (\is_string($assertion->var_id) && $expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall) { if ($prefix === $assertion->rule[0][0][0]) { $if_types[$assertion->var_id] = [[\substr($assertion->rule[0][0], 1)]]; } else { $if_types[$assertion->var_id] = [[$prefix . $assertion->rule[0][0]]]; } } } } if ($if_false_assertions) { $negated_prefix = !$negate ? '!' : ''; foreach ($if_false_assertions as $assertion) { $assertion = clone $assertion; foreach ($assertion->rule as $i => $and_rules) { foreach ($and_rules as $j => $rule) { if (\strpos($rule, 'scalar-class-constant(') === 0) { $codebase = $source->getCodebase(); $assertion->rule[$i][$j] = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, \Psalm\Type::parseString(\substr($rule, 22, -1)), null, null, null)->getId(); } } } if (\is_int($assertion->var_id) && isset($expr->args[$assertion->var_id])) { if ($assertion->var_id === 0) { $var_name = $first_var_name; } else { $var_name = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($expr->args[$assertion->var_id]->value, $this_class_name, $source); } if ($var_name) { if ($negated_prefix === $assertion->rule[0][0][0]) { $if_types[$var_name] = [[\substr($assertion->rule[0][0], 1)]]; } else { $if_types[$var_name] = [[$negated_prefix . $assertion->rule[0][0]]]; } } } elseif ($assertion->var_id === '$this' && $expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($expr->var, $this_class_name, $source); if ($var_id) { if ($negated_prefix === $assertion->rule[0][0][0]) { $if_types[$var_id] = [[\substr($assertion->rule[0][0], 1)]]; } else { $if_types[$var_id] = [[$negated_prefix . $assertion->rule[0][0]]]; } } } elseif (\is_string($assertion->var_id) && $expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall) { if ($prefix === $assertion->rule[0][0][0]) { $if_types[$assertion->var_id] = [[\substr($assertion->rule[0][0], 1)]]; } else { $if_types[$assertion->var_id] = [[$negated_prefix . $assertion->rule[0][0]]]; } } } } return $if_types; } /** * @return list */ protected static function getInstanceOfTypes(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_ $stmt, ?string $this_class_name, \Psalm\FileSource $source) : array { if ($stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { if (!\in_array(\strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], \true)) { $instanceof_class = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($stmt->class, $source->getAliases()); if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $codebase = $source->getCodebase(); $instanceof_class = $codebase->classlikes->getUnAliasedName($instanceof_class); } return [$instanceof_class]; } elseif ($this_class_name && \in_array(\strtolower($stmt->class->parts[0]), ['self', 'static'], \true)) { if ($stmt->class->parts[0] === 'static') { return ['=' . $this_class_name . '&static']; } return [$this_class_name]; } } elseif ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $stmt_class_type = $source->node_data->getType($stmt->class); if ($stmt_class_type) { $literal_class_strings = []; foreach ($stmt_class_type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TLiteralClassString) { $literal_class_strings[] = $atomic_type->value; } elseif ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $literal_class_strings[] = $atomic_type->param_name; } } return $literal_class_strings; } } return []; } protected static function hasNullVariable(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional, \Psalm\FileSource $source) : ?int { if ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($conditional->right->name->parts[0]) === 'null') { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($conditional->left->name->parts[0]) === 'null') { return self::ASSIGNMENT_TO_LEFT; } if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($right_type = $source->node_data->getType($conditional->right)) && $right_type->isNull()) { return self::ASSIGNMENT_TO_RIGHT; } return null; } public static function hasFalseVariable(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional) : ?int { if ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($conditional->right->name->parts[0]) === 'false') { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($conditional->left->name->parts[0]) === 'false') { return self::ASSIGNMENT_TO_LEFT; } return null; } public static function hasTrueVariable(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional) : ?int { if ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($conditional->right->name->parts[0]) === 'true') { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($conditional->left->name->parts[0]) === 'true') { return self::ASSIGNMENT_TO_LEFT; } return null; } protected static function hasEmptyArrayVariable(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional) : ?int { if ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ && !$conditional->right->items) { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ && !$conditional->left->items) { return self::ASSIGNMENT_TO_LEFT; } return null; } /** * @return false|int */ protected static function hasGetTypeCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional) { if ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->right->name->parts[0]) === 'gettype' && $conditional->right->args && $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->left->name->parts[0]) === 'gettype' && $conditional->left->args && $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { return self::ASSIGNMENT_TO_LEFT; } return \false; } /** * @return false|int */ protected static function hasGetDebugTypeCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional) { if ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->right->name->parts[0]) === 'get_debug_type' && $conditional->right->args && ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch)) { return self::ASSIGNMENT_TO_RIGHT; } if ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->left->name->parts[0]) === 'get_debug_type' && $conditional->left->args && ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch)) { return self::ASSIGNMENT_TO_LEFT; } return \false; } /** * @return false|int */ protected static function hasGetClassCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional, \Psalm\FileSource $source) { if (!$source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \false; } $right_get_class = $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->right->name->parts[0]) === 'get_class'; $right_static_class = $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $conditional->right->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $conditional->right->class->parts === ['static'] && $conditional->right->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($conditional->right->name->name) === 'class'; $left_class_string = $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $conditional->left->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $conditional->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($conditional->left->name->name) === 'class'; $left_type = $source->node_data->getType($conditional->left); $left_class_string_t = \false; if ($left_type && $left_type->isSingle()) { foreach ($left_type->getAtomicTypes() as $type_part) { if ($type_part instanceof \Psalm\Type\Atomic\TClassString) { $left_class_string_t = \true; break; } } } if (($right_get_class || $right_static_class) && ($left_class_string || $left_class_string_t)) { return self::ASSIGNMENT_TO_RIGHT; } $left_get_class = $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->left->name->parts[0]) === 'get_class'; $left_static_class = $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $conditional->left->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $conditional->left->class->parts === ['static'] && $conditional->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($conditional->left->name->name) === 'class'; $right_class_string = $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $conditional->right->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $conditional->right->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($conditional->right->name->name) === 'class'; $right_type = $source->node_data->getType($conditional->right); $right_class_string_t = \false; if ($right_type && $right_type->isSingle()) { foreach ($right_type->getAtomicTypes() as $type_part) { if ($type_part instanceof \Psalm\Type\Atomic\TClassString) { $right_class_string_t = \true; break; } } } if (($left_get_class || $left_static_class) && ($right_class_string || $right_class_string_t)) { return self::ASSIGNMENT_TO_LEFT; } return \false; } /** * @return false|int */ protected static function hasNonEmptyCountEqualityCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional, ?int &$min_count) { $left_count = $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->left->name->parts[0]) === 'count' && $conditional->left->args; $operator_greater_than_or_equal = $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual; if ($left_count && $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $operator_greater_than_or_equal && $conditional->right->value >= ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater ? 0 : 1)) { $min_count = $conditional->right->value + ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater ? 1 : 0); return self::ASSIGNMENT_TO_RIGHT; } $right_count = $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->right->name->parts[0]) === 'count' && $conditional->right->args; $operator_less_than_or_equal = $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual; if ($right_count && $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $operator_less_than_or_equal && $conditional->left->value >= ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller ? 0 : 1)) { $min_count = $conditional->left->value + ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller ? 1 : 0); return self::ASSIGNMENT_TO_LEFT; } return \false; } /** * @return false|int */ protected static function hasLessThanCountEqualityCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional, ?int &$max_count) { $left_count = $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->left->name->parts[0]) === 'count' && $conditional->left->args; $operator_less_than_or_equal = $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller; if ($left_count && $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $operator_less_than_or_equal) { $max_count = $conditional->right->value - ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller ? 1 : 0); return self::ASSIGNMENT_TO_RIGHT; } $right_count = $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->right->name->parts[0]) === 'count' && $conditional->right->args; $operator_greater_than_or_equal = $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater; if ($right_count && $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $operator_greater_than_or_equal) { $max_count = $conditional->left->value - ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater ? 1 : 0); return self::ASSIGNMENT_TO_LEFT; } return \false; } /** * @param PhpParser\Node\Expr\BinaryOp\NotIdentical|PhpParser\Node\Expr\BinaryOp\NotEqual $conditional * * @return false|int */ protected static function hasNotCountEqualityCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional, ?int &$count) { $left_count = $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->left->name->parts[0]) === 'count' && $conditional->left->args; if ($left_count && $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $count = $conditional->right->value; return self::ASSIGNMENT_TO_RIGHT; } $right_count = $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->right->name->parts[0]) === 'count' && $conditional->right->args; if ($right_count && $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $count = $conditional->left->value; return self::ASSIGNMENT_TO_LEFT; } return \false; } /** * @return false|int */ protected static function hasPositiveNumberCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional, ?int &$min_count) { $operator_greater_than_or_equal = $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual; if ($conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $operator_greater_than_or_equal && $conditional->right->value >= ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater ? 0 : 1)) { $min_count = $conditional->right->value + ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater ? 1 : 0); return self::ASSIGNMENT_TO_RIGHT; } $operator_less_than_or_equal = $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual; if ($conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $operator_less_than_or_equal && $conditional->left->value >= ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller ? 0 : 1)) { $min_count = $conditional->left->value + ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller ? 1 : 0); return self::ASSIGNMENT_TO_LEFT; } return \false; } /** * @return false|int */ protected static function hasReconcilableNonEmptyCountEqualityCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional) { $left_count = $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->left->name->parts[0]) === 'count'; $right_number = $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $conditional->right->value === ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater ? 0 : 1); $operator_greater_than_or_equal = $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual; if ($left_count && $right_number && $operator_greater_than_or_equal) { return self::ASSIGNMENT_TO_RIGHT; } $right_count = $conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $conditional->right->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($conditional->right->name->parts[0]) === 'count'; $left_number = $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $conditional->left->value === ($conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller ? 0 : 1); $operator_less_than_or_equal = $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller || $conditional instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual; if ($right_count && $left_number && $operator_less_than_or_equal) { return self::ASSIGNMENT_TO_LEFT; } return \false; } /** * @return false|int */ protected static function hasTypedValueComparison(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp $conditional, \Psalm\FileSource $source) { if (!$source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { return \false; } if (($right_type = $source->node_data->getType($conditional->right)) && (!$conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && !$conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && !$conditional->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch || $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch || $conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch) && \count($right_type->getAtomicTypes()) === 1 && !$right_type->hasMixed()) { return self::ASSIGNMENT_TO_RIGHT; } if (($left_type = $source->node_data->getType($conditional->left)) && !$conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && !$conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && !$conditional->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch && \count($left_type->getAtomicTypes()) === 1 && !$left_type->hasMixed()) { return self::ASSIGNMENT_TO_LEFT; } return \false; } protected static function hasNullCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'is_null') { return \true; } return \false; } protected static function hasIsACheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt, \Psalm\Internal\Analyzer\StatementsAnalyzer $source) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && (\strtolower($stmt->name->parts[0]) === 'is_a' || \strtolower($stmt->name->parts[0]) === 'is_subclass_of') && isset($stmt->args[1])) { $second_arg = $stmt->args[1]->value; if ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $second_arg->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $second_arg->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($second_arg->name->name) === 'class' || ($second_arg_type = $source->node_data->getType($second_arg)) && $second_arg_type->hasString()) { return \true; } } return \false; } protected static function hasArrayCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'is_array') { return \true; } return \false; } protected static function hasStringCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'is_string') { return \true; } return \false; } protected static function hasBoolCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'is_bool') { return \true; } return \false; } protected static function hasObjectCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name->parts === ['is_object']) { return \true; } return \false; } protected static function hasNumericCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name->parts === ['is_numeric']) { return \true; } return \false; } protected static function hasIterableCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'is_iterable') { return \true; } return \false; } protected static function hasCountableCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'is_countable') { return \true; } return \false; } /** * @return 0|1|2 */ protected static function hasClassExistsCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : int { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'class_exists') { if (!isset($stmt->args[1])) { return 2; } $second_arg = $stmt->args[1]->value; if ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($second_arg->name->parts[0]) === 'true') { return 2; } return 1; } return 0; } /** * @return 0|1|2 */ protected static function hasTraitExistsCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : int { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'trait_exists') { if (!isset($stmt->args[1])) { return 2; } $second_arg = $stmt->args[1]->value; if ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($second_arg->name->parts[0]) === 'true') { return 2; } return 1; } return 0; } protected static function hasInterfaceExistsCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'interface_exists') { return \true; } return \false; } protected static function hasFunctionExistsCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && \strtolower($stmt->name->parts[0]) === 'function_exists') { return \true; } return \false; } protected static function hasIntCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && ($stmt->name->parts === ['is_int'] || $stmt->name->parts === ['is_integer'] || $stmt->name->parts === ['is_long'])) { return \true; } return \false; } protected static function hasFloatCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && ($stmt->name->parts === ['is_float'] || $stmt->name->parts === ['is_real'] || $stmt->name->parts === ['is_double'])) { return \true; } return \false; } protected static function hasResourceCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name->parts === ['is_resource']) { return \true; } return \false; } protected static function hasScalarCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name->parts === ['is_scalar']) { return \true; } return \false; } protected static function hasCallableCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name->parts === ['is_callable']) { return \true; } return \false; } protected static function hasInArrayCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name->parts === ['in_array'] && isset($stmt->args[2])) { $second_arg = $stmt->args[2]->value; if ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($second_arg->name->parts[0]) === 'true') { return \true; } } return \false; } protected static function hasNonEmptyCountCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name->parts === ['count']) { return \true; } return \false; } protected static function hasArrayKeyExistsCheck(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $stmt) : bool { if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name->parts === ['array_key_exists']) { return \true; } return \false; } } name)) { return '$' . $stmt->name; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { if (\count($stmt->class->parts) === 1 && \in_array(\strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], \true)) { if (!$this_class_name) { $fq_class_name = $stmt->class->parts[0]; } else { $fq_class_name = $this_class_name; } } else { $fq_class_name = $source ? \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($stmt->class, $source->getAliases()) : \implode('\\', $stmt->class->parts); } return $fq_class_name . '::$' . $stmt->name->name; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $object_id = self::getVarId($stmt->var, $this_class_name, $source); if (!$object_id) { return null; } return $object_id . '->' . $stmt->name->name; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch && $nesting !== null) { ++$nesting; return self::getVarId($stmt->var, $this_class_name, $source, $nesting); } return null; } public static function getRootVarId(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, ?string $this_class_name, ?\Psalm\FileSource $source = null) : ?string { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch) { return self::getVarId($stmt, $this_class_name, $source); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $property_root = self::getRootVarId($stmt->var, $this_class_name, $source); if ($property_root) { return $property_root . '->' . $stmt->name->name; } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { return self::getRootVarId($stmt->var, $this_class_name, $source); } return null; } public static function getArrayVarId(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, ?string $this_class_name, ?\Psalm\FileSource $source = null) : ?string { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { return self::getArrayVarId($stmt->var, $this_class_name, $source); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { $root_var_id = self::getArrayVarId($stmt->var, $this_class_name, $source); $offset = null; if ($root_var_id) { if ($stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $offset = $stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ ? '\'' . $stmt->dim->value . '\'' : $stmt->dim->value; } elseif ($stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($stmt->dim->name)) { $offset = '$' . $stmt->dim->name; } elseif ($stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { $offset = \implode('\\', $stmt->dim->name->parts); } elseif ($stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch) { $object_id = self::getArrayVarId($stmt->dim->var, $this_class_name, $source); if ($object_id && $stmt->dim->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $offset = $object_id . '->' . $stmt->dim->name; } } elseif ($stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $stmt->dim->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $stmt->dim->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->dim->class->parts[0] === 'static') { $offset = 'static::' . $stmt->dim->name; } elseif ($stmt->dim && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($stmt_dim_type = $source->node_data->getType($stmt->dim)) && (!$stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || !$stmt->dim->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier || $stmt->dim->name->name !== 'class')) { if ($stmt_dim_type->isSingleStringLiteral()) { $offset = '\'' . $stmt_dim_type->getSingleStringLiteral()->value . '\''; } elseif ($stmt_dim_type->isSingleIntLiteral()) { $offset = $stmt_dim_type->getSingleIntLiteral()->value; } } elseif ($stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $stmt->dim->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { /** @var string|null */ $resolved_name = $stmt->dim->class->getAttribute('resolvedName'); if ($resolved_name) { $offset = $resolved_name . '::' . $stmt->dim->name; } } return $offset !== null ? $root_var_id . '[' . $offset . ']' : null; } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch) { $object_id = self::getArrayVarId($stmt->var, $this_class_name, $source); if (!$object_id) { return null; } if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { return $object_id . '->' . $stmt->name; } elseif ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer && ($stmt_name_type = $source->node_data->getType($stmt->name)) && $stmt_name_type->isSingleStringLiteral()) { return $object_id . '->' . $stmt_name_type->getSingleStringLiteral()->value; } else { return null; } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { /** @var string|null */ $resolved_name = $stmt->class->getAttribute('resolvedName'); if ($resolved_name) { if (($resolved_name === 'self' || $resolved_name === 'static') && $this_class_name) { $resolved_name = $this_class_name; } return $resolved_name . '::' . $stmt->name; } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && !$stmt->args) { $config = \Psalm\Config::getInstance(); if ($config->memoize_method_calls || isset($stmt->pure)) { $lhs_var_name = self::getArrayVarId($stmt->var, $this_class_name, $source); if (!$lhs_var_name) { return null; } return $lhs_var_name . '->' . \strtolower($stmt->name->name) . '()'; } } return self::getVarId($stmt, $this_class_name, $source); } } inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; if ($stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context) === \false) { return \false; } } elseif (!\in_array(\strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], \true)) { if ($context->check_classes) { $codebase = $statements_analyzer->getCodebase(); $fq_class_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($stmt->class, $statements_analyzer->getAliases()); if ($codebase->store_node_types && $fq_class_name && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->class, $codebase->classlikes->classOrInterfaceExists($fq_class_name) ? $fq_class_name : '*' . \implode('\\', $stmt->class->parts)); } if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_class_name, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->class), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues(), \false) === \false) { return \false; } if ($codebase->alter_code) { $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $stmt->class, $fq_class_name, $context->calling_method_id); } } } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getBool()); return \true; } } node_data->setType($stmt, \Psalm\Type::getInt()); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Class_) { $codebase = $statements_analyzer->getCodebase(); if (!$context->self) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedConstant('Cannot get __class__ outside a class', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getClassString()); } else { if ($codebase->alter_code) { $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $stmt, $context->self, $context->calling_method_id); } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getLiteralClassString($context->self)); } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Namespace_) { $namespace = $statements_analyzer->getNamespace(); if ($namespace === null && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedConstant('Cannot get __namespace__ outside a namespace', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getString($namespace)); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Method || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Function_) { $source = $statements_analyzer->getSource(); if ($source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getString($source->getId())); } else { $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TCallableString()])); } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\File || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Dir) { $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyString()])); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Trait_) { if ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) { $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyString()])); } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getString()); } } } } node_data->setType($stmt, $stmt_type); $inside_negation = $context->inside_negation; $context->inside_negation = !$inside_negation; $result = \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context); $context->inside_negation = $inside_negation; $expr_type = $statements_analyzer->node_data->getType($stmt->expr); if ($expr_type) { $stmt_type->parent_nodes = $expr_type->parent_nodes; } return $result; } } items)) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getEmptyArray()); return \true; } $item_key_atomic_types = []; $item_value_atomic_types = []; $property_types = []; $class_strings = []; $can_create_objectlike = \true; $array_keys = []; $int_offset_diff = 0; $codebase = $statements_analyzer->getCodebase(); $all_list = \true; $parent_taint_nodes = []; foreach ($stmt->items as $int_offset => $item) { if ($item === null) { \Psalm\IssueBuffer::add(new \Psalm\Issue\ParseError('Array element cannot be empty', new \Psalm\CodeLocation($statements_analyzer, $stmt))); return \false; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $item->value, $context) === \false) { return \false; } if ($item->unpack) { $unpacked_array_type = $statements_analyzer->node_data->getType($item->value); if (!$unpacked_array_type) { continue; } foreach ($unpacked_array_type->getAtomicTypes() as $unpacked_atomic_type) { if ($unpacked_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $unpacked_array_offset = 0; foreach ($unpacked_atomic_type->properties as $key => $property_value) { if (\is_string($key)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DuplicateArrayKey('String keys are not supported in unpacked arrays', new \Psalm\CodeLocation($statements_analyzer->getSource(), $item->value)), $statements_analyzer->getSuppressedIssues())) { // fall through } continue; } $item_key_atomic_types[] = new \Psalm\Type\Atomic\TLiteralInt($key); $item_value_atomic_types = \array_merge($item_value_atomic_types, \array_values($property_value->getAtomicTypes())); $array_keys[$int_offset + $int_offset_diff + $unpacked_array_offset] = \true; $property_types[$int_offset + $int_offset_diff + $unpacked_array_offset] = $property_value; $unpacked_array_offset++; } $int_offset_diff += $unpacked_array_offset - 1; } else { $can_create_objectlike = \false; if ($unpacked_atomic_type instanceof \Psalm\Type\Atomic\TArray) { if ($unpacked_atomic_type->type_params[0]->hasString()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DuplicateArrayKey('String keys are not supported in unpacked arrays', new \Psalm\CodeLocation($statements_analyzer->getSource(), $item->value)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($unpacked_atomic_type->type_params[0]->hasInt()) { $item_key_atomic_types[] = new \Psalm\Type\Atomic\TInt(); } $item_value_atomic_types = \array_merge($item_value_atomic_types, \array_values($unpacked_atomic_type->type_params[1]->getAtomicTypes())); } elseif ($unpacked_atomic_type instanceof \Psalm\Type\Atomic\TList) { $item_key_atomic_types[] = new \Psalm\Type\Atomic\TInt(); $item_value_atomic_types = \array_merge($item_value_atomic_types, \array_values($unpacked_atomic_type->type_param->getAtomicTypes())); } } } continue; } $item_key_value = null; if ($item->key) { $all_list = \false; $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $item->key, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; if ($item_key_type = $statements_analyzer->node_data->getType($item->key)) { $key_type = $item_key_type; if ($key_type->isNull()) { $key_type = \Psalm\Type::getString(''); } if ($item->key instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ && \preg_match('/^(0|[1-9][0-9]*)$/', $item->key->value)) { $key_type = \Psalm\Type::getInt(\false, (int) $item->key->value); } $item_key_atomic_types = \array_merge($item_key_atomic_types, \array_values($key_type->getAtomicTypes())); if ($key_type->isSingleStringLiteral()) { $item_key_literal_type = $key_type->getSingleStringLiteral(); $item_key_value = $item_key_literal_type->value; if ($item_key_literal_type instanceof \Psalm\Type\Atomic\TLiteralClassString) { $class_strings[$item_key_value] = \true; } } elseif ($key_type->isSingleIntLiteral()) { $item_key_value = $key_type->getSingleIntLiteral()->value; if ($item_key_value > $int_offset + $int_offset_diff) { $int_offset_diff = $item_key_value - $int_offset; } } } } else { $item_key_value = $int_offset + $int_offset_diff; $item_key_atomic_types[] = new \Psalm\Type\Atomic\TInt(); } if ($item_key_value !== null) { if (isset($array_keys[$item_key_value])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DuplicateArrayKey('Key \'' . $item_key_value . '\' already exists on array', new \Psalm\CodeLocation($statements_analyzer->getSource(), $item)), $statements_analyzer->getSuppressedIssues())) { // fall through } } $array_keys[$item_key_value] = \true; } if ($statements_analyzer->data_flow_graph && ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph || !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues()))) { if ($item_value_type = $statements_analyzer->node_data->getType($item->value)) { if ($item_value_type->parent_nodes) { $var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $item); $new_parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment('array' . ($item_key_value !== null ? '[\'' . $item_key_value . '\']' : ''), $var_location); $statements_analyzer->data_flow_graph->addNode($new_parent_node); foreach ($item_value_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $new_parent_node, 'array-assignment' . ($item_key_value !== null ? '-\'' . $item_key_value . '\'' : '')); } $parent_taint_nodes += [$new_parent_node->id => $new_parent_node]; } } } if ($item->byRef) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($item->value, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($var_id) { $context->removeDescendents($var_id, $context->vars_in_scope[$var_id] ?? null, null, $statements_analyzer); $context->vars_in_scope[$var_id] = \Psalm\Type::getMixed(); } } if ($item_value_atomic_types && !$can_create_objectlike) { continue; } if ($item_value_type = $statements_analyzer->node_data->getType($item->value)) { if ($item_key_value !== null && \count($property_types) <= 100) { $property_types[$item_key_value] = $item_value_type; } else { $can_create_objectlike = \false; } $item_value_atomic_types = \array_merge($item_value_atomic_types, \array_values($item_value_type->getAtomicTypes())); } else { $item_value_atomic_types[] = new \Psalm\Type\Atomic\TMixed(); if ($item_key_value !== null && \count($property_types) <= 100) { $property_types[$item_key_value] = \Psalm\Type::getMixed(); } else { $can_create_objectlike = \false; } } } if ($item_key_atomic_types) { $item_key_type = \Psalm\Internal\Type\TypeCombination::combineTypes($item_key_atomic_types, $codebase, \false, \true, 30); } else { $item_key_type = null; } if ($item_value_atomic_types) { $item_value_type = \Psalm\Internal\Type\TypeCombination::combineTypes($item_value_atomic_types, $codebase, \false, \true, 30); } else { $item_value_type = null; } // if this array looks like an object-like array, let's return that instead if ($item_value_type && $item_key_type && ($item_key_type->hasString() || $item_key_type->hasInt()) && $can_create_objectlike && $property_types) { $object_like = new \Psalm\Type\Atomic\TKeyedArray($property_types, $class_strings); $object_like->sealed = \true; $object_like->is_list = $all_list; $stmt_type = new \Psalm\Type\Union([$object_like]); if ($parent_taint_nodes) { $stmt_type->parent_nodes = $parent_taint_nodes; } $statements_analyzer->node_data->setType($stmt, $stmt_type); return \true; } if ($all_list) { $array_type = new \Psalm\Type\Atomic\TNonEmptyList($item_value_type ?: \Psalm\Type::getMixed()); $array_type->count = \count($stmt->items); $stmt_type = new \Psalm\Type\Union([$array_type]); if ($parent_taint_nodes) { $stmt_type->parent_nodes = $parent_taint_nodes; } $statements_analyzer->node_data->setType($stmt, $stmt_type); return \true; } $array_type = new \Psalm\Type\Atomic\TNonEmptyArray([$item_key_type && !$item_key_type->hasMixed() ? $item_key_type : \Psalm\Type::getArrayKey(), $item_value_type ?: \Psalm\Type::getMixed()]); $array_type->count = \count($stmt->items); $stmt_type = new \Psalm\Type\Union([$array_type]); if ($parent_taint_nodes) { $stmt_type->parent_nodes = $parent_taint_nodes; } $statements_analyzer->node_data->setType($stmt, $stmt_type); return \true; } } var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context); $tmp_name = '__tmp_nullsafe__' . (int) $stmt->var->getAttribute('startFilePos'); $condition_type = $statements_analyzer->node_data->getType($stmt->var); if ($condition_type) { $context->vars_in_scope['$' . $tmp_name] = $condition_type; $tmp_var = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($tmp_name, $stmt->var->getAttributes()); } else { $tmp_var = $stmt->var; } } else { $tmp_var = $stmt->var; } $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $null_value1 = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('null'), $stmt->var->getAttributes()); $null_comparison = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical($tmp_var, $null_value1, $stmt->var->getAttributes()); $null_value2 = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('null'), $stmt->var->getAttributes()); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafePropertyFetch) { $ternary = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary($null_comparison, $null_value2, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch($tmp_var, $stmt->name, $stmt->getAttributes()), $stmt->getAttributes()); } else { $ternary = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary($null_comparison, $null_value2, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($tmp_var, $stmt->name, $stmt->args, $stmt->getAttributes()), $stmt->getAttributes()); } \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $ternary, $context); $ternary_type = $statements_analyzer->node_data->getType($ternary); $statements_analyzer->node_data = $old_node_data; $statements_analyzer->node_data->setType($stmt, $ternary_type ?: \Psalm\Type::getMixed()); return \true; } } self, $statements_analyzer); $lhs_type = $statements_analyzer->node_data->getType($stmt->class); if (!$lhs_type) { return null; } $codebase = $statements_analyzer->getCodebase(); $prop_name = $stmt->name; foreach ($lhs_type->getAtomicTypes() as $lhs_atomic_type) { if ($lhs_atomic_type instanceof \Psalm\Type\Atomic\TClassString) { if (!$lhs_atomic_type->as_type) { continue; } $lhs_atomic_type = $lhs_atomic_type->as_type; } if (!$lhs_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { continue; } $fq_class_name = $lhs_atomic_type->value; if (!$prop_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $prop_name, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; if (!$context->ignore_variable_property) { $codebase->analyzer->addMixedMemberName(\strtolower($fq_class_name) . '::$', $context->calling_method_id ?: $statements_analyzer->getFileName()); } return null; } $property_id = $fq_class_name . '::$' . $prop_name; if (!$codebase->properties->propertyExists($property_id, \false, $statements_analyzer, $context)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedPropertyAssignment('Static property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } return null; } if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkPropertyVisibility($property_id, $context, $statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues()) === \false) { return \false; } $declaring_property_class = (string) $codebase->properties->getDeclaringClassForProperty($fq_class_name . '::$' . $prop_name->name, \false); $declaring_property_id = \strtolower($declaring_property_class) . '::$' . $prop_name; if ($codebase->alter_code && $stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $moved_class = $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $stmt->class, $fq_class_name, $context->calling_method_id); if (!$moved_class) { foreach ($codebase->property_transforms as $original_pattern => $transformation) { if ($declaring_property_id === $original_pattern) { [$old_declaring_fq_class_name] = \explode('::$', $declaring_property_id); [$new_fq_class_name, $new_property_name] = \explode('::$', $transformation); $file_manipulations = []; if (\strtolower($new_fq_class_name) !== \strtolower($old_declaring_fq_class_name)) { $file_manipulations[] = new \Psalm\FileManipulation((int) $stmt->class->getAttribute('startFilePos'), (int) $stmt->class->getAttribute('endFilePos') + 1, \Psalm\Type::getStringFromFQCLN($new_fq_class_name, $statements_analyzer->getNamespace(), $statements_analyzer->getAliasedClassesFlipped(), null)); } $file_manipulations[] = new \Psalm\FileManipulation((int) $stmt->name->getAttribute('startFilePos'), (int) $stmt->name->getAttribute('endFilePos') + 1, '$' . $new_property_name); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } } } $class_storage = $codebase->classlike_storage_provider->get($declaring_property_class); if ($var_id) { $context->vars_in_scope[$var_id] = $assignment_value_type; } $class_property_type = $codebase->properties->getPropertyType($property_id, \true, $statements_analyzer, $context); if (!$class_property_type) { $class_property_type = \Psalm\Type::getMixed(); $source_analyzer = $statements_analyzer->getSource()->getSource(); $prop_name_name = $prop_name->name; if ($source_analyzer instanceof \Psalm\Internal\Analyzer\ClassAnalyzer && $fq_class_name === $source_analyzer->getFQCLN()) { if (isset($source_analyzer->inferred_property_types[$prop_name_name])) { $source_analyzer->inferred_property_types[$prop_name_name] = \Psalm\Type::combineUnionTypes($assignment_value_type, $source_analyzer->inferred_property_types[$prop_name_name]); } else { $source_analyzer->inferred_property_types[$prop_name_name] = $assignment_value_type; } } } else { $class_property_type = clone $class_property_type; } if ($assignment_value_type->hasMixed()) { return null; } if ($class_property_type->hasMixed()) { return null; } $class_property_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $class_property_type, $fq_class_name, $fq_class_name, $class_storage->parent_class); $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $type_match_found = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $assignment_value_type, $class_property_type, \true, \true, $union_comparison_results); if ($union_comparison_results->type_coerced) { if ($union_comparison_results->type_coerced_from_mixed) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedPropertyTypeCoercion($var_id . ' expects \'' . $class_property_type->getId() . '\', ' . ' parent type `' . $assignment_value_type->getId() . '` provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location), $property_id), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PropertyTypeCoercion($var_id . ' expects \'' . $class_property_type->getId() . '\', ' . ' parent type \'' . $assignment_value_type->getId() . '\' provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location), $property_id), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } } if ($union_comparison_results->to_string_cast) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImplicitToStringCast($var_id . ' expects \'' . $class_property_type . '\', ' . '\'' . $assignment_value_type . '\' provided with a __toString method', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if (!$type_match_found && !$union_comparison_results->type_coerced) { if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::canBeContainedBy($codebase, $assignment_value_type, $class_property_type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidPropertyAssignmentValue($var_id . ' with declared type \'' . $class_property_type->getId() . '\' cannot be assigned type \'' . $assignment_value_type->getId() . '\'', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { return \false; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidPropertyAssignmentValue($var_id . ' with declared type \'' . $class_property_type->getId() . '\' cannot be assigned type \'' . $assignment_value_type->getId() . '\'', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { return \false; } } } if ($var_id) { $context->vars_in_scope[$var_id] = $assignment_value_type; } } return null; } } var, $statements_analyzer->getFQCLN(), $statements_analyzer, $nesting); self::updateArrayType($statements_analyzer, $stmt, $assign_value, $assignment_value_type, $context); if (!$statements_analyzer->node_data->getType($stmt->var) && $var_id) { $context->vars_in_scope[$var_id] = \Psalm\Type::getMixed(); } } /** * @return false|null */ public static function updateArrayType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch $stmt, ?\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $assign_value, \Psalm\Type\Union $assignment_type, \Psalm\Context $context) : ?bool { $root_array_expr = $stmt; $child_stmts = []; while ($root_array_expr->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { $child_stmts[] = $root_array_expr; $root_array_expr = $root_array_expr->var; } $child_stmts[] = $root_array_expr; $root_array_expr = $root_array_expr->var; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $root_array_expr, $context, \true) === \false) { // fall through } $codebase = $statements_analyzer->getCodebase(); $root_type = $statements_analyzer->node_data->getType($root_array_expr) ?: \Psalm\Type::getMixed(); if ($root_type->hasMixed()) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context, \true) === \false) { // fall through } if ($stmt->dim) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->dim, $context) === \false) { // fall through } } } $child_stmts = \array_reverse($child_stmts); $current_type = $root_type; $current_dim = $stmt->dim; $reversed_child_stmts = []; // gets a variable id that *may* contain array keys $root_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($root_array_expr, $statements_analyzer->getFQCLN(), $statements_analyzer); $var_id_additions = []; $parent_var_id = null; $offset_already_existed = \false; $full_var_id = \true; $child_stmt = null; // First go from the root element up, and go as far as we can to figure out what // array types there are while ($child_stmts) { $child_stmt = \array_shift($child_stmts); if (\count($child_stmts)) { \array_unshift($reversed_child_stmts, $child_stmt); } $child_stmt_dim_type = null; $dim_value = null; if ($child_stmt->dim) { $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $child_stmt->dim, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; if (!($child_stmt_dim_type = $statements_analyzer->node_data->getType($child_stmt->dim))) { return null; } if ($child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || ($child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch || $child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch) && $child_stmt_dim_type->isSingleStringLiteral()) { if ($child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $dim_value = new \Psalm\Type\Atomic\TLiteralString($child_stmt->dim->value); } else { $dim_value = $child_stmt_dim_type->getSingleStringLiteral(); } if (\preg_match('/^(0|[1-9][0-9]*)$/', $dim_value->value)) { $var_id_additions[] = '[' . $dim_value->value . ']'; } else { $var_id_additions[] = '[\'' . $dim_value->value . '\']'; } } elseif ($child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || ($child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch || $child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch) && $child_stmt_dim_type->isSingleIntLiteral()) { if ($child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $dim_value = new \Psalm\Type\Atomic\TLiteralInt($child_stmt->dim->value); } else { $dim_value = $child_stmt_dim_type->getSingleIntLiteral(); } $var_id_additions[] = '[' . $dim_value->value . ']'; } elseif ($child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($child_stmt->dim->name)) { $var_id_additions[] = '[$' . $child_stmt->dim->name . ']'; } elseif ($child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && $child_stmt->dim->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $object_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($child_stmt->dim->var, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($object_id) { $var_id_additions[] = '[' . $object_id . '->' . $child_stmt->dim->name->name . ']'; } } elseif ($child_stmt->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $child_stmt->dim->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $child_stmt->dim->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $object_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($child_stmt->dim->class, $statements_analyzer->getAliases()); $var_id_additions[] = '[' . $object_name . '::' . $child_stmt->dim->name->name . ']'; } else { $var_id_additions[] = '[' . $child_stmt_dim_type . ']'; $full_var_id = \false; } } else { $var_id_additions[] = ''; $full_var_id = \false; } if (!($child_stmt_var_type = $statements_analyzer->node_data->getType($child_stmt->var))) { return null; } if ($child_stmt_var_type->isEmpty()) { $child_stmt_var_type = \Psalm\Type::getEmptyArray(); $statements_analyzer->node_data->setType($child_stmt->var, $child_stmt_var_type); } $array_var_id = $root_var_id . \implode('', $var_id_additions); if ($parent_var_id && isset($context->vars_in_scope[$parent_var_id])) { $child_stmt_var_type = clone $context->vars_in_scope[$parent_var_id]; $statements_analyzer->node_data->setType($child_stmt->var, $child_stmt_var_type); } $array_type = clone $child_stmt_var_type; $child_stmt_type = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::getArrayAccessTypeGivenOffset($statements_analyzer, $child_stmt, $array_type, $child_stmt_dim_type ?: \Psalm\Type::getInt(), \true, $array_var_id, $context, $assign_value, $child_stmts ? null : $assignment_type); $statements_analyzer->node_data->setType($child_stmt, $child_stmt_type); $statements_analyzer->node_data->setType($child_stmt->var, $array_type); if ($root_var_id) { if (!$parent_var_id) { $rooted_parent_id = $root_var_id; $root_type = $array_type; } else { $rooted_parent_id = $parent_var_id; } $context->vars_in_scope[$rooted_parent_id] = $array_type; $context->possibly_assigned_var_ids[$rooted_parent_id] = \true; } if (!$child_stmts) { // we need this slight hack as the type we're putting it has to be // different from the type we're getting out if ($array_type->isSingle() && $array_type->hasClassStringMap()) { $assignment_type = $child_stmt_type; } $child_stmt_type = $assignment_type; $statements_analyzer->node_data->setType($child_stmt, $assignment_type); if ($statements_analyzer->data_flow_graph) { self::taintArrayAssignment($statements_analyzer, $child_stmt, $array_type, $assignment_type, \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($child_stmt->var, $statements_analyzer->getFQCLN(), $statements_analyzer), $dim_value !== null ? [$dim_value] : []); } } $current_type = $child_stmt_type; $current_dim = $child_stmt->dim; $parent_var_id = $array_var_id; } if ($root_var_id && $full_var_id && $child_stmt && ($child_stmt_var_type = $statements_analyzer->node_data->getType($child_stmt->var)) && !$child_stmt_var_type->hasObjectType()) { $array_var_id = $root_var_id . \implode('', $var_id_additions); $parent_var_id = $root_var_id . \implode('', \array_slice($var_id_additions, 0, -1)); if (isset($context->vars_in_scope[$array_var_id]) && !$context->vars_in_scope[$array_var_id]->possibly_undefined) { $offset_already_existed = \true; } $context->vars_in_scope[$array_var_id] = clone $assignment_type; $context->possibly_assigned_var_ids[$array_var_id] = \true; } // only update as many child stmts are we were able to process above foreach ($reversed_child_stmts as $child_stmt) { $child_stmt_type = $statements_analyzer->node_data->getType($child_stmt); if (!$child_stmt_type) { throw new \InvalidArgumentException('Should never get here'); } $key_values = []; if ($current_dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $key_values[] = new \Psalm\Type\Atomic\TLiteralString($current_dim->value); } elseif ($current_dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $key_values[] = new \Psalm\Type\Atomic\TLiteralInt($current_dim->value); } elseif ($current_dim && ($current_dim_type = $statements_analyzer->node_data->getType($current_dim))) { $string_literals = $current_dim_type->getLiteralStrings(); $int_literals = $current_dim_type->getLiteralInts(); $all_atomic_types = $current_dim_type->getAtomicTypes(); if (\count($string_literals) + \count($int_literals) === \count($all_atomic_types)) { foreach ($string_literals as $string_literal) { $key_values[] = clone $string_literal; } foreach ($int_literals as $int_literal) { $key_values[] = clone $int_literal; } } } if ($key_values) { $new_child_type = self::updateTypeWithKeyValues($codebase, $child_stmt_type, $current_type, $key_values); } else { if (!$current_dim) { $array_assignment_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList($current_type)]); } else { $current_dim_type = $statements_analyzer->node_data->getType($current_dim); $array_assignment_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([$current_dim_type && !$current_dim_type->hasMixed() ? $current_dim_type : \Psalm\Type::getArrayKey(), $current_type])]); } $new_child_type = \Psalm\Type::combineUnionTypes($child_stmt_type, $array_assignment_type, $codebase, \true, \true); } $new_child_type->removeType('null'); $new_child_type->possibly_undefined = \false; if (!$child_stmt_type->hasObjectType()) { $child_stmt_type = $new_child_type; $statements_analyzer->node_data->setType($child_stmt, $new_child_type); } $current_type = $child_stmt_type; $current_dim = $child_stmt->dim; \array_pop($var_id_additions); $parent_array_var_id = null; if ($root_var_id) { $array_var_id = $root_var_id . \implode('', $var_id_additions); $parent_array_var_id = $root_var_id . \implode('', \array_slice($var_id_additions, 0, -1)); $context->vars_in_scope[$array_var_id] = clone $child_stmt_type; $context->possibly_assigned_var_ids[$array_var_id] = \true; } if ($statements_analyzer->data_flow_graph) { self::taintArrayAssignment($statements_analyzer, $child_stmt, $statements_analyzer->node_data->getType($child_stmt->var) ?: \Psalm\Type::getMixed(), $new_child_type, $parent_array_var_id, $key_values); } } $root_is_string = $root_type->isString(); $key_values = []; if ($current_dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $key_values[] = new \Psalm\Type\Atomic\TLiteralString($current_dim->value); } elseif ($current_dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && !$root_is_string) { $key_values[] = new \Psalm\Type\Atomic\TLiteralInt($current_dim->value); } elseif ($current_dim && ($current_dim_type = $statements_analyzer->node_data->getType($current_dim)) && !$root_is_string) { $string_literals = $current_dim_type->getLiteralStrings(); $int_literals = $current_dim_type->getLiteralInts(); $all_atomic_types = $current_dim_type->getAtomicTypes(); if (\count($string_literals) + \count($int_literals) === \count($all_atomic_types)) { foreach ($string_literals as $string_literal) { $key_values[] = clone $string_literal; } foreach ($int_literals as $int_literal) { $key_values[] = clone $int_literal; } } } if ($key_values) { $new_child_type = self::updateTypeWithKeyValues($codebase, $root_type, $current_type, $key_values); } elseif (!$root_is_string) { if ($current_dim) { if ($current_dim_type = $statements_analyzer->node_data->getType($current_dim)) { if ($current_dim_type->hasMixed()) { $current_dim_type = \Psalm\Type::getArrayKey(); } $array_atomic_key_type = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::replaceOffsetTypeWithInts($current_dim_type); } else { $array_atomic_key_type = \Psalm\Type::getArrayKey(); } if ($offset_already_existed && $child_stmt && $parent_var_id && ($parent_type = $context->vars_in_scope[$parent_var_id] ?? null)) { if ($parent_type->hasList()) { $array_atomic_type = new \Psalm\Type\Atomic\TNonEmptyList($current_type); } elseif ($parent_type->hasClassStringMap() && $current_dim_type && $current_dim_type->isTemplatedClassString()) { /** * @var Type\Atomic\TClassStringMap * @psalm-suppress PossiblyUndefinedStringArrayOffset */ $class_string_map = $parent_type->getAtomicTypes()['array']; /** * @var Type\Atomic\TTemplateParamClass */ $offset_type_part = \array_values($current_dim_type->getAtomicTypes())[0]; $template_result = new \Psalm\Internal\Type\TemplateResult([], [$offset_type_part->param_name => [$offset_type_part->defining_class => [new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParam($class_string_map->param_name, $offset_type_part->as_type ? new \Psalm\Type\Union([$offset_type_part->as_type]) : \Psalm\Type::getObject(), 'class-string-map')])]]]); $current_type->replaceTemplateTypesWithArgTypes($template_result, $codebase); $array_atomic_type = new \Psalm\Type\Atomic\TClassStringMap($class_string_map->param_name, $class_string_map->as_type, $current_type); } else { $array_atomic_type = new \Psalm\Type\Atomic\TNonEmptyArray([$array_atomic_key_type, $current_type]); } } else { $array_atomic_type = new \Psalm\Type\Atomic\TNonEmptyArray([$array_atomic_key_type, $current_type]); } } else { $array_atomic_type = new \Psalm\Type\Atomic\TNonEmptyList($current_type); } $from_countable_object_like = \false; $new_child_type = null; if (!$current_dim && !$context->inside_loop) { $atomic_root_types = $root_type->getAtomicTypes(); if (isset($atomic_root_types['array'])) { if ($array_atomic_type instanceof \Psalm\Type\Atomic\TClassStringMap) { $array_atomic_type = new \Psalm\Type\Atomic\TNonEmptyArray([$array_atomic_type->getStandinKeyParam(), $array_atomic_type->value_param]); } elseif ($atomic_root_types['array'] instanceof \Psalm\Type\Atomic\TNonEmptyArray || $atomic_root_types['array'] instanceof \Psalm\Type\Atomic\TNonEmptyList) { $array_atomic_type->count = $atomic_root_types['array']->count; } elseif ($atomic_root_types['array'] instanceof \Psalm\Type\Atomic\TKeyedArray && $atomic_root_types['array']->sealed) { $array_atomic_type->count = \count($atomic_root_types['array']->properties); $from_countable_object_like = \true; if ($atomic_root_types['array']->is_list && $array_atomic_type instanceof \Psalm\Type\Atomic\TList) { $array_atomic_type = clone $atomic_root_types['array']; $new_child_type = new \Psalm\Type\Union([$array_atomic_type]); $new_child_type->parent_nodes = $root_type->parent_nodes; } } elseif ($array_atomic_type instanceof \Psalm\Type\Atomic\TList) { $array_atomic_type = new \Psalm\Type\Atomic\TNonEmptyList($array_atomic_type->type_param); } else { $array_atomic_type = new \Psalm\Type\Atomic\TNonEmptyArray($array_atomic_type->type_params); } } } $array_assignment_type = new \Psalm\Type\Union([$array_atomic_type]); if (!$new_child_type) { $new_child_type = \Psalm\Type::combineUnionTypes($root_type, $array_assignment_type, $codebase, \true, \true); } if ($from_countable_object_like) { $atomic_root_types = $new_child_type->getAtomicTypes(); if (isset($atomic_root_types['array']) && ($atomic_root_types['array'] instanceof \Psalm\Type\Atomic\TNonEmptyArray || $atomic_root_types['array'] instanceof \Psalm\Type\Atomic\TNonEmptyList) && $atomic_root_types['array']->count !== null) { $atomic_root_types['array']->count++; } } } else { $new_child_type = $root_type; } $new_child_type->removeType('null'); if (!$root_type->hasObjectType()) { $root_type = $new_child_type; } $statements_analyzer->node_data->setType($root_array_expr, $root_type); if ($root_array_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch) { if ($root_array_expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { \Psalm\Internal\Analyzer\Statements\Expression\Assignment\InstancePropertyAssignmentAnalyzer::analyze($statements_analyzer, $root_array_expr, $root_array_expr->name->name, null, $root_type, $context, \false); } else { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $root_array_expr->name, $context) === \false) { return \false; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $root_array_expr->var, $context) === \false) { return \false; } } } elseif ($root_array_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch && $root_array_expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { \Psalm\Internal\Analyzer\Statements\Expression\Assignment\StaticPropertyAssignmentAnalyzer::analyze($statements_analyzer, $root_array_expr, null, $root_type, $context); } elseif ($root_var_id) { $context->vars_in_scope[$root_var_id] = $root_type; } if ($root_array_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $root_array_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall || $root_array_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { if ($root_type->hasArray()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArrayAssignment('Assigning to the output of a function has no effect', new \Psalm\CodeLocation($statements_analyzer->getSource(), $root_array_expr)), $statements_analyzer->getSuppressedIssues())) { // do nothing } } } return null; } /** * @param non-empty-list $key_values */ private static function updateTypeWithKeyValues(\Psalm\Codebase $codebase, \Psalm\Type\Union $child_stmt_type, \Psalm\Type\Union $current_type, array $key_values) : \Psalm\Type\Union { $has_matching_objectlike_property = \false; $has_matching_string = \false; foreach ($child_stmt_type->getAtomicTypes() as $type) { foreach ($key_values as $key_value) { if ($type instanceof \Psalm\Type\Atomic\TKeyedArray) { if (isset($type->properties[$key_value->value])) { $has_matching_objectlike_property = \true; $type->properties[$key_value->value] = clone $current_type; } } elseif ($type instanceof \Psalm\Type\Atomic\TString && $key_value instanceof \Psalm\Type\Atomic\TLiteralInt) { $has_matching_string = \true; if ($type instanceof \Psalm\Type\Atomic\TLiteralString && $current_type->isSingleStringLiteral()) { $new_char = $current_type->getSingleStringLiteral()->value; if (\strlen($new_char) === 1) { $type->value[0] = $new_char; } } } elseif ($type instanceof \Psalm\Type\Atomic\TNonEmptyList && $key_value instanceof \Psalm\Type\Atomic\TLiteralInt && \count($key_values) === 1) { $has_matching_objectlike_property = \true; $type->type_param = \Psalm\Type::combineUnionTypes(clone $current_type, $type->type_param, $codebase, \true, \false); } } } $child_stmt_type->bustCache(); if (!$has_matching_objectlike_property && !$has_matching_string) { if (\count($key_values) === 1) { $key_value = $key_values[0]; $object_like = new \Psalm\Type\Atomic\TKeyedArray([$key_value->value => clone $current_type], $key_value instanceof \Psalm\Type\Atomic\TLiteralClassString ? [(string) $key_value->value => \true] : null); $object_like->sealed = \true; $array_assignment_type = new \Psalm\Type\Union([$object_like]); } else { $array_assignment_literals = $key_values; $array_assignment_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNonEmptyArray([new \Psalm\Type\Union($array_assignment_literals), clone $current_type])]); } return \Psalm\Type::combineUnionTypes($child_stmt_type, $array_assignment_type, $codebase, \true, \false); } return $child_stmt_type; } /** * @param list $key_values $key_values */ private static function taintArrayAssignment(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch $expr, \Psalm\Type\Union $stmt_type, \Psalm\Type\Union $child_stmt_type, ?string $var_var_id, array $key_values) : void { if ($statements_analyzer->data_flow_graph && ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph || !\in_array('TaintedInput', $statements_analyzer->getSuppressedIssues()))) { if (!$stmt_type->parent_nodes) { $var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $expr->var); $parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_var_id ?: 'assignment', $var_location); $statements_analyzer->data_flow_graph->addNode($parent_node); $stmt_type->parent_nodes = [$parent_node->id => $parent_node]; } foreach ($stmt_type->parent_nodes as $parent_node) { foreach ($child_stmt_type->parent_nodes as $child_parent_node) { if ($key_values) { foreach ($key_values as $key_value) { $statements_analyzer->data_flow_graph->addPath($child_parent_node, $parent_node, 'array-assignment-\'' . $key_value->value . '\''); } } else { $statements_analyzer->data_flow_graph->addPath($child_parent_node, $parent_node, 'array-assignment'); } } } } } } getCodebase(); $property_exists = \false; $property_ids = []; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\PropertyProperty) { if (!$context->self || !$stmt->default) { return null; } $property_id = $context->self . '::$' . $prop_name; $property_ids[] = $property_id; $property_exists = \true; try { $class_property_type = $codebase->properties->getPropertyType($property_id, \true, $statements_analyzer, $context); } catch (\UnexpectedValueException $e) { return \false; } if ($class_property_type) { $class_storage = $codebase->classlike_storage_provider->get($context->self); $class_property_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, clone $class_property_type, $class_storage->name, $class_storage->name, $class_storage->parent_class); } $class_property_types[] = $class_property_type ?: \Psalm\Type::getMixed(); $var_id = '$this->' . $prop_name; } else { $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; $lhs_type = $statements_analyzer->node_data->getType($stmt->var); if ($lhs_type === null) { return null; } $lhs_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($stmt->var, $statements_analyzer->getFQCLN(), $statements_analyzer); $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($stmt, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($var_id) { $context->assigned_var_ids[$var_id] = \true; if ($direct_assignment && isset($context->protected_var_ids[$var_id])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\LoopInvalidation('Variable ' . $var_id . ' has already been assigned in a for/foreach loop', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if ($lhs_type->hasMixed()) { if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $codebase->analyzer->addMixedMemberName('$' . $stmt->name->name, $context->calling_method_id ?: $statements_analyzer->getFileName()); } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedPropertyAssignment($lhs_var_id . ' of type mixed cannot be assigned to', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var)), $statements_analyzer->getSuppressedIssues())) { return \false; } return null; } if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } if ($lhs_type->isNull()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullPropertyAssignment($lhs_var_id . ' of type null cannot be assigned to', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var)), $statements_analyzer->getSuppressedIssues())) { return \false; } return null; } if ($lhs_type->isNullable() && !$lhs_type->ignore_nullable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullPropertyAssignment($lhs_var_id . ' with possibly null type \'' . $lhs_type . '\' cannot be assigned to', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var)), $statements_analyzer->getSuppressedIssues())) { return \false; } } $has_regular_setter = \false; $invalid_assignment_types = []; $has_valid_assignment_type = \false; $lhs_atomic_types = $lhs_type->getAtomicTypes(); while ($lhs_atomic_types) { $lhs_type_part = \array_pop($lhs_atomic_types); if ($lhs_type_part instanceof \Psalm\Type\Atomic\TTemplateParam) { $lhs_atomic_types = \array_merge($lhs_atomic_types, $lhs_type_part->as->getAtomicTypes()); continue; } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TNull) { continue; } if ($lhs_type_part instanceof \Psalm\Type\Atomic\TFalse && $lhs_type->ignore_falsable_issues && \count($lhs_type->getAtomicTypes()) > 1) { continue; } if (!$lhs_type_part instanceof \Psalm\Type\Atomic\TObject && !$lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject) { $invalid_assignment_types[] = (string) $lhs_type_part; continue; } $has_valid_assignment_type = \true; // stdClass and SimpleXMLElement are special cases where we cannot infer the return types // but we don't want to throw an error // Hack has a similar issue: https://github.com/facebook/hhvm/issues/5164 if ($lhs_type_part instanceof \Psalm\Type\Atomic\TObject || \in_array(\strtolower($lhs_type_part->value), \Psalm\Config::getInstance()->getUniversalObjectCrates() + ['dateinterval', 'domdocument', 'domnode'], \true)) { if ($var_id) { if ($lhs_type_part instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($lhs_type_part->value) === 'stdclass') { $context->vars_in_scope[$var_id] = $assignment_value_type; } else { $context->vars_in_scope[$var_id] = \Psalm\Type::getMixed(); } } return null; } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::isMock($lhs_type_part->value)) { if ($var_id) { $context->vars_in_scope[$var_id] = \Psalm\Type::getMixed(); } return null; } $intersection_types = $lhs_type_part->getIntersectionTypes() ?: []; $fq_class_name = $lhs_type_part->value; $override_property_visibility = \false; $class_exists = \false; $interface_exists = \false; if (!$codebase->classExists($lhs_type_part->value)) { if ($codebase->interfaceExists($lhs_type_part->value)) { $interface_exists = \true; $interface_storage = $codebase->classlike_storage_provider->get(\strtolower($lhs_type_part->value)); $override_property_visibility = $interface_storage->override_property_visibility; foreach ($intersection_types as $intersection_type) { if ($intersection_type instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classExists($intersection_type->value)) { $fq_class_name = $intersection_type->value; $class_exists = \true; break; } } if (!$class_exists) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NoInterfaceProperties('Interfaces cannot have properties', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $lhs_type_part->value), $statements_analyzer->getSuppressedIssues())) { return null; } if (!$codebase->methods->methodExists(new \Psalm\Internal\MethodIdentifier($fq_class_name, '__set'))) { return null; } } } if (!$class_exists && !$interface_exists) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedClass('Cannot set properties of undefined class ' . $lhs_type_part->value, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $lhs_type_part->value), $statements_analyzer->getSuppressedIssues())) { // fall through } return null; } } else { $class_exists = \true; } $property_id = $fq_class_name . '::$' . $prop_name; $property_ids[] = $property_id; $has_magic_setter = \false; $set_method_id = new \Psalm\Internal\MethodIdentifier($fq_class_name, '__set'); if ((!$codebase->properties->propertyExists($property_id, \false, $statements_analyzer, $context) || $lhs_var_id !== '$this' && $fq_class_name !== $context->self && \Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkPropertyVisibility($property_id, $context, $statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues(), \false) !== \true) && $codebase->methods->methodExists($set_method_id, $context->calling_method_id, $codebase->collect_locations ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt) : null, !$context->collect_initializations && !$context->collect_mutations ? $statements_analyzer : null, $statements_analyzer->getFilePath())) { $has_magic_setter = \true; $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); if ($var_id) { if (isset($class_storage->pseudo_property_set_types['$' . $prop_name])) { $class_property_types[] = clone $class_storage->pseudo_property_set_types['$' . $prop_name]; $has_regular_setter = \true; $property_exists = \true; if (!$context->collect_initializations) { self::taintProperty($statements_analyzer, $stmt, $property_id, $class_storage, $assignment_value_type, $context); } continue; } } if ($assignment_value) { if ($var_id) { $context->removeVarFromConflictingClauses($var_id, \Psalm\Type::getMixed(), $statements_analyzer); unset($context->vars_in_scope[$var_id]); } $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($stmt->var, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('__set', $stmt->name->getAttributes()), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($prop_name, $stmt->name->getAttributes())), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($assignment_value)]); $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('PossiblyNullReference', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyNullReference']); } \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_method_call, $context, \false); if (!\in_array('PossiblyNullReference', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyNullReference']); } $statements_analyzer->node_data = $old_data_provider; } /* * If we have an explicit list of all allowed magic properties on the class, and we're * not in that list, fall through */ if (!$var_id || !$class_storage->sealed_properties) { if (!$context->collect_initializations) { self::taintProperty($statements_analyzer, $stmt, $property_id, $class_storage, $assignment_value_type, $context); } continue; } if (!$class_exists) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedMagicPropertyAssignment('Magic instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if (!$class_exists) { continue; } $has_regular_setter = \true; if ($stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $stmt->var->name === 'this' && $context->self) { $self_property_id = $context->self . '::$' . $prop_name; if ($self_property_id !== $property_id && $codebase->properties->propertyExists($self_property_id, \false, $statements_analyzer, $context)) { $property_id = $self_property_id; } } if ($statements_analyzer->data_flow_graph && !$context->collect_initializations) { $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); self::taintProperty($statements_analyzer, $stmt, $property_id, $class_storage, $assignment_value_type, $context); } if (!$codebase->properties->propertyExists($property_id, \false, $statements_analyzer, $context, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt))) { if ($stmt->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $stmt->var->name === 'this') { // if this is a proper error, we'll see it on the first pass if ($context->collect_mutations) { continue; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedThisPropertyAssignment('Instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if ($has_magic_setter) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedMagicPropertyAssignment('Magic instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedPropertyAssignment('Instance property ' . $property_id . ' is not defined', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } } continue; } if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations) { $codebase->analyzer->addNodeReference($statements_analyzer->getFilePath(), $stmt->name, $property_id); } $property_exists = \true; if (!$override_property_visibility) { if (!$context->collect_mutations) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkPropertyVisibility($property_id, $context, $statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues()) === \false) { return \false; } } else { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkPropertyVisibility($property_id, $context, $statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $statements_analyzer->getSuppressedIssues(), \false) !== \true) { continue; } } } $declaring_property_class = (string) $codebase->properties->getDeclaringClassForProperty($property_id, \false); if ($codebase->properties_to_rename) { $declaring_property_id = \strtolower($declaring_property_class) . '::$' . $prop_name; foreach ($codebase->properties_to_rename as $original_property_id => $new_property_name) { if ($declaring_property_id === $original_property_id) { $file_manipulations = [new \Psalm\FileManipulation((int) $stmt->name->getAttribute('startFilePos'), (int) $stmt->name->getAttribute('endFilePos') + 1, $new_property_name)]; \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } } $declaring_class_storage = $codebase->classlike_storage_provider->get($declaring_property_class); if (isset($declaring_class_storage->properties[$prop_name])) { $property_storage = $declaring_class_storage->properties[$prop_name]; if ($property_storage->deprecated) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedProperty($property_id . ' is marked deprecated', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($context->self && !\Psalm\Internal\Analyzer\NamespaceAnalyzer::isWithin($context->self, $property_storage->internal)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InternalProperty($property_id . ' is internal to ' . $property_storage->internal . ' but called from ' . $context->self, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $property_id), $statements_analyzer->getSuppressedIssues())) { // fall through } } self::trackPropertyImpurity($statements_analyzer, $stmt, $property_id, $property_storage, $declaring_class_storage, $context); if (!$property_storage->readonly && !$context->collect_mutations && !$context->collect_initializations && isset($context->vars_in_scope[$lhs_var_id]) && !$context->vars_in_scope[$lhs_var_id]->allow_mutations) { if ($context->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpurePropertyAssignment('Cannot assign to a property from a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_impure = \true; } } if ($property_storage->getter_method) { $getter_id = $lhs_var_id . '->' . $property_storage->getter_method . '()'; unset($context->vars_in_scope[$getter_id]); } } $class_property_type = $codebase->properties->getPropertyType($property_id, \true, $statements_analyzer, $context); if (!$class_property_type || isset($declaring_class_storage->properties[$prop_name]) && !$declaring_class_storage->properties[$prop_name]->type_location) { if (!$class_property_type) { $class_property_type = \Psalm\Type::getMixed(); } $source_analyzer = $statements_analyzer->getSource()->getSource(); if ($lhs_var_id === '$this' && $source_analyzer instanceof \Psalm\Internal\Analyzer\ClassAnalyzer) { if (isset($source_analyzer->inferred_property_types[$prop_name])) { $source_analyzer->inferred_property_types[$prop_name] = \Psalm\Type::combineUnionTypes($assignment_value_type, $source_analyzer->inferred_property_types[$prop_name]); } else { $source_analyzer->inferred_property_types[$prop_name] = $assignment_value_type; } } } if (!$class_property_type->isMixed()) { $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $class_property_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, clone $class_property_type, $fq_class_name, $lhs_type_part, $declaring_class_storage->parent_class, \true, \false, $class_storage->final); $class_property_type = \Psalm\Internal\Codebase\Methods::localizeType($codebase, $class_property_type, $fq_class_name, $declaring_property_class); if ($lhs_type_part instanceof \Psalm\Type\Atomic\TGenericObject) { $class_property_type = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\AtomicPropertyFetchAnalyzer::localizePropertyType($codebase, $class_property_type, $lhs_type_part, $class_storage, $declaring_class_storage); } $assignment_value_type = \Psalm\Internal\Codebase\Methods::localizeType($codebase, $assignment_value_type, $fq_class_name, $declaring_property_class); if (!$class_property_type->hasMixed() && $assignment_value_type->hasMixed()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedAssignment('Cannot assign' . ($var_id ? ' ' . $var_id . ' ' : ' ') . 'to a mixed type', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } $class_property_types[] = $class_property_type; } if ($invalid_assignment_types) { $invalid_assignment_type = $invalid_assignment_types[0]; if (!$has_valid_assignment_type) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidPropertyAssignment($lhs_var_id . ' with non-object type \'' . $invalid_assignment_type . '\' cannot treated as an object', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var)), $statements_analyzer->getSuppressedIssues())) { return \false; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidPropertyAssignment($lhs_var_id . ' with possible non-object type \'' . $invalid_assignment_type . '\' cannot treated as an object', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var)), $statements_analyzer->getSuppressedIssues())) { return \false; } } } if (!$has_regular_setter) { return null; } if ($var_id) { if ($context->collect_initializations && $lhs_var_id === '$this') { $assignment_value_type->initialized_class = $context->self; } // because we don't want to be assigning for property declarations $context->vars_in_scope[$var_id] = $assignment_value_type; } } if (!$property_exists) { return null; } if ($assignment_value_type->hasMixed()) { return null; } $invalid_assignment_value_types = []; $has_valid_assignment_value_type = \false; if ($codebase->store_node_types && !$context->collect_initializations && !$context->collect_mutations && \count($class_property_types) === 1) { $codebase->analyzer->addNodeType($statements_analyzer->getFilePath(), $stmt->name, $class_property_types[0]->getId()); } foreach ($class_property_types as $class_property_type) { if ($class_property_type->hasMixed()) { continue; } $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); $type_match_found = \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $assignment_value_type, $class_property_type, \true, \true, $union_comparison_results); if ($type_match_found && $union_comparison_results->replacement_union_type) { if ($var_id) { $context->vars_in_scope[$var_id] = $union_comparison_results->replacement_union_type; } } if ($union_comparison_results->type_coerced) { if ($union_comparison_results->type_coerced_from_mixed) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedPropertyTypeCoercion($var_id . ' expects \'' . $class_property_type->getId() . '\', ' . ' parent type `' . $assignment_value_type->getId() . '` provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location), $property_ids[0]), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PropertyTypeCoercion($var_id . ' expects \'' . $class_property_type->getId() . '\', ' . ' parent type \'' . $assignment_value_type->getId() . '\' provided', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location), $property_ids[0]), $statements_analyzer->getSuppressedIssues())) { // keep soldiering on } } } if ($union_comparison_results->to_string_cast) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImplicitToStringCast($var_id . ' expects \'' . $class_property_type . '\', ' . '\'' . $assignment_value_type . '\' provided with a __toString method', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if (!$type_match_found && !$union_comparison_results->type_coerced) { if (\Psalm\Internal\Type\Comparator\UnionTypeComparator::canBeContainedBy($codebase, $assignment_value_type, $class_property_type, \true, \true)) { $has_valid_assignment_value_type = \true; } $invalid_assignment_value_types[] = $class_property_type->getId(); } else { $has_valid_assignment_value_type = \true; } if ($type_match_found) { if (!$assignment_value_type->ignore_nullable_issues && $assignment_value_type->isNullable() && !$class_property_type->isNullable()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullPropertyAssignmentValue($var_id . ' with non-nullable declared type \'' . $class_property_type . '\' cannot be assigned nullable type \'' . $assignment_value_type . '\'', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location), $property_ids[0]), $statements_analyzer->getSuppressedIssues())) { return \false; } } if (!$assignment_value_type->ignore_falsable_issues && $assignment_value_type->isFalsable() && !$class_property_type->hasBool() && !$class_property_type->hasScalar()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyFalsePropertyAssignmentValue($var_id . ' with non-falsable declared type \'' . $class_property_type . '\' cannot be assigned possibly false type \'' . $assignment_value_type . '\'', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location), $property_ids[0]), $statements_analyzer->getSuppressedIssues())) { return \false; } } } } if ($invalid_assignment_value_types) { $invalid_class_property_type = $invalid_assignment_value_types[0]; if (!$has_valid_assignment_value_type) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidPropertyAssignmentValue($var_id . ' with declared type \'' . $invalid_class_property_type . '\' cannot be assigned type \'' . $assignment_value_type->getId() . '\'', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location), $property_ids[0]), $statements_analyzer->getSuppressedIssues())) { return \false; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidPropertyAssignmentValue($var_id . ' with declared type \'' . $invalid_class_property_type . '\' cannot be assigned possibly different type \'' . $assignment_value_type->getId() . '\'', new \Psalm\CodeLocation($statements_analyzer->getSource(), $assignment_value ?: $stmt, $context->include_location), $property_ids[0]), $statements_analyzer->getSuppressedIssues())) { return \false; } } } return null; } public static function trackPropertyImpurity(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch $stmt, string $property_id, \Psalm\Storage\PropertyStorage $property_storage, \Psalm\Storage\ClassLikeStorage $declaring_class_storage, \Psalm\Context $context) : void { $codebase = $statements_analyzer->getCodebase(); $stmt_var_type = $statements_analyzer->node_data->getType($stmt->var); $property_var_pure_compatible = $stmt_var_type && $stmt_var_type->reference_free && $stmt_var_type->allow_mutations; $appearing_property_class = $codebase->properties->getAppearingClassForProperty($property_id, \true); $project_analyzer = $statements_analyzer->getProjectAnalyzer(); if ($appearing_property_class && ($property_storage->readonly || $codebase->alter_code)) { $can_set_readonly_property = $context->self && $context->calling_method_id && ($appearing_property_class === $context->self || $codebase->classExtends($context->self, $appearing_property_class)) && (\strpos($context->calling_method_id, '::__construct') || \strpos($context->calling_method_id, '::unserialize') || \strpos($context->calling_method_id, '::__unserialize') || \strpos($context->calling_method_id, '::__clone') || $property_storage->allow_private_mutation || $property_var_pure_compatible); if (!$can_set_readonly_property) { if ($property_storage->readonly) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleProperty($property_id . ' is marked readonly', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif (!$declaring_class_storage->mutation_free && isset($project_analyzer->getIssuesToFix()['MissingImmutableAnnotation']) && $statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer) { $codebase->analyzer->addMutableClass($declaring_class_storage->name); } } } } public static function analyzeStatement(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property $stmt, \Psalm\Context $context) : void { foreach ($stmt->props as $prop) { if ($prop->default) { \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $prop->default, $context); if ($prop_default_type = $statements_analyzer->node_data->getType($prop->default)) { if (self::analyze($statements_analyzer, $prop, $prop->name->name, $prop->default, $prop_default_type, $context) === \false) { // fall through } } } } } private static function taintProperty(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch $stmt, string $property_id, \Psalm\Storage\ClassLikeStorage $class_storage, \Psalm\Type\Union $assignment_value_type, \Psalm\Context $context) : void { if (!$statements_analyzer->data_flow_graph) { return; } $data_flow_graph = $statements_analyzer->data_flow_graph; $var_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->var); $property_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); if ($class_storage->specialize_instance) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->var, null, $statements_analyzer); $var_property_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt, null, $statements_analyzer); if ($var_id) { if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $context->vars_in_scope[$var_id]->parent_nodes = []; return; } $var_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_id, $var_location); $data_flow_graph->addNode($var_node); $property_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_property_id ?: $var_id . '->$property', $property_location); $data_flow_graph->addNode($property_node); $data_flow_graph->addPath($property_node, $var_node, 'property-assignment' . ($stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier ? '-' . $stmt->name : '')); if ($assignment_value_type->parent_nodes) { foreach ($assignment_value_type->parent_nodes as $parent_node) { $data_flow_graph->addPath($parent_node, $property_node, '='); } } $stmt_var_type = clone $context->vars_in_scope[$var_id]; if ($context->vars_in_scope[$var_id]->parent_nodes) { foreach ($context->vars_in_scope[$var_id]->parent_nodes as $parent_node) { $data_flow_graph->addPath($parent_node, $var_node, '='); } } $stmt_var_type->parent_nodes = [$var_node->id => $var_node]; $context->vars_in_scope[$var_id] = $stmt_var_type; } } else { if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && \in_array('TaintedInput', $statements_analyzer->getSuppressedIssues())) { $assignment_value_type->parent_nodes = []; return; } $code_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $localized_property_node = new \Psalm\Internal\DataFlow\DataFlowNode($property_id . '-' . $code_location->file_name . ':' . $code_location->raw_file_start, $property_id, $code_location, null); $data_flow_graph->addNode($localized_property_node); $property_node = new \Psalm\Internal\DataFlow\DataFlowNode($property_id, $property_id, null, null); $data_flow_graph->addNode($property_node); $data_flow_graph->addPath($localized_property_node, $property_node, 'property-assignment'); if ($assignment_value_type->parent_nodes) { foreach ($assignment_value_type->parent_nodes as $parent_node) { $data_flow_graph->addPath($parent_node, $localized_property_node, '='); } } } } } expr, $context) === \false) { return \false; } $as_int = \true; $maybe_type = $statements_analyzer->node_data->getType($stmt->expr); if ($maybe_type) { $maybe = $maybe_type->getAtomicTypes(); if (\count($maybe) === 1 && \current($maybe) instanceof \Psalm\Type\Atomic\TBool) { $as_int = \false; $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TLiteralInt(0), new \Psalm\Type\Atomic\TLiteralInt(1)])); } } if ($as_int) { $type = \Psalm\Type::getInt(); if ($statements_analyzer->data_flow_graph && $statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph) { $type->parent_nodes = $maybe_type ? $maybe_type->parent_nodes : []; } $statements_analyzer->node_data->setType($stmt, $type); } return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Double) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getFloat()); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Bool_) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getBool()); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\String_) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr); if ($stmt_expr_type) { $stmt_type = self::castStringAttempt($statements_analyzer, $context, $stmt_expr_type, $stmt->expr, \true); } else { $stmt_type = \Psalm\Type::getString(); } $statements_analyzer->node_data->setType($stmt, $stmt_type); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Object_) { $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; $statements_analyzer->node_data->setType($stmt, new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject('stdClass')])); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Array_) { $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; $permissible_atomic_types = []; $all_permissible = \false; if ($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr)) { $all_permissible = \true; foreach ($stmt_expr_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\Scalar) { $permissible_atomic_types[] = new \Psalm\Type\Atomic\TKeyedArray([new \Psalm\Type\Union([$type])]); } elseif ($type instanceof \Psalm\Type\Atomic\TNull) { $permissible_atomic_types[] = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getEmpty(), \Psalm\Type::getEmpty()]); } elseif ($type instanceof \Psalm\Type\Atomic\TArray || $type instanceof \Psalm\Type\Atomic\TList || $type instanceof \Psalm\Type\Atomic\TKeyedArray) { $permissible_atomic_types[] = clone $type; } else { $all_permissible = \false; break; } } } if ($permissible_atomic_types && $all_permissible) { $statements_analyzer->node_data->setType($stmt, \Psalm\Internal\Type\TypeCombination::combineTypes($permissible_atomic_types)); } else { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getArray()); } return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Unset_ && $statements_analyzer->getCodebase()->php_major_version < 8) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getNull()); return \true; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnrecognizedExpression('Psalm does not understand the cast ' . \get_class($stmt), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } return \false; } public static function castStringAttempt(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Context $context, \Psalm\Type\Union $stmt_type, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, bool $explicit_cast = \false) : \Psalm\Type\Union { $codebase = $statements_analyzer->getCodebase(); $invalid_casts = []; $valid_strings = []; $castable_types = []; $atomic_types = $stmt_type->getAtomicTypes(); $parent_nodes = []; if ($statements_analyzer->data_flow_graph) { $parent_nodes = $stmt_type->parent_nodes; } while ($atomic_types) { $atomic_type = \array_pop($atomic_types); if ($atomic_type instanceof \Psalm\Type\Atomic\TFloat || $atomic_type instanceof \Psalm\Type\Atomic\TInt || $atomic_type instanceof \Psalm\Type\Atomic\TNumeric) { $castable_types[] = new \Psalm\Type\Atomic\TNumericString(); continue; } if ($atomic_type instanceof \Psalm\Type\Atomic\TString) { $valid_strings[] = $atomic_type; continue; } if ($atomic_type instanceof \Psalm\Type\Atomic\TNull || $atomic_type instanceof \Psalm\Type\Atomic\TFalse) { $valid_strings[] = new \Psalm\Type\Atomic\TLiteralString(''); continue; } if ($atomic_type instanceof \Psalm\Type\Atomic\TMixed || $atomic_type instanceof \Psalm\Type\Atomic\TResource || $atomic_type instanceof \Psalm\Type\Atomic\Scalar) { $castable_types[] = new \Psalm\Type\Atomic\TString(); continue; } if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject || $atomic_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { $intersection_types = [$atomic_type]; if ($atomic_type->extra_types) { $intersection_types = \array_merge($intersection_types, $atomic_type->extra_types); } foreach ($intersection_types as $intersection_type) { if ($intersection_type instanceof \Psalm\Type\Atomic\TNamedObject) { $intersection_method_id = new \Psalm\Internal\MethodIdentifier($intersection_type->value, '__tostring'); if ($codebase->methods->methodExists($intersection_method_id, $context->calling_method_id, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt))) { $return_type = $codebase->methods->getMethodReturnType($intersection_method_id, $self_class) ?: \Psalm\Type::getString(); $declaring_method_id = $codebase->methods->getDeclaringMethodId($intersection_method_id); \Psalm\Internal\Analyzer\Statements\Expression\Call\Method\MethodCallReturnTypeFetcher::taintMethodCallResult($statements_analyzer, $return_type, $stmt, $stmt, $intersection_method_id, $declaring_method_id, $intersection_type->value . '::__toString', $context); if ($statements_analyzer->data_flow_graph) { $parent_nodes = \array_merge($return_type->parent_nodes, $parent_nodes); } $castable_types = \array_merge($castable_types, \array_values($return_type->getAtomicTypes())); continue 2; } } if ($intersection_type instanceof \Psalm\Type\Atomic\TObjectWithProperties && isset($intersection_type->methods['__toString'])) { $castable_types[] = new \Psalm\Type\Atomic\TString(); continue 2; } } } if ($atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $atomic_types = \array_merge($atomic_types, $atomic_type->as->getAtomicTypes()); continue; } $invalid_casts[] = $atomic_type->getId(); } if ($invalid_casts) { if ($valid_strings || $castable_types) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidCast($invalid_casts[0] . ' cannot be cast to string', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidCast($invalid_casts[0] . ' cannot be cast to string', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } elseif ($explicit_cast && !$castable_types) { // todo: emit error here } $valid_types = \array_merge($valid_strings, $castable_types); if (!$valid_types) { $str_type = \Psalm\Type::getString(); } else { $str_type = \Psalm\Internal\Type\TypeCombination::combineTypes($valid_types, $codebase); } if ($statements_analyzer->data_flow_graph) { $str_type->parent_nodes = $parent_nodes; } return $str_type; } } inside_call; $context->inside_call = \true; $was_inside_conditional = $context->inside_conditional; $context->inside_conditional = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->cond, $context) === \false) { $context->inside_conditional = $was_inside_conditional; return \false; } $context->inside_conditional = $was_inside_conditional; $switch_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->cond, null, $statements_analyzer); $match_condition = $stmt->cond; if (!$switch_var_id && ($stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall)) { $switch_var_id = '$__tmp_switch__' . (int) $stmt->cond->getAttribute('startFilePos'); $condition_type = $statements_analyzer->node_data->getType($stmt->cond) ?: \Psalm\Type::getMixed(); $context->vars_in_scope[$switch_var_id] = $condition_type; $match_condition = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable(\substr($switch_var_id, 1), $stmt->cond->getAttributes()); } $arms = $stmt->arms; foreach ($arms as $i => $arm) { // move default to the end if ($arm->conds === null) { unset($arms[$i]); $arms[] = $arm; } } $arms = \array_reverse($arms); $last_arm = \array_shift($arms); $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; if (!$last_arm->conds) { $ternary = $last_arm->body; } else { $ternary = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary(self::convertCondsToConditional($last_arm->conds, $match_condition, $last_arm->getAttributes()), $last_arm->body, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Throw_(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified('UnhandledMatchError')))); } foreach ($arms as $arm) { if (!$arm->conds) { continue; } $ternary = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary(self::convertCondsToConditional($arm->conds, $match_condition, $arm->getAttributes()), $arm->body, $ternary, $arm->getAttributes()); } $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantConditionGivenDocblockType']); } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $ternary, $context) === \false) { return \false; } if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantConditionGivenDocblockType']); } if ($switch_var_id && $last_arm->conds) { $codebase = $statements_analyzer->getCodebase(); $all_conds = $last_arm->conds; foreach ($arms as $arm) { if (!$arm->conds) { throw new \UnexpectedValueException('bad'); } $all_conds = \array_merge($arm->conds, $all_conds); } $all_match_condition = self::convertCondsToConditional(\array_values($all_conds), $match_condition, $match_condition->getAttributes()); \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $all_match_condition, $context); $clauses = \Psalm\Type\Algebra::getFormula(\spl_object_id($all_match_condition), \spl_object_id($all_match_condition), $all_match_condition, $context->self, $statements_analyzer, $codebase, \false, \false); $reconcilable_types = \Psalm\Type\Algebra::getTruthsFromFormula(\Psalm\Type\Algebra::negateFormula($clauses)); // if the if has an || in the conditional, we cannot easily reason about it if ($reconcilable_types) { $changed_var_ids = []; $vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($reconcilable_types, [], $context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, [], $context->inside_loop, null); if (isset($vars_in_scope_reconciled[$switch_var_id])) { if ($vars_in_scope_reconciled[$switch_var_id]->hasLiteralValue()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnhandledMatchCondition('This match expression is not exhaustive - consider values ' . $vars_in_scope_reconciled[$switch_var_id]->getId(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $match_condition)), $statements_analyzer->getSuppressedIssues())) { // continue } } } } } $stmt_expr_type = $statements_analyzer->node_data->getType($ternary); $old_node_data->setType($stmt, $stmt_expr_type ?: \Psalm\Type::getMixed()); $statements_analyzer->node_data = $old_node_data; $context->inside_call = $was_inside_call; return \true; } /** * @param non-empty-list $conds */ private static function convertCondsToConditional(array $conds, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $match_condition, array $attributes) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr { if (\count($conds) === 1) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical($match_condition, $conds[0], $attributes); } $array_items = \array_map(function ($cond) : PhpParser\Node\Expr\ArrayItem { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($cond, null, \false, $cond->getAttributes()); }, $conds); return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified(['in_array']), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($match_condition), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($array_items)), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified(['true'])))], $attributes); } } expr, $context); if (($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr)) && $stmt_expr_type->hasBool() && $stmt_expr_type->isSingle() && !$stmt_expr_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidArgument('Calling empty on a boolean value is almost certainly unintended', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr), 'empty'), $statements_analyzer->getSuppressedIssues())) { // fall through } } $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getBool()); } } getCodebase(); if ($context->mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureStaticVariable('Cannot use a static variable in a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } foreach ($stmt->vars as $var) { if (!\is_string($var->var->name)) { continue; } $var_id = '$' . $var->var->name; $doc_comment = $stmt->getDocComment(); $comment_type = null; if ($doc_comment && ($parsed_docblock = $statements_analyzer->getParsedDocblock())) { $var_comments = []; try { $var_comments = \Psalm\Internal\Analyzer\CommentAnalyzer::arrayToDocblocks($doc_comment, $parsed_docblock, $statements_analyzer->getSource(), $statements_analyzer->getSource()->getAliases(), $statements_analyzer->getSource()->getTemplateTypeMap()); } catch (\Psalm\Exception\IncorrectDocblockException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingDocblockType((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer, $var)))) { // fall through } } catch (\Psalm\Exception\DocblockParseException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $var)))) { // fall through } } foreach ($var_comments as $var_comment) { if (!$var_comment->type) { continue; } try { $var_comment_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $var_comment->type, $context->self, $context->self, $statements_analyzer->getParentFQCLN()); $var_comment_type->setFromDocblock(); $var_comment_type->check($statements_analyzer, new \Psalm\CodeLocation($statements_analyzer->getSource(), $var), $statements_analyzer->getSuppressedIssues()); if ($codebase->alter_code && $var_comment->type_start && $var_comment->type_end && $var_comment->line_number) { $type_location = new \Psalm\CodeLocation\DocblockTypeLocation($statements_analyzer, $var_comment->type_start, $var_comment->type_end, $var_comment->line_number); $codebase->classlikes->handleDocblockTypeInMigration($codebase, $statements_analyzer, $var_comment_type, $type_location, $context->calling_method_id); } if (!$var_comment->var_id || $var_comment->var_id === $var_id) { $comment_type = $var_comment_type; continue; } $context->vars_in_scope[$var_comment->var_id] = $var_comment_type; } catch (\UnexpectedValueException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer, $var)))) { // fall through } } } if ($comment_type) { $context->byref_constraints[$var_id] = new \Psalm\Internal\ReferenceConstraint($comment_type); } } if ($var->default) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $var->default, $context) === \false) { return \false; } if ($comment_type && ($var_default_type = $statements_analyzer->node_data->getType($var->default)) && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $var_default_type, $comment_type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ReferenceConstraintViolation($var_id . ' of type ' . $comment_type->getId() . ' cannot be assigned type ' . $var_default_type->getId(), new \Psalm\CodeLocation($statements_analyzer, $var)))) { // fall through } } } if ($context->check_variables) { $context->vars_in_scope[$var_id] = $comment_type ? clone $comment_type : \Psalm\Type::getMixed(); $context->vars_possibly_in_scope[$var_id] = \true; $context->assigned_var_ids[$var_id] = \true; $statements_analyzer->byref_uses[$var_id] = \true; $location = new \Psalm\CodeLocation($statements_analyzer, $var); $statements_analyzer->registerVariable($var_id, $location, $context->branch_point); } } return null; } } getCodebase(); if (self::handleExpression($statements_analyzer, $stmt, $context, $array_assignment, $global_context, $from_stmt) === \false) { return \false; } if (!$context->inside_conditional && ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Empty_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Isset_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall)) { $assertions = $statements_analyzer->node_data->getAssertions($stmt); if ($assertions === null) { \Psalm\Internal\Analyzer\Statements\Expression\AssertionFinder::scrapeAssertions($stmt, $context->self, $statements_analyzer, $codebase, \false, \true, \false); } } $plugin_classes = $codebase->config->after_expression_checks; if ($plugin_classes) { $file_manipulations = []; foreach ($plugin_classes as $plugin_fq_class_name) { if ($plugin_fq_class_name::afterExpressionAnalysis($stmt, $context, $statements_analyzer, $codebase, $file_manipulations) === \false) { return \false; } } if ($file_manipulations) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } return \true; } private static function handleExpression(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, \Psalm\Context $context, bool $array_assignment, ?\Psalm\Context $global_context, bool $from_stmt) : bool { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { return \Psalm\Internal\Analyzer\Statements\Expression\Fetch\VariableFetchAnalyzer::analyze($statements_analyzer, $stmt, $context, \false, null, $array_assignment); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { $assignment_type = \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::analyze($statements_analyzer, $stmt->var, $stmt->expr, null, $context, $stmt->getDocComment()); if ($assignment_type === \false) { return \false; } if (!$from_stmt) { $statements_analyzer->node_data->setType($stmt, $assignment_type); } return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp) { return \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::analyzeAssignmentOperation($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall) { return \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall) { return \Psalm\Internal\Analyzer\Statements\Expression\Call\StaticCallAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::analyze($statements_analyzer, $stmt, $context); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getString($stmt->value)); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\EncapsedStringPart) { return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst) { \Psalm\Internal\Analyzer\Statements\Expression\MagicConstAnalyzer::analyze($statements_analyzer, $stmt, $context); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getInt(\false, $stmt->value)); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getFloat($stmt->value)); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryMinus || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\UnaryPlus) { return \Psalm\Internal\Analyzer\Statements\Expression\UnaryPlusMinusAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Isset_) { \Psalm\Internal\Analyzer\Statements\Expression\IssetAnalyzer::analyze($statements_analyzer, $stmt, $context); $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getBool()); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch) { return \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ClassConstFetchAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch) { return \Psalm\Internal\Analyzer\Statements\Expression\Fetch\InstancePropertyFetchAnalyzer::analyze($statements_analyzer, $stmt, $context, $array_assignment); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch) { return \Psalm\Internal\Analyzer\Statements\Expression\Fetch\StaticPropertyFetchAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BitwiseNot) { return \Psalm\Internal\Analyzer\Statements\Expression\BitwiseNotAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp) { return \Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::analyze($statements_analyzer, $stmt, $context, 0, $from_stmt); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec) { \Psalm\Internal\Analyzer\Statements\Expression\IncDecExpressionAnalyzer::analyze($statements_analyzer, $stmt, $context); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_) { return \Psalm\Internal\Analyzer\Statements\Expression\Call\NewAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_) { return \Psalm\Internal\Analyzer\Statements\Expression\ArrayAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\Encapsed) { return \Psalm\Internal\Analyzer\Statements\Expression\EncapsulatedStringAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { return \Psalm\Internal\Analyzer\Statements\Expression\Call\FunctionCallAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary) { return \Psalm\Internal\Analyzer\Statements\Expression\TernaryAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot) { return \Psalm\Internal\Analyzer\Statements\Expression\BooleanNotAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Empty_) { \Psalm\Internal\Analyzer\Statements\Expression\EmptyAnalyzer::analyze($statements_analyzer, $stmt, $context); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { \Psalm\Internal\Analyzer\ClosureAnalyzer::analyzeExpression($statements_analyzer, $stmt, $context); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch) { return \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast) { return \Psalm\Internal\Analyzer\Statements\Expression\CastAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Clone_) { return \Psalm\Internal\Analyzer\Statements\Expression\CloneAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_) { return \Psalm\Internal\Analyzer\Statements\Expression\InstanceofAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_) { return \Psalm\Internal\Analyzer\Statements\Expression\ExitAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_) { return \Psalm\Internal\Analyzer\Statements\Expression\IncludeAnalyzer::analyze($statements_analyzer, $stmt, $context, $global_context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Eval_) { \Psalm\Internal\Analyzer\Statements\Expression\EvalAnalyzer::analyze($statements_analyzer, $stmt, $context); return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef) { return \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::analyzeAssignmentRef($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ErrorSuppress) { $context->error_suppressing = \true; if (self::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $context->error_suppressing = \false; $expr_type = $statements_analyzer->node_data->getType($stmt->expr); if ($expr_type) { $statements_analyzer->node_data->setType($stmt, $expr_type); } return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ShellExec) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ForbiddenCode('Use of shell_exec', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // continue } return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Print_) { $was_inside_call = $context->inside_call; $context->inside_call = \true; if (\Psalm\Internal\Analyzer\Statements\Expression\PrintAnalyzer::analyze($statements_analyzer, $stmt, $context) === \false) { return \false; } $context->inside_call = $was_inside_call; return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_) { return \Psalm\Internal\Analyzer\Statements\Expression\YieldAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom) { return \Psalm\Internal\Analyzer\Statements\Expression\YieldFromAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Match_ && $statements_analyzer->getCodebase()->php_major_version >= 8) { return \Psalm\Internal\Analyzer\Statements\Expression\MatchAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Throw_ && $statements_analyzer->getCodebase()->php_major_version >= 8) { return \Psalm\Internal\Analyzer\Statements\ThrowAnalyzer::analyze($statements_analyzer, $stmt, $context); } if (($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafePropertyFetch || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\NullsafeMethodCall) && $statements_analyzer->getCodebase()->php_major_version >= 8) { return \Psalm\Internal\Analyzer\Statements\Expression\NullsafeAnalyzer::analyze($statements_analyzer, $stmt, $context); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error) { // do nothing return \true; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnrecognizedExpression('Psalm does not understand ' . \get_class($stmt), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } return \false; } public static function isMock(string $fq_class_name) : bool { return \in_array(\strtolower($fq_class_name), \Psalm\Config::getInstance()->getMockClasses(), \true); } } loop_scope; $leaving_switch = \true; if ($loop_scope) { if ($context->break_types && \end($context->break_types) === 'switch' && (!$stmt->num || !$stmt->num instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || $stmt->num->value < 2)) { $loop_scope->final_actions[] = \Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_LEAVE_SWITCH; } else { $leaving_switch = \false; $loop_scope->final_actions[] = \Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK; } $redefined_vars = $context->getRedefinedVars($loop_scope->loop_parent_context->vars_in_scope); if ($loop_scope->possibly_redefined_loop_parent_vars === null) { $loop_scope->possibly_redefined_loop_parent_vars = $redefined_vars; } else { foreach ($redefined_vars as $var => $type) { if ($type->hasMixed()) { if (isset($loop_scope->possibly_redefined_loop_parent_vars[$var])) { $type->parent_nodes += $loop_scope->possibly_redefined_loop_parent_vars[$var]->parent_nodes; } $loop_scope->possibly_redefined_loop_parent_vars[$var] = $type; } elseif (isset($loop_scope->possibly_redefined_loop_parent_vars[$var])) { $loop_scope->possibly_redefined_loop_parent_vars[$var] = \Psalm\Type::combineUnionTypes($type, $loop_scope->possibly_redefined_loop_parent_vars[$var]); } else { $loop_scope->possibly_redefined_loop_parent_vars[$var] = $type; } } } if ($loop_scope->iteration_count === 0) { foreach ($context->vars_in_scope as $var_id => $type) { if (!isset($loop_scope->loop_parent_context->vars_in_scope[$var_id])) { if (isset($loop_scope->possibly_defined_loop_parent_vars[$var_id])) { $loop_scope->possibly_defined_loop_parent_vars[$var_id] = \Psalm\Type::combineUnionTypes($type, $loop_scope->possibly_defined_loop_parent_vars[$var_id]); } else { $loop_scope->possibly_defined_loop_parent_vars[$var_id] = $type; } } } } if ($context->finally_scope) { foreach ($context->vars_in_scope as $var_id => $type) { if (isset($context->finally_scope->vars_in_scope[$var_id])) { if ($context->finally_scope->vars_in_scope[$var_id] !== $type) { $context->finally_scope->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->finally_scope->vars_in_scope[$var_id], $type, $statements_analyzer->getCodebase()); } } else { $context->finally_scope->vars_in_scope[$var_id] = $type; } } } } $case_scope = $context->case_scope; if ($case_scope && $leaving_switch) { foreach ($context->vars_in_scope as $var_id => $type) { if ($case_scope->parent_context !== $context) { if ($case_scope->break_vars === null) { $case_scope->break_vars = []; } if (isset($case_scope->break_vars[$var_id])) { $case_scope->break_vars[$var_id] = \Psalm\Type::combineUnionTypes($type, $case_scope->break_vars[$var_id]); } else { $case_scope->break_vars[$var_id] = $type; } } } } $context->has_returned = \true; } } getCodebase(); foreach ($stmt->exprs as $i => $expr) { $context->inside_call = \true; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $expr, $context); $context->inside_call = \false; $expr_type = $statements_analyzer->node_data->getType($expr); if ($statements_analyzer->data_flow_graph && $expr_type) { $expr_type = \Psalm\Internal\Analyzer\Statements\Expression\CastAnalyzer::castStringAttempt($statements_analyzer, $context, $expr_type, $expr, \false); } if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph) { $call_location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt); $echo_param_sink = \Psalm\Internal\DataFlow\TaintSink::getForMethodArgument('echo', 'echo', (int) $i, null, $call_location); $echo_param_sink->taints = [\Psalm\Type\TaintKind::INPUT_HTML, \Psalm\Type\TaintKind::USER_SECRET, \Psalm\Type\TaintKind::SYSTEM_SECRET]; $statements_analyzer->data_flow_graph->addSink($echo_param_sink); } if ($expr_type) { if (\Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentAnalyzer::verifyType($statements_analyzer, $expr_type, \Psalm\Type::getString(), null, 'echo', (int) $i, new \Psalm\CodeLocation($statements_analyzer->getSource(), $expr), $expr, $context, $echo_param, \false, null, \true, \true, new \Psalm\CodeLocation($statements_analyzer, $stmt)) === \false) { return \false; } } } if ($codebase->config->forbid_echo) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ForbiddenEcho('Use of echo', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSource()->getSuppressedIssues())) { return \false; } } elseif (isset($codebase->config->forbidden_functions['echo'])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ForbiddenCode('Use of echo', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSource()->getSuppressedIssues())) { // continue } } if (!$context->collect_initializations && !$context->collect_mutations) { if ($context->mutation_free || $context->external_mutation_free) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureFunctionCall('Cannot call echo from a mutation-free context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } elseif ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } } return \true; } } loop_scope; if ($loop_scope === null) { if (!$context->break_types) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ContinueOutsideLoop('Continue call outside loop context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSource()->getSuppressedIssues())) { return \false; } } } else { if ($context->break_types && \end($context->break_types) === 'switch' && (!$stmt->num || !$stmt->num instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || $stmt->num->value < 2)) { $loop_scope->final_actions[] = \Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_LEAVE_SWITCH; } else { $loop_scope->final_actions[] = \Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE; } $redefined_vars = $context->getRedefinedVars($loop_scope->loop_parent_context->vars_in_scope); if ($loop_scope->redefined_loop_vars === null) { $loop_scope->redefined_loop_vars = $redefined_vars; } else { foreach ($loop_scope->redefined_loop_vars as $redefined_var => $type) { if (!isset($redefined_vars[$redefined_var])) { unset($loop_scope->redefined_loop_vars[$redefined_var]); } else { $loop_scope->redefined_loop_vars[$redefined_var] = \Psalm\Type::combineUnionTypes($redefined_vars[$redefined_var], $type); } } } foreach ($redefined_vars as $var => $type) { if ($type->hasMixed()) { if (isset($loop_scope->possibly_redefined_loop_vars[$var])) { $type->parent_nodes += $loop_scope->possibly_redefined_loop_vars[$var]->parent_nodes; } $loop_scope->possibly_redefined_loop_vars[$var] = $type; } elseif (isset($loop_scope->possibly_redefined_loop_vars[$var])) { $loop_scope->possibly_redefined_loop_vars[$var] = \Psalm\Type::combineUnionTypes($type, $loop_scope->possibly_redefined_loop_vars[$var]); } else { $loop_scope->possibly_redefined_loop_vars[$var] = $type; } } if ($context->finally_scope) { foreach ($context->vars_in_scope as $var_id => $type) { if (isset($context->finally_scope->vars_in_scope[$var_id])) { if ($context->finally_scope->vars_in_scope[$var_id] !== $type) { $context->finally_scope->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->finally_scope->vars_in_scope[$var_id], $type, $statements_analyzer->getCodebase()); } } else { $context->finally_scope->vars_in_scope[$var_id] = $type; } } } } $context->has_returned = \true; return null; } } */ private $removed_unref_vars = []; /** * @param array $stmts * @param array $var_loc_map * */ public function findUnusedAssignment(\Psalm\Codebase $codebase, array $stmts, array $var_loc_map, string $var_id, \Psalm\CodeLocation $original_location) : void { $search_result = $this->findAssignStmt($stmts, $var_id, $original_location); [$assign_stmt, $assign_exp] = $search_result; $chain_assignment = \false; if ($assign_stmt !== null && $assign_exp !== null) { // Check if we have to remove assignment statemnt as expression (i.e. just "$var = ") // Consider chain of assignments $rhs_exp = $assign_exp->expr; if ($rhs_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign || $rhs_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp || $rhs_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef) { $chain_assignment = \true; $removable_stmt = $this->checkRemovableChainAssignment($assign_exp, $var_loc_map); } else { $removable_stmt = \true; } if ($removable_stmt) { $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $visitor = new \Psalm\Internal\PhpVisitor\CheckTrivialExprVisitor(); $traverser->addVisitor($visitor); $traverser->traverse([$rhs_exp]); $rhs_exp_trivial = \count($visitor->getNonTrivialExpr()) === 0; if ($rhs_exp_trivial) { $treat_as_expr = \false; } else { $treat_as_expr = \true; } } else { $treat_as_expr = \true; } if ($treat_as_expr) { $is_assign_ref = $assign_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef; $new_file_manipulation = self::getPartialRemovalBounds($codebase, $original_location, $assign_stmt->getEndFilePos(), $is_assign_ref); $this->removed_unref_vars[$var_id] = $original_location; } else { // Remove whole assignment statement $new_file_manipulation = new \Psalm\FileManipulation($assign_stmt->getStartFilePos(), $assign_stmt->getEndFilePos() + 1, "", \false, \true); // If statement we are removing is a chain of assignments, mark other variables as removed if ($chain_assignment) { $this->markRemovedChainAssignVar($assign_exp, $var_loc_map); } else { $this->removed_unref_vars[$var_id] = $original_location; } } \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($original_location->file_path, [$new_file_manipulation]); } elseif ($assign_exp !== null) { $is_assign_ref = $assign_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef; $new_file_manipulation = self::getPartialRemovalBounds($codebase, $original_location, $assign_exp->getEndFilePos(), $is_assign_ref); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($original_location->file_path, [$new_file_manipulation]); $this->removed_unref_vars[$var_id] = $original_location; } } private static function getPartialRemovalBounds(\Psalm\Codebase $codebase, \Psalm\CodeLocation $var_loc, int $end_bound, bool $assign_ref = \false) : \Psalm\FileManipulation { $var_start_loc = $var_loc->raw_file_start; $stmt_content = $codebase->file_provider->getContents($var_loc->file_path); $str_for_token = " $var_loc_map */ private function markRemovedChainAssignVar(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $cur_assign, array $var_loc_map) : void { $var = $cur_assign->var; if ($var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($var->name)) { $var_name = "\$" . $var->name; $var_loc = $var_loc_map[$var_name]; $this->removed_unref_vars[$var_name] = $var_loc; $rhs_exp = $cur_assign->expr; if ($rhs_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign || $rhs_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp || $rhs_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef) { $this->markRemovedChainAssignVar($rhs_exp, $var_loc_map); } } } /** * @param PhpParser\Node\Expr\Assign|PhpParser\Node\Expr\AssignOp|PhpParser\Node\Expr\AssignRef $cur_assign * @param array $var_loc_map */ private function checkRemovableChainAssignment(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $cur_assign, array $var_loc_map) : bool { // Check if current assignment expr's variable is removable $var = $cur_assign->var; if ($var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($var->name)) { $var_loc = $cur_assign->var->getStartFilePos(); $var_name = "\$" . $var->name; if (\array_key_exists($var_name, $var_loc_map) && $var_loc_map[$var_name]->raw_file_start === $var_loc) { $curr_removable = \true; } else { $curr_removable = \false; } if ($curr_removable) { $rhs_exp = $cur_assign->expr; if ($rhs_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign || $rhs_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp || $rhs_exp instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef) { $rhs_removable = $this->checkRemovableChainAssignment($rhs_exp, $var_loc_map); return $rhs_removable; } } return $curr_removable; } else { return \false; } } /** * @param array $stmts * @return array{ * 0: PhpParser\Node\Stmt|null, * 1: PhpParser\Node\Expr\Assign|PhpParser\Node\Expr\AssignOp|PhpParser\Node\Expr\AssignRef|null * } */ private function findAssignStmt(array $stmts, string $var_id, \Psalm\CodeLocation $original_location) : array { $assign_stmt = null; $assign_exp = null; $assign_exp_found = \false; $i = 0; while ($i < \count($stmts) && !$assign_exp_found) { $stmt = $stmts[$i]; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression) { $search_result = $this->findAssignExp($stmt->expr, $var_id, $original_location->raw_file_start); [$target_exp, $levels_taken] = $search_result; if ($target_exp !== null) { $assign_exp_found = \true; $assign_exp = $target_exp; $assign_stmt = $levels_taken === 1 ? $stmt : null; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TryCatch) { $search_result = $this->findAssignStmt($stmt->stmts, $var_id, $original_location); if ($search_result[0] && $search_result[1]) { return $search_result; } foreach ($stmt->catches as $catch_stmt) { $search_result = $this->findAssignStmt($catch_stmt->stmts, $var_id, $original_location); if ($search_result[0] && $search_result[1]) { return $search_result; } } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Do_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\While_) { $search_result = $this->findAssignStmt($stmt->stmts, $var_id, $original_location); if ($search_result[0] && $search_result[1]) { return $search_result; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_) { $search_result = $this->findAssignStmt($stmt->stmts, $var_id, $original_location); if ($search_result[0] && $search_result[1]) { return $search_result; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\For_) { $search_result = $this->findAssignStmt($stmt->stmts, $var_id, $original_location); if ($search_result[0] && $search_result[1]) { return $search_result; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_) { $search_result = $this->findAssignStmt($stmt->stmts, $var_id, $original_location); if ($search_result[0] && $search_result[1]) { return $search_result; } foreach ($stmt->elseifs as $elseif_stmt) { $search_result = $this->findAssignStmt($elseif_stmt->stmts, $var_id, $original_location); if ($search_result[0] && $search_result[1]) { return $search_result; } } if ($stmt->else) { $search_result = $this->findAssignStmt($stmt->else->stmts, $var_id, $original_location); if ($search_result[0] && $search_result[1]) { return $search_result; } } } $i++; } return [$assign_stmt, $assign_exp]; } /** * @return array{ * 0: PhpParser\Node\Expr\Assign|PhpParser\Node\Expr\AssignOp|PhpParser\Node\Expr\AssignRef|null, * 1: int * } */ private function findAssignExp(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $current_node, string $var_id, int $var_start_loc, int $search_level = 1) : array { if ($current_node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign || $current_node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp || $current_node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef) { $var = $current_node->var; if ($var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $var->name === \substr($var_id, 1) && $var->getStartFilePos() === $var_start_loc) { return [$current_node, $search_level]; } $rhs_exp = $current_node->expr; $rhs_search_result = $this->findAssignExp($rhs_exp, $var_id, $var_start_loc, $search_level + 1); return [$rhs_search_result[0], $rhs_search_result[1]]; } else { return [null, $search_level]; } } public function checkIfVarRemoved(string $var_id, \Psalm\CodeLocation $var_loc) : bool { return \array_key_exists($var_id, $this->removed_unref_vars) && $this->removed_unref_vars[$var_id] === $var_loc; } } inside_unset = \true; foreach ($stmt->vars as $var) { $was_inside_use = $context->inside_use; $context->inside_use = \true; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $var, $context); $context->inside_use = $was_inside_use; $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($var, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($var_id) { $context->remove($var_id); } if ($var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch && $var->dim) { $root_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($var->var, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($root_var_id && isset($context->vars_in_scope[$root_var_id])) { $root_type = clone $context->vars_in_scope[$root_var_id]; foreach ($root_type->getAtomicTypes() as $atomic_root_type) { if ($atomic_root_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($var->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $var->dim instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber) { if (isset($atomic_root_type->properties[$var->dim->value])) { unset($atomic_root_type->properties[$var->dim->value]); } if (!$atomic_root_type->properties) { if ($atomic_root_type->previous_value_type) { $root_type->addType(new \Psalm\Type\Atomic\TArray([$atomic_root_type->previous_key_type ? clone $atomic_root_type->previous_key_type : new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArrayKey()]), clone $atomic_root_type->previous_value_type])); } else { $root_type->addType(new \Psalm\Type\Atomic\TArray([new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()]), new \Psalm\Type\Union([new \Psalm\Type\Atomic\TEmpty()])])); } } } else { foreach ($atomic_root_type->properties as $key => $type) { $atomic_root_type->properties[$key] = clone $type; $atomic_root_type->properties[$key]->possibly_undefined = \true; } $atomic_root_type->sealed = \false; $root_type->addType($atomic_root_type->getGenericArrayType()); } } elseif ($atomic_root_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $root_type->addType(new \Psalm\Type\Atomic\TArray($atomic_root_type->type_params)); } elseif ($atomic_root_type instanceof \Psalm\Type\Atomic\TNonEmptyMixed) { $root_type->addType(new \Psalm\Type\Atomic\TMixed()); } elseif ($atomic_root_type instanceof \Psalm\Type\Atomic\TList) { $root_type->addType(new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $atomic_root_type->type_param])); } } $context->vars_in_scope[$root_var_id] = $root_type; $context->removeVarFromConflictingClauses($root_var_id, $context->vars_in_scope[$root_var_id], $statements_analyzer); } } } $context->inside_unset = \false; } } inside_throw = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $context->inside_throw = \false; if ($context->finally_scope) { foreach ($context->vars_in_scope as $var_id => $type) { if (isset($context->finally_scope->vars_in_scope[$var_id])) { if ($context->finally_scope->vars_in_scope[$var_id] !== $type) { $context->finally_scope->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->finally_scope->vars_in_scope[$var_id], $type, $statements_analyzer->getCodebase()); } } else { $context->finally_scope->vars_in_scope[$var_id] = $type; } } } if ($context->check_classes && ($throw_type = $statements_analyzer->node_data->getType($stmt->expr)) && !$throw_type->hasMixed()) { $exception_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject('Exception'), new \Psalm\Type\Atomic\TNamedObject('Throwable')]); $file_analyzer = $statements_analyzer->getFileAnalyzer(); $codebase = $statements_analyzer->getCodebase(); foreach ($throw_type->getAtomicTypes() as $throw_type_part) { $throw_type_candidate = new \Psalm\Type\Union([$throw_type_part]); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $throw_type_candidate, $exception_type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidThrow('Cannot throw ' . $throw_type_part . ' as it does not extend Exception or implement Throwable', new \Psalm\CodeLocation($file_analyzer, $stmt), (string) $throw_type_part), $statements_analyzer->getSuppressedIssues())) { return \false; } } elseif (!$context->isSuppressingExceptions($statements_analyzer)) { $codelocation = new \Psalm\CodeLocation($file_analyzer, $stmt); $hash = $codelocation->getHash(); foreach ($throw_type->getAtomicTypes() as $throw_atomic_type) { if ($throw_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $context->possibly_thrown_exceptions[$throw_atomic_type->value][$hash] = $codelocation; } } } } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Throw_) { $statements_analyzer->node_data->setType($stmt, \Psalm\Type::getEmpty()); } return \true; } } collect_initializations && !$global_context) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidGlobal('Cannot use global scope here', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSource()->getSuppressedIssues())) { // fall through } } $source = $statements_analyzer->getSource(); $function_storage = $source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer ? $source->getFunctionLikeStorage($statements_analyzer) : null; foreach ($stmt->vars as $var) { if ($var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { if (\is_string($var->name)) { $var_id = '$' . $var->name; if ($var->name === 'argv' || $var->name === 'argc') { $context->vars_in_scope[$var_id] = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\VariableFetchAnalyzer::getGlobalType($var_id); } elseif (isset($function_storage->global_types[$var_id])) { $context->vars_in_scope[$var_id] = clone $function_storage->global_types[$var_id]; $context->vars_possibly_in_scope[$var_id] = \true; } else { $context->vars_in_scope[$var_id] = $global_context && $global_context->hasVariable($var_id) ? clone $global_context->vars_in_scope[$var_id] : \Psalm\Internal\Analyzer\Statements\Expression\Fetch\VariableFetchAnalyzer::getGlobalType($var_id); $context->vars_possibly_in_scope[$var_id] = \true; $context->byref_constraints[$var_id] = new \Psalm\Internal\ReferenceConstraint(); } } } } } } getDocComment(); $var_comments = []; $var_comment_type = null; $source = $statements_analyzer->getSource(); $codebase = $statements_analyzer->getCodebase(); if ($doc_comment && ($parsed_docblock = $statements_analyzer->getParsedDocblock())) { $file_storage_provider = $codebase->file_storage_provider; $file_storage = $file_storage_provider->get($statements_analyzer->getFilePath()); try { $var_comments = \Psalm\Internal\Analyzer\CommentAnalyzer::arrayToDocblocks($doc_comment, $parsed_docblock, $statements_analyzer->getSource(), $statements_analyzer->getAliases(), $statements_analyzer->getTemplateTypeMap(), $file_storage->type_aliases); } catch (\Psalm\Exception\DocblockParseException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($source, $stmt)))) { // fall through } } foreach ($var_comments as $var_comment) { if (!$var_comment->type) { continue; } $comment_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $var_comment->type, $context->self, $context->self, $statements_analyzer->getParentFQCLN()); if ($codebase->alter_code && $var_comment->type_start && $var_comment->type_end && $var_comment->line_number) { $type_location = new \Psalm\CodeLocation\DocblockTypeLocation($statements_analyzer, $var_comment->type_start, $var_comment->type_end, $var_comment->line_number); $codebase->classlikes->handleDocblockTypeInMigration($codebase, $statements_analyzer, $comment_type, $type_location, $context->calling_method_id); } if (!$var_comment->var_id) { $var_comment_type = $comment_type; continue; } if (isset($context->vars_in_scope[$var_comment->var_id])) { $comment_type->parent_nodes = $context->vars_in_scope[$var_comment->var_id]->parent_nodes; } $context->vars_in_scope[$var_comment->var_id] = $comment_type; } } if ($stmt->expr) { $context->inside_call = \true; if ($stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { self::potentiallyInferTypesOnClosureFromParentReturnType($statements_analyzer, $stmt->expr, $context); } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr); if ($var_comment_type) { $stmt_type = $var_comment_type; if ($stmt_expr_type && $stmt_expr_type->parent_nodes) { $stmt_type->parent_nodes = $stmt_expr_type->parent_nodes; } $statements_analyzer->node_data->setType($stmt, $var_comment_type); } elseif ($stmt_expr_type) { $stmt_type = $stmt_expr_type; if ($stmt_type->isNever()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NoValue('This function or method call never returns output', new \Psalm\CodeLocation($source, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } $stmt_type = \Psalm\Type::getEmpty(); } if ($stmt_type->isVoid()) { $stmt_type = \Psalm\Type::getNull(); } } else { $stmt_type = \Psalm\Type::getMixed(); } } else { $stmt_type = \Psalm\Type::getVoid(); } $statements_analyzer->node_data->setType($stmt, $stmt_type); if ($context->finally_scope) { foreach ($context->vars_in_scope as $var_id => $type) { if (isset($context->finally_scope->vars_in_scope[$var_id])) { if ($context->finally_scope->vars_in_scope[$var_id] !== $type) { $context->finally_scope->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->finally_scope->vars_in_scope[$var_id], $type, $statements_analyzer->getCodebase()); } } else { $context->finally_scope->vars_in_scope[$var_id] = $type; } } } if ($source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && !$source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) { $source->addReturnTypes($context); $source->examineParamTypes($statements_analyzer, $context, $codebase, $stmt); $storage = $source->getFunctionLikeStorage($statements_analyzer); $cased_method_id = $source->getCorrectlyCasedMethodId(); if ($stmt->expr && $storage->location) { $inferred_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $stmt_type, $source->getFQCLN(), $source->getFQCLN(), $source->getParentFQCLN()); if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph) { self::handleTaints($statements_analyzer, $stmt, $cased_method_id, $inferred_type, $storage); } if ($storage instanceof \Psalm\Storage\MethodStorage && $context->self) { $self_class = $context->self; $declared_return_type = $codebase->methods->getMethodReturnType(\Psalm\Internal\MethodIdentifier::wrap($cased_method_id), $self_class, $statements_analyzer, null); } else { $declared_return_type = $storage->return_type; } if ($declared_return_type && !$declared_return_type->hasMixed()) { $local_return_type = $source->getLocalReturnType($declared_return_type, $storage instanceof \Psalm\Storage\MethodStorage && $storage->final); if ($storage instanceof \Psalm\Storage\MethodStorage) { [$fq_class_name, $method_name] = \explode('::', $cased_method_id); $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $found_generic_params = \Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector::collect($codebase, $class_storage, $class_storage, \strtolower($method_name), null, '$this'); if ($found_generic_params) { foreach ($found_generic_params as $template_name => $_) { unset($found_generic_params[$template_name][$fq_class_name]); } $local_return_type = clone $local_return_type; $local_return_type->replaceTemplateTypesWithArgTypes(new \Psalm\Internal\Type\TemplateResult([], $found_generic_params), $codebase); } } if ($local_return_type->isGenerator() && $storage->has_yield) { return null; } if ($stmt_type->hasMixed()) { if ($local_return_type->isVoid() || $local_return_type->isNever()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidReturnStatement('No return values are expected for ' . $cased_method_id, new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { return \false; } } if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && !$source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) { $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath()); } if ($stmt_type->isMixed()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedReturnStatement('Could not infer a return type', new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall through } return null; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedReturnStatement('Possibly-mixed return value', new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($local_return_type->isMixed()) { return null; } if (!$context->collect_initializations && !$context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && !$source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) { $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath()); } if ($local_return_type->isVoid()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidReturnStatement('No return values are expected for ' . $cased_method_id, new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { return \false; } return null; } $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $inferred_type, $local_return_type, \true, \true, $union_comparison_results)) { // is the declared return type more specific than the inferred one? if ($union_comparison_results->type_coerced) { if ($union_comparison_results->type_coerced_from_mixed) { if (!$union_comparison_results->type_coerced_from_as_mixed) { if ($inferred_type->hasMixed()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedReturnStatement('Could not infer a return type', new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedReturnTypeCoercion('The type \'' . $stmt_type->getId() . '\' is more general than the' . ' declared return type \'' . $local_return_type->getId() . '\'' . ' for ' . $cased_method_id, new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\LessSpecificReturnStatement('The type \'' . $stmt_type->getId() . '\' is more general than the' . ' declared return type \'' . $local_return_type->getId() . '\'' . ' for ' . $cased_method_id, new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall throuhg } } foreach ($local_return_type->getAtomicTypes() as $local_type_part) { if ($local_type_part instanceof \Psalm\Type\Atomic\TClassString && $stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $stmt->expr->value, new \Psalm\CodeLocation($source, $stmt->expr), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues()) === \false) { return \false; } } elseif ($local_type_part instanceof \Psalm\Type\Atomic\TArray && $stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_) { $value_param = $local_type_part->type_params[1]; foreach ($value_param->getAtomicTypes() as $local_array_type_part) { if ($local_array_type_part instanceof \Psalm\Type\Atomic\TClassString) { foreach ($stmt->expr->items as $item) { if ($item && $item->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $item->value->value, new \Psalm\CodeLocation($source, $item->value), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues()) === \false) { return \false; } } } } } } } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidReturnStatement('The inferred type \'' . $inferred_type->getId() . '\' does not match the declared return ' . 'type \'' . $local_return_type->getId() . '\' for ' . $cased_method_id, new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if (!$stmt_type->ignore_nullable_issues && $inferred_type->isNullable() && !$local_return_type->isNullable() && !$local_return_type->hasTemplate()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullableReturnStatement('The declared return type \'' . $local_return_type->getId() . '\' for ' . $cased_method_id . ' is not nullable, but the function returns \'' . $inferred_type->getId() . '\'', new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { //fall through } } if (!$stmt_type->ignore_falsable_issues && $inferred_type->isFalsable() && !$local_return_type->isFalsable() && (!$local_return_type->hasBool() || $local_return_type->isTrue()) && !$local_return_type->hasScalar()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\FalsableReturnStatement('The declared return type \'' . $local_return_type . '\' for ' . $cased_method_id . ' does not allow false, but the function returns \'' . $inferred_type . '\'', new \Psalm\CodeLocation($source, $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall throughg } } } } else { if ($storage->signature_return_type && !$storage->signature_return_type->isVoid() && !$storage->has_yield) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidReturnStatement('Empty return statement is not expected in ' . $cased_method_id, new \Psalm\CodeLocation($source, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } return null; } private static function handleTaints(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_ $stmt, string $cased_method_id, \Psalm\Type\Union $inferred_type, \Psalm\Storage\FunctionLikeStorage $storage) : void { if (!$statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph || !$stmt->expr || !$storage->location) { return; } $method_node = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodReturn(\strtolower($cased_method_id), $cased_method_id, $storage->signature_return_type_location ?: $storage->location); $statements_analyzer->data_flow_graph->addNode($method_node); if ($inferred_type->parent_nodes) { foreach ($inferred_type->parent_nodes as $parent_node) { $statements_analyzer->data_flow_graph->addPath($parent_node, $method_node, 'return', $storage->added_taints, $storage->removed_taints); } } } /** * If a function returns a closure, we try to infer the param/return types of * the inner closure. * @see \Psalm\Tests\ReturnTypeTest:756 * @param PhpParser\Node\Expr\Closure|PhpParser\Node\Expr\ArrowFunction $expr */ private static function potentiallyInferTypesOnClosureFromParentReturnType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $expr, \Psalm\Context $context) : void { // if not returning from inside of a function, return if (!$context->calling_method_id && !$context->calling_function_id) { return; } $closure_id = (new \Psalm\Internal\Analyzer\ClosureAnalyzer($expr, $statements_analyzer))->getClosureId(); $closure_storage = $statements_analyzer->getCodebase()->getFunctionLikeStorage($statements_analyzer, $closure_id); /** @psalm-suppress ArgumentTypeCoercion */ $parent_fn_storage = $statements_analyzer->getCodebase()->getFunctionLikeStorage($statements_analyzer, $context->calling_function_id ?: $context->calling_method_id); if ($parent_fn_storage->return_type === null) { return; } // can't infer returned closure if the parent doesn't have a callable return type if (!$parent_fn_storage->return_type->hasCallableType()) { return; } // cannot infer if we have union/intersection types if (!$parent_fn_storage->return_type->isSingle()) { return; } /** @var Type\Atomic\TClosure|Type\Atomic\TCallable $parent_callable_return_type */ $parent_callable_return_type = \current($parent_fn_storage->return_type->getAtomicTypes()); if ($parent_callable_return_type->params === null && $parent_callable_return_type->return_type === null) { return; } foreach ($closure_storage->params as $key => $param) { $parent_param = $parent_callable_return_type->params[$key] ?? null; $param->type = self::inferInnerClosureTypeFromParent($statements_analyzer->getCodebase(), $param->type, $parent_param ? $parent_param->type : null); } $closure_storage->return_type = self::inferInnerClosureTypeFromParent($statements_analyzer->getCodebase(), $closure_storage->return_type, $parent_callable_return_type->return_type); } /** * - If non parent type, do nothing * - If no return type, infer from parent * - If parent return type is more specific, infer from parent * - else, do nothing */ private static function inferInnerClosureTypeFromParent(\Psalm\Codebase $codebase, ?\Psalm\Type\Union $return_type, ?\Psalm\Type\Union $parent_return_type) : ?\Psalm\Type\Union { if (!$parent_return_type) { return $return_type; } if (!$return_type || \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $parent_return_type, $return_type)) { return $parent_return_type; } return $return_type; } } assigned_var_ids; $context->assigned_var_ids = []; $init_var_types = []; foreach ($stmt->init as $init) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $init, $context) === \false) { return \false; } if ($init instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign && $init->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($init->var->name) && ($init_var_type = $statements_analyzer->node_data->getType($init->expr))) { $init_var_types[$init->var->name] = $init_var_type; } } $assigned_var_ids = $context->assigned_var_ids; $context->assigned_var_ids = \array_merge($pre_assigned_var_ids, $assigned_var_ids); $while_true = !$stmt->cond && !$stmt->init && !$stmt->loop; $pre_context = null; if ($while_true) { $pre_context = clone $context; } $for_context = clone $context; $for_context->inside_loop = \true; $for_context->break_types[] = 'loop'; $codebase = $statements_analyzer->getCodebase(); if ($codebase->alter_code) { $for_context->branch_point = $for_context->branch_point ?: (int) $stmt->getAttribute('startFilePos'); } $loop_scope = new \Psalm\Internal\Scope\LoopScope($for_context, $context); $loop_scope->protected_var_ids = \array_merge($assigned_var_ids, $context->protected_var_ids); \Psalm\Internal\Analyzer\Statements\Block\LoopAnalyzer::analyze($statements_analyzer, $stmt->stmts, $stmt->cond, $stmt->loop, $loop_scope, $inner_loop_context); if (!$inner_loop_context) { throw new \UnexpectedValueException('There should be an inner loop context'); } $always_enters_loop = \false; foreach ($stmt->cond as $cond) { if ($cond_type = $statements_analyzer->node_data->getType($cond)) { foreach ($cond_type->getAtomicTypes() as $iterator_type) { $always_enters_loop = $iterator_type instanceof \Psalm\Type\Atomic\TTrue; break; } } if (\count($stmt->init) === 1 && \count($stmt->cond) === 1 && $cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp && $cond->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $cond->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($cond->left->name) && isset($init_var_types[$cond->left->name]) && $init_var_types[$cond->left->name]->isSingleIntLiteral()) { $init_value = $init_var_types[$cond->left->name]->getSingleIntLiteral()->value; $cond_value = $cond->right->value; if ($cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Smaller && $init_value < $cond_value) { $always_enters_loop = \true; break; } if ($cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\SmallerOrEqual && $init_value <= $cond_value) { $always_enters_loop = \true; break; } if ($cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Greater && $init_value > $cond_value) { $always_enters_loop = \true; break; } if ($cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\GreaterOrEqual && $init_value >= $cond_value) { $always_enters_loop = \true; break; } } } if ($while_true) { $always_enters_loop = \true; } $can_leave_loop = !$while_true || \in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK, $loop_scope->final_actions, \true); if ($always_enters_loop && $can_leave_loop) { foreach ($inner_loop_context->vars_in_scope as $var_id => $type) { // if there are break statements in the loop it's not certain // that the loop has finished executing if (\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK, $loop_scope->final_actions, \true) || \in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE, $loop_scope->final_actions, \true)) { if (isset($loop_scope->possibly_defined_loop_parent_vars[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($type, $loop_scope->possibly_defined_loop_parent_vars[$var_id]); } } else { $context->vars_in_scope[$var_id] = $type; } } } $for_context->loop_scope = null; if ($can_leave_loop) { $context->vars_possibly_in_scope = \array_merge($context->vars_possibly_in_scope, $for_context->vars_possibly_in_scope); } elseif ($pre_context) { $context->vars_possibly_in_scope = $pre_context->vars_possibly_in_scope; } $context->referenced_var_ids = \array_intersect_key($for_context->referenced_var_ids, $context->referenced_var_ids); if ($context->collect_exceptions) { $context->mergeExceptions($for_context); } return null; } } getCodebase(); $context->inside_conditional = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->cond, $context) === \false) { return \false; } $context->inside_conditional = \false; $switch_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getArrayVarId($stmt->cond, null, $statements_analyzer); if (!$switch_var_id && ($stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall)) { $switch_var_id = '$__tmp_switch__' . (int) $stmt->cond->getAttribute('startFilePos'); $condition_type = $statements_analyzer->node_data->getType($stmt->cond) ?: \Psalm\Type::getMixed(); $context->vars_in_scope[$switch_var_id] = $condition_type; } $original_context = clone $context; // the last statement always breaks, by default $last_case_exit_type = 'break'; $case_exit_types = new \SplFixedArray(\count($stmt->cases)); $has_default = \false; $case_action_map = []; $config = \Psalm\Config::getInstance(); // create a map of case statement -> ultimate exit type for ($i = \count($stmt->cases) - 1; $i >= 0; --$i) { $case = $stmt->cases[$i]; $case_actions = $case_action_map[$i] = \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($case->stmts, $statements_analyzer->node_data, $config->exit_functions, ['switch']); if (!\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE, $case_actions, \true)) { if ($case_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END]) { $last_case_exit_type = 'return_throw'; } elseif ($case_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE]) { $last_case_exit_type = 'continue'; } elseif (\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_LEAVE_SWITCH, $case_actions, \true)) { $last_case_exit_type = 'break'; } } $case_exit_types[$i] = $last_case_exit_type; } $switch_scope = new \Psalm\Internal\Scope\SwitchScope(); $was_caching_assertions = $statements_analyzer->node_data->cache_assertions; $statements_analyzer->node_data->cache_assertions = \false; for ($i = 0, $l = \count($stmt->cases); $i < $l; $i++) { $case = $stmt->cases[$i]; /** @var string */ $case_exit_type = $case_exit_types[$i]; $case_actions = $case_action_map[$i]; if (!$case->cond) { $has_default = \true; } if (\Psalm\Internal\Analyzer\Statements\Block\SwitchCaseAnalyzer::analyze($statements_analyzer, $codebase, $stmt, $switch_var_id, $case, $context, $original_context, $case_exit_type, $case_actions, $i === $l - 1, $switch_scope) === \false) { return \false; } } $all_options_matched = $has_default; if (!$has_default && $switch_scope->negated_clauses && $switch_var_id) { $entry_clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($original_context->clauses, $switch_scope->negated_clauses)); $reconcilable_if_types = \Psalm\Type\Algebra::getTruthsFromFormula($entry_clauses); // if the if has an || in the conditional, we cannot easily reason about it if ($reconcilable_if_types && isset($reconcilable_if_types[$switch_var_id])) { $changed_var_ids = []; $case_vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($reconcilable_if_types, [], $original_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, [], $original_context->inside_loop); if (isset($case_vars_in_scope_reconciled[$switch_var_id]) && $case_vars_in_scope_reconciled[$switch_var_id]->isEmpty()) { $all_options_matched = \true; } } } if ($was_caching_assertions) { $statements_analyzer->node_data->cache_assertions = \true; } // only update vars if there is a default or all possible cases accounted for // if the default has a throw/return/continue, that should be handled above if ($all_options_matched) { if ($switch_scope->new_vars_in_scope) { $context->vars_in_scope = \array_merge($context->vars_in_scope, $switch_scope->new_vars_in_scope); } if ($switch_scope->redefined_vars) { $context->vars_in_scope = \array_merge($context->vars_in_scope, $switch_scope->redefined_vars); } if ($switch_scope->possibly_redefined_vars) { foreach ($switch_scope->possibly_redefined_vars as $var_id => $type) { if (!isset($switch_scope->redefined_vars[$var_id]) && !isset($switch_scope->new_vars_in_scope[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($type, $context->vars_in_scope[$var_id]); } } } /** @psalm-suppress UndefinedPropertyAssignment */ $stmt->allMatched = \true; } elseif ($switch_scope->possibly_redefined_vars) { foreach ($switch_scope->possibly_redefined_vars as $var_id => $type) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($type, $context->vars_in_scope[$var_id]); } } if ($switch_scope->new_assigned_var_ids) { $context->assigned_var_ids += $switch_scope->new_assigned_var_ids; } $context->vars_possibly_in_scope = \array_merge($context->vars_possibly_in_scope, $switch_scope->new_vars_possibly_in_scope); return null; } } getCodebase(); /** @var int $i */ foreach ($stmt->catches as $i => $catch) { $catch_actions[$i] = \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($catch->stmts, $statements_analyzer->node_data, $codebase->config->exit_functions); $all_catches_leave = $all_catches_leave && !\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE, $catch_actions[$i], \true); } $existing_thrown_exceptions = $context->possibly_thrown_exceptions; /** * @var array> */ $context->possibly_thrown_exceptions = []; $old_context = clone $context; if ($all_catches_leave && !$stmt->finally) { $try_context = $context; } else { $try_context = clone $context; if ($codebase->alter_code) { $try_context->branch_point = $try_context->branch_point ?: (int) $stmt->getAttribute('startFilePos'); } if ($stmt->finally) { $try_context->finally_scope = new \Psalm\Internal\Scope\FinallyScope($try_context->vars_in_scope); } } $assigned_var_ids = $try_context->assigned_var_ids; $context->assigned_var_ids = []; $old_referenced_var_ids = $try_context->referenced_var_ids; if ($statements_analyzer->analyze($stmt->stmts, $context) === \false) { return \false; } if ($try_context->finally_scope) { foreach ($context->vars_in_scope as $var_id => $type) { if (isset($try_context->finally_scope->vars_in_scope[$var_id])) { if ($try_context->finally_scope->vars_in_scope[$var_id] !== $type) { $try_context->finally_scope->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($try_context->finally_scope->vars_in_scope[$var_id], $type, $statements_analyzer->getCodebase()); } } else { $try_context->finally_scope->vars_in_scope[$var_id] = $type; } } } $context->has_returned = \false; $stmt_control_actions = \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($stmt->stmts, $statements_analyzer->node_data, $codebase->config->exit_functions, $context->break_types); /** @var array */ $newly_assigned_var_ids = $context->assigned_var_ids; $context->assigned_var_ids = \array_merge($assigned_var_ids, $newly_assigned_var_ids); $possibly_referenced_var_ids = \array_merge($context->referenced_var_ids, $old_referenced_var_ids); if ($try_context !== $context) { foreach ($context->vars_in_scope as $var_id => $type) { if (!isset($try_context->vars_in_scope[$var_id])) { $try_context->vars_in_scope[$var_id] = clone $type; $context->vars_in_scope[$var_id]->possibly_undefined = \true; $context->vars_in_scope[$var_id]->possibly_undefined_from_try = \true; } else { $try_context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($try_context->vars_in_scope[$var_id], $type); } } $try_context->vars_possibly_in_scope = $context->vars_possibly_in_scope; $try_context->possibly_thrown_exceptions = $context->possibly_thrown_exceptions; $context->referenced_var_ids = \array_intersect_key($try_context->referenced_var_ids, $context->referenced_var_ids); } $try_leaves_loop = $context->loop_scope && $context->loop_scope->final_actions && !\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE, $context->loop_scope->final_actions, \true); if (!$all_catches_leave) { foreach ($newly_assigned_var_ids as $assigned_var_id => $_) { $context->removeVarFromConflictingClauses($assigned_var_id); } } else { foreach ($newly_assigned_var_ids as $assigned_var_id => $_) { $try_context->removeVarFromConflictingClauses($assigned_var_id); } } // at this point we have two contexts – $context, in which it is assumed that everything was fine, // and $try_context - which allows all variables to have the union of the values before and after // the try was applied $original_context = clone $try_context; $issues_to_suppress = ['RedundantCondition', 'RedundantConditionGivenDocblockType', 'TypeDoesNotContainNull', 'TypeDoesNotContainType']; $definitely_newly_assigned_var_ids = $newly_assigned_var_ids; /** @var int $i */ foreach ($stmt->catches as $i => $catch) { $catch_context = clone $original_context; $catch_context->has_returned = \false; foreach ($catch_context->vars_in_scope as $var_id => $type) { if (!isset($old_context->vars_in_scope[$var_id])) { $type = clone $type; $type->possibly_undefined_from_try = \true; $catch_context->vars_in_scope[$var_id] = $type; } else { $catch_context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($type, $old_context->vars_in_scope[$var_id]); } } $fq_catch_classes = []; if (!$catch->types) { throw new \UnexpectedValueException('Very bad'); } foreach ($catch->types as $catch_type) { $fq_catch_class = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($catch_type, $statements_analyzer->getAliases()); $fq_catch_class = $codebase->classlikes->getUnAliasedName($fq_catch_class); if ($codebase->alter_code && $fq_catch_class) { $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $statements_analyzer, $catch_type, $fq_catch_class, $context->calling_method_id); } if ($original_context->check_classes) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $fq_catch_class, new \Psalm\CodeLocation($statements_analyzer->getSource(), $catch_type, $context->include_location), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues(), \false) === \false) { return \false; } } if ($codebase->classExists($fq_catch_class) && \strtolower($fq_catch_class) !== 'exception' && !($codebase->classExtends($fq_catch_class, 'Exception') || $codebase->classImplements($fq_catch_class, 'Throwable')) || $codebase->interfaceExists($fq_catch_class) && \strtolower($fq_catch_class) !== 'throwable' && !$codebase->interfaceExtends($fq_catch_class, 'Throwable')) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidCatch('Class/interface ' . $fq_catch_class . ' cannot be caught', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt), $fq_catch_class), $statements_analyzer->getSuppressedIssues())) { return \false; } } $fq_catch_classes[] = $fq_catch_class; } if ($catch_context->collect_exceptions) { foreach ($fq_catch_classes as $fq_catch_class) { $fq_catch_class_lower = \strtolower($fq_catch_class); foreach ($catch_context->possibly_thrown_exceptions as $exception_fqcln => $_) { $exception_fqcln_lower = \strtolower($exception_fqcln); if ($exception_fqcln_lower === $fq_catch_class_lower || $codebase->classExists($exception_fqcln) && $codebase->classExtendsOrImplements($exception_fqcln, $fq_catch_class) || $codebase->interfaceExists($exception_fqcln) && $codebase->interfaceExtends($exception_fqcln, $fq_catch_class)) { unset($original_context->possibly_thrown_exceptions[$exception_fqcln]); unset($context->possibly_thrown_exceptions[$exception_fqcln]); unset($catch_context->possibly_thrown_exceptions[$exception_fqcln]); } } } /** * @var array> */ $catch_context->possibly_thrown_exceptions = []; } // discard all clauses because crazy stuff may have happened in try block $catch_context->clauses = []; /** @psalm-suppress RedundantConditionGivenDocblockType */ if ($catch->var && \is_string($catch->var->name)) { $catch_var_id = '$' . $catch->var->name; $catch_context->vars_in_scope[$catch_var_id] = new \Psalm\Type\Union(\array_map( /** * @param string $fq_catch_class */ function ($fq_catch_class) use($codebase) : \Psalm\Type\Atomic\TNamedObject { $catch_class_type = new \Psalm\Type\Atomic\TNamedObject($fq_catch_class); if (\version_compare(\PHP_VERSION, '7.0.0dev', '>=') && \strtolower($fq_catch_class) !== 'throwable' && $codebase->interfaceExists($fq_catch_class) && !$codebase->interfaceExtends($fq_catch_class, 'Throwable')) { $catch_class_type->addIntersectionType(new \Psalm\Type\Atomic\TNamedObject('Throwable')); } return $catch_class_type; }, $fq_catch_classes )); $catch_context->vars_possibly_in_scope[$catch_var_id] = \true; $location = new \Psalm\CodeLocation($statements_analyzer->getSource(), $catch->var); if (!$statements_analyzer->hasVariable($catch_var_id)) { $statements_analyzer->registerVariable($catch_var_id, $location, $catch_context->branch_point); } else { $statements_analyzer->registerVariableAssignment($catch_var_id, $location); } if ($statements_analyzer->data_flow_graph) { $catch_var_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($catch_var_id, $location); $catch_context->vars_in_scope[$catch_var_id]->parent_nodes = [$catch_var_node->id => $catch_var_node]; if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph) { $statements_analyzer->data_flow_graph->addPath($catch_var_node, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'variable-use'); } } } $suppressed_issues = $statements_analyzer->getSuppressedIssues(); foreach ($issues_to_suppress as $issue_to_suppress) { if (!\in_array($issue_to_suppress, $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues([$issue_to_suppress]); } } $old_catch_assigned_var_ids = $catch_context->referenced_var_ids; $catch_context->assigned_var_ids = []; $statements_analyzer->analyze($catch->stmts, $catch_context); // recalculate in case there's a no-return clause $catch_actions[$i] = \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($catch->stmts, $statements_analyzer->node_data, $codebase->config->exit_functions, $context->break_types); foreach ($issues_to_suppress as $issue_to_suppress) { if (!\in_array($issue_to_suppress, $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues([$issue_to_suppress]); } } /** @var array */ $new_catch_assigned_var_ids = $catch_context->assigned_var_ids; $catch_context->assigned_var_ids += $old_catch_assigned_var_ids; $context->referenced_var_ids = \array_intersect_key($catch_context->referenced_var_ids, $context->referenced_var_ids); $possibly_referenced_var_ids = \array_merge($catch_context->referenced_var_ids, $possibly_referenced_var_ids); if ($codebase->find_unused_variables && $catch_actions[$i] !== [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END]) { // something } if ($catch_context->collect_exceptions) { $context->mergeExceptions($catch_context); } if ($catch_actions[$i] !== [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END] && $catch_actions[$i] !== [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE] && $catch_actions[$i] !== [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK]) { $definitely_newly_assigned_var_ids = \array_intersect_key($new_catch_assigned_var_ids, $definitely_newly_assigned_var_ids); foreach ($catch_context->vars_in_scope as $var_id => $type) { if ($stmt_control_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END]) { $context->vars_in_scope[$var_id] = $type; } elseif (isset($context->vars_in_scope[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->vars_in_scope[$var_id], $type); } } $context->vars_possibly_in_scope = \array_merge($catch_context->vars_possibly_in_scope, $context->vars_possibly_in_scope); } else { if ($stmt->finally) { $context->vars_possibly_in_scope = \array_merge($catch_context->vars_possibly_in_scope, $context->vars_possibly_in_scope); } } if ($try_context->finally_scope) { foreach ($catch_context->vars_in_scope as $var_id => $type) { if (isset($try_context->finally_scope->vars_in_scope[$var_id])) { if ($try_context->finally_scope->vars_in_scope[$var_id] !== $type) { $try_context->finally_scope->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($try_context->finally_scope->vars_in_scope[$var_id], $type, $statements_analyzer->getCodebase()); } } else { $try_context->finally_scope->vars_in_scope[$var_id] = $type; } } } } if ($context->loop_scope && !$try_leaves_loop && !\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE, $context->loop_scope->final_actions, \true)) { $context->loop_scope->final_actions[] = \Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE; } if ($stmt->finally) { if ($try_context->finally_scope) { $finally_context = clone $context; $finally_context->assigned_var_ids = []; $finally_context->possibly_assigned_var_ids = []; $finally_context->vars_in_scope = $try_context->finally_scope->vars_in_scope; $statements_analyzer->analyze($stmt->finally->stmts, $finally_context); if ($finally_context->has_returned) { $context->has_returned = \true; } /** @var string $var_id */ foreach ($finally_context->assigned_var_ids as $var_id => $_) { if (isset($context->vars_in_scope[$var_id])) { if ($context->vars_in_scope[$var_id]->possibly_undefined && $context->vars_in_scope[$var_id]->possibly_undefined_from_try) { $context->vars_in_scope[$var_id]->possibly_undefined = \false; $context->vars_in_scope[$var_id]->possibly_undefined_from_try = \false; } $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($context->vars_in_scope[$var_id], $finally_context->vars_in_scope[$var_id], $codebase); } elseif (isset($finally_context->vars_in_scope[$var_id])) { $context->vars_in_scope[$var_id] = clone $finally_context->vars_in_scope[$var_id]; } } } } foreach ($definitely_newly_assigned_var_ids as $var_id => $_) { if (isset($context->vars_in_scope[$var_id])) { $new_type = clone $context->vars_in_scope[$var_id]; if ($new_type->possibly_undefined_from_try) { $new_type->possibly_undefined = \false; $new_type->possibly_undefined_from_try = \false; } $context->vars_in_scope[$var_id] = $new_type; } } foreach ($existing_thrown_exceptions as $possibly_thrown_exception => $codelocations) { foreach ($codelocations as $hash => $codelocation) { $context->possibly_thrown_exceptions[$possibly_thrown_exception][$hash] = $codelocation; } } return null; } } cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && $stmt->cond->name->parts === ['true'] || $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $stmt->cond->value > 0; $pre_context = null; if ($while_true) { $pre_context = clone $context; } $while_context = clone $context; $while_context->inside_loop = \true; $while_context->break_types[] = 'loop'; $codebase = $statements_analyzer->getCodebase(); if ($codebase->alter_code) { $while_context->branch_point = $while_context->branch_point ?: (int) $stmt->getAttribute('startFilePos'); } $loop_scope = new \Psalm\Internal\Scope\LoopScope($while_context, $context); $loop_scope->protected_var_ids = $context->protected_var_ids; if (\Psalm\Internal\Analyzer\Statements\Block\LoopAnalyzer::analyze($statements_analyzer, $stmt->stmts, self::getAndExpressions($stmt->cond), [], $loop_scope, $inner_loop_context) === \false) { return \false; } if (!$inner_loop_context) { throw new \UnexpectedValueException('Should always enter loop'); } $always_enters_loop = \false; if ($stmt_cond_type = $statements_analyzer->node_data->getType($stmt->cond)) { $always_enters_loop = \true; foreach ($stmt_cond_type->getAtomicTypes() as $iterator_type) { if ($iterator_type instanceof \Psalm\Type\Atomic\TArray || $iterator_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($iterator_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if (!$iterator_type->sealed) { $always_enters_loop = \false; } } elseif (!$iterator_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $always_enters_loop = \false; } continue; } if ($iterator_type instanceof \Psalm\Type\Atomic\TTrue) { continue; } if ($iterator_type instanceof \Psalm\Type\Atomic\TLiteralString && $iterator_type->value) { continue; } if ($iterator_type instanceof \Psalm\Type\Atomic\TLiteralInt && $iterator_type->value) { continue; } $always_enters_loop = \false; break; } } $can_leave_loop = !$while_true || \in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK, $loop_scope->final_actions, \true); if ($always_enters_loop && $can_leave_loop) { foreach ($inner_loop_context->vars_in_scope as $var_id => $type) { // if there are break statements in the loop it's not certain // that the loop has finished executing, so the assertions at the end // the loop in the while conditional may not hold if (\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK, $loop_scope->final_actions, \true) || \in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE, $loop_scope->final_actions, \true)) { if (isset($loop_scope->possibly_defined_loop_parent_vars[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($type, $loop_scope->possibly_defined_loop_parent_vars[$var_id]); } } else { $context->vars_in_scope[$var_id] = $type; } } } $while_context->loop_scope = null; if ($can_leave_loop) { $context->vars_possibly_in_scope = \array_merge($context->vars_possibly_in_scope, $while_context->vars_possibly_in_scope); } elseif ($pre_context) { $context->vars_possibly_in_scope = $pre_context->vars_possibly_in_scope; } $context->referenced_var_ids = \array_merge($context->referenced_var_ids, $while_context->referenced_var_ids); return null; } /** * @return list */ private static function getAndExpressions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr) : array { if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd) { return \array_merge(self::getAndExpressions($expr->left), self::getAndExpressions($expr->right)); } return [$expr]; } } getDocComment(); $codebase = $statements_analyzer->getCodebase(); $file_path = $statements_analyzer->getRootFilePath(); $type_aliases = $codebase->file_storage_provider->get($file_path)->type_aliases; if ($doc_comment) { try { $var_comments = \Psalm\Internal\Analyzer\CommentAnalyzer::getTypeFromComment($doc_comment, $statements_analyzer->getSource(), $statements_analyzer->getSource()->getAliases(), $statements_analyzer->getTemplateTypeMap() ?: [], $type_aliases); } catch (\Psalm\Exception\DocblockParseException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer, $stmt)))) { // fall through } } } $safe_var_ids = []; if ($stmt->keyVar instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($stmt->keyVar->name)) { $safe_var_ids['$' . $stmt->keyVar->name] = \true; } if ($stmt->valueVar instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($stmt->valueVar->name)) { $safe_var_ids['$' . $stmt->valueVar->name] = \true; } elseif ($stmt->valueVar instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\List_) { foreach ($stmt->valueVar->items as $list_item) { if (!$list_item) { continue; } $list_item_key = $list_item->key; $list_item_value = $list_item->value; if ($list_item_value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($list_item_value->name)) { $safe_var_ids['$' . $list_item_value->name] = \true; } if ($list_item_key instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($list_item_key->name)) { $safe_var_ids['$' . $list_item_key->name] = \true; } } } foreach ($var_comments as $var_comment) { if (!$var_comment->var_id || !$var_comment->type) { continue; } if (isset($safe_var_ids[$var_comment->var_id])) { continue; } $comment_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $var_comment->type, $context->self, $context->self, $statements_analyzer->getParentFQCLN()); $type_location = null; if ($var_comment->type_start && $var_comment->type_end && $var_comment->line_number) { $type_location = new \Psalm\CodeLocation\DocblockTypeLocation($statements_analyzer, $var_comment->type_start, $var_comment->type_end, $var_comment->line_number); if ($codebase->alter_code) { $codebase->classlikes->handleDocblockTypeInMigration($codebase, $statements_analyzer, $comment_type, $type_location, $context->calling_method_id); } } if (isset($context->vars_in_scope[$var_comment->var_id]) || \Psalm\Internal\Analyzer\Statements\Expression\Fetch\VariableFetchAnalyzer::isSuperGlobal($var_comment->var_id)) { if ($codebase->find_unused_variables && $doc_comment && $type_location && isset($context->vars_in_scope[$var_comment->var_id]) && $context->vars_in_scope[$var_comment->var_id]->getId() === $comment_type->getId() && !$comment_type->isMixed()) { $project_analyzer = $statements_analyzer->getProjectAnalyzer(); if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['UnnecessaryVarAnnotation'])) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::addVarAnnotationToRemove($type_location); } elseif (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnnecessaryVarAnnotation('The @var ' . $comment_type . ' annotation for ' . $var_comment->var_id . ' is unnecessary', $type_location), [], \true)) { // fall through } } if (isset($context->vars_in_scope[$var_comment->var_id])) { $comment_type->parent_nodes = $context->vars_in_scope[$var_comment->var_id]->parent_nodes; } $context->vars_in_scope[$var_comment->var_id] = $comment_type; } } $was_inside_use = $context->inside_use; $context->inside_use = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context) === \false) { return \false; } $context->inside_use = $was_inside_use; $key_type = null; $value_type = null; $always_non_empty_array = \true; $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getVarId($stmt->expr, $statements_analyzer->getFQCLN(), $statements_analyzer); if ($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr)) { $iterator_type = $stmt_expr_type; } elseif ($var_id && $context->hasVariable($var_id)) { $iterator_type = $context->vars_in_scope[$var_id]; } else { $iterator_type = null; } if ($iterator_type) { if (self::checkIteratorType($statements_analyzer, $stmt, $iterator_type, $codebase, $context, $key_type, $value_type, $always_non_empty_array) === \false) { return \false; } } $foreach_context = clone $context; foreach ($foreach_context->vars_in_scope as $context_var_id => $context_type) { $foreach_context->vars_in_scope[$context_var_id] = clone $context_type; } $foreach_context->inside_loop = \true; $foreach_context->break_types[] = 'loop'; if ($codebase->alter_code) { $foreach_context->branch_point = $foreach_context->branch_point ?: (int) $stmt->getAttribute('startFilePos'); } if ($stmt->keyVar && $stmt->keyVar instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($stmt->keyVar->name)) { $key_type = $key_type ?: \Psalm\Type::getMixed(); \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::analyze($statements_analyzer, $stmt->keyVar, $stmt->expr, $key_type, $foreach_context, $doc_comment, ['$' . $stmt->keyVar->name => \true]); } $value_type = $value_type ?: \Psalm\Type::getMixed(); if ($stmt->byRef) { $value_type->by_ref = \true; } \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::analyze($statements_analyzer, $stmt->valueVar, $stmt->expr, $value_type, $foreach_context, $doc_comment, $stmt->valueVar instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($stmt->valueVar->name) ? ['$' . $stmt->valueVar->name => \true] : []); foreach ($var_comments as $var_comment) { if (!$var_comment->var_id || !$var_comment->type) { continue; } $comment_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $var_comment->type, $context->self, $context->self, $statements_analyzer->getParentFQCLN()); if (isset($foreach_context->vars_in_scope[$var_comment->var_id])) { $existing_var_type = $foreach_context->vars_in_scope[$var_comment->var_id]; $comment_type->parent_nodes = $existing_var_type->parent_nodes; $comment_type->by_ref = $existing_var_type->by_ref; } $foreach_context->vars_in_scope[$var_comment->var_id] = $comment_type; } $loop_scope = new \Psalm\Internal\Scope\LoopScope($foreach_context, $context); $loop_scope->protected_var_ids = $context->protected_var_ids; \Psalm\Internal\Analyzer\Statements\Block\LoopAnalyzer::analyze($statements_analyzer, $stmt->stmts, [], [], $loop_scope, $inner_loop_context, \false, $always_non_empty_array); if (!$inner_loop_context) { throw new \UnexpectedValueException('There should be an inner loop context'); } $foreach_context->loop_scope = null; $context->vars_possibly_in_scope = \array_merge($foreach_context->vars_possibly_in_scope, $context->vars_possibly_in_scope); $context->referenced_var_ids = \array_intersect_key($foreach_context->referenced_var_ids, $context->referenced_var_ids); if ($context->collect_exceptions) { $context->mergeExceptions($foreach_context); } return null; } /** * @return false|null */ public static function checkIteratorType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_ $stmt, \Psalm\Type\Union $iterator_type, \Psalm\Codebase $codebase, \Psalm\Context $context, ?\Psalm\Type\Union &$key_type, ?\Psalm\Type\Union &$value_type, bool &$always_non_empty_array) : ?bool { if ($iterator_type->isNull()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\NullIterator('Cannot iterate over null', new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { return \false; } } elseif ($iterator_type->isNullable() && !$iterator_type->ignore_nullable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyNullIterator('Cannot iterate over nullable var ' . $iterator_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { return \false; } } elseif ($iterator_type->isFalsable() && !$iterator_type->ignore_falsable_issues) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyFalseIterator('Cannot iterate over falsable var ' . $iterator_type, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { return \false; } } $has_valid_iterator = \false; $invalid_iterator_types = []; $raw_object_types = []; foreach ($iterator_type->getAtomicTypes() as $iterator_atomic_type) { if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $iterator_atomic_type = \array_values($iterator_atomic_type->as->getAtomicTypes())[0]; } // if it's an empty array, we cannot iterate over it if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TArray && $iterator_atomic_type->type_params[1]->isEmpty()) { $always_non_empty_array = \false; $has_valid_iterator = \true; continue; } if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TNull || $iterator_atomic_type instanceof \Psalm\Type\Atomic\TFalse) { $always_non_empty_array = \false; continue; } if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TArray || $iterator_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray || $iterator_atomic_type instanceof \Psalm\Type\Atomic\TList) { if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if (!$iterator_atomic_type->sealed) { $always_non_empty_array = \false; } $iterator_atomic_type = $iterator_atomic_type->getGenericArrayType(); } elseif ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TList) { if (!$iterator_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyList) { $always_non_empty_array = \false; } $iterator_atomic_type = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $iterator_atomic_type->type_param]); } elseif (!$iterator_atomic_type instanceof \Psalm\Type\Atomic\TNonEmptyArray) { $always_non_empty_array = \false; } if (!$value_type) { $value_type = clone $iterator_atomic_type->type_params[1]; } else { $value_type = \Psalm\Type::combineUnionTypes($value_type, $iterator_atomic_type->type_params[1]); } \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::taintArrayFetch($statements_analyzer, $stmt->expr, null, $value_type, \Psalm\Type::getMixed()); $key_type_part = $iterator_atomic_type->type_params[0]; if (!$key_type) { $key_type = $key_type_part; } else { $key_type = \Psalm\Type::combineUnionTypes($key_type, $key_type_part); } \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::taintArrayFetch($statements_analyzer, $stmt->expr, null, $key_type, \Psalm\Type::getMixed()); $has_valid_iterator = \true; continue; } $always_non_empty_array = \false; if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\Scalar || $iterator_atomic_type instanceof \Psalm\Type\Atomic\TVoid) { $invalid_iterator_types[] = $iterator_atomic_type->getKey(); $value_type = \Psalm\Type::getMixed(); } elseif ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TObject || $iterator_atomic_type instanceof \Psalm\Type\Atomic\TMixed || $iterator_atomic_type instanceof \Psalm\Type\Atomic\TEmpty) { $has_valid_iterator = \true; $value_type = \Psalm\Type::getMixed(); \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ArrayFetchAnalyzer::taintArrayFetch($statements_analyzer, $stmt->expr, null, $value_type, \Psalm\Type::getMixed()); if (!$context->pure) { if ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call a possibly-mutating iterator from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } elseif ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TIterable) { if ($iterator_atomic_type->extra_types) { $iterator_atomic_type_copy = clone $iterator_atomic_type; $iterator_atomic_type_copy->extra_types = []; $iterator_atomic_types = [$iterator_atomic_type_copy]; $iterator_atomic_types = \array_merge($iterator_atomic_types, $iterator_atomic_type->extra_types); } else { $iterator_atomic_types = [$iterator_atomic_type]; } $intersection_value_type = null; $intersection_key_type = null; foreach ($iterator_atomic_types as $iat) { if (!$iat instanceof \Psalm\Type\Atomic\TIterable) { continue; } [$key_type_part, $value_type_part] = $iat->type_params; if (!$intersection_value_type) { $intersection_value_type = $value_type_part; } else { $intersection_value_type = \Psalm\Type::intersectUnionTypes($intersection_value_type, $value_type_part, $codebase) ?: \Psalm\Type::getMixed(); } if (!$intersection_key_type) { $intersection_key_type = $key_type_part; } else { $intersection_key_type = \Psalm\Type::intersectUnionTypes($intersection_key_type, $key_type_part, $codebase) ?: \Psalm\Type::getMixed(); } } if (!$intersection_value_type || !$intersection_key_type) { throw new \UnexpectedValueException('Should not happen'); } if (!$value_type) { $value_type = $intersection_value_type; } else { $value_type = \Psalm\Type::combineUnionTypes($value_type, $intersection_value_type); } if (!$key_type) { $key_type = $intersection_key_type; } else { $key_type = \Psalm\Type::combineUnionTypes($key_type, $intersection_key_type); } $has_valid_iterator = \true; if (!$context->pure) { if ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call a possibly-mutating Traversable::getIterator from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } elseif ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { if ($iterator_atomic_type->value !== 'Traversable' && $iterator_atomic_type->value !== $statements_analyzer->getClassName()) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $iterator_atomic_type->value, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr), $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues()) === \false) { return \false; } } if (\Psalm\Internal\Type\Comparator\AtomicTypeComparator::isContainedBy($codebase, $iterator_atomic_type, new \Psalm\Type\Atomic\TIterable([\Psalm\Type::getMixed(), \Psalm\Type::getMixed()]))) { self::handleIterable($statements_analyzer, $iterator_atomic_type, $stmt->expr, $codebase, $context, $key_type, $value_type, $has_valid_iterator); } else { $raw_object_types[] = $iterator_atomic_type->value; } if (!$context->pure) { if ($statements_analyzer->getSource() instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer && $statements_analyzer->getSource()->track_mutations) { $statements_analyzer->getSource()->inferred_has_mutation = \true; $statements_analyzer->getSource()->inferred_impure = \true; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ImpureMethodCall('Cannot call a possibly-mutating iterator from a pure context', new \Psalm\CodeLocation($statements_analyzer, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } if ($raw_object_types) { if ($has_valid_iterator) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossibleRawObjectIteration('Possibly undesired iteration over regular object ' . \reset($raw_object_types), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RawObjectIteration('Possibly undesired iteration over regular object ' . \reset($raw_object_types), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } if ($invalid_iterator_types) { if ($has_valid_iterator) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\PossiblyInvalidIterator('Cannot iterate over ' . $invalid_iterator_types[0], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidIterator('Cannot iterate over ' . $invalid_iterator_types[0], new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->expr)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } return null; } public static function handleIterable(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Type\Atomic\TNamedObject $iterator_atomic_type, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $foreach_expr, \Psalm\Codebase $codebase, \Psalm\Context $context, ?\Psalm\Type\Union &$key_type, ?\Psalm\Type\Union &$value_type, bool &$has_valid_iterator) : void { if ($iterator_atomic_type->extra_types) { $iterator_atomic_type_copy = clone $iterator_atomic_type; $iterator_atomic_type_copy->extra_types = []; $iterator_atomic_types = [$iterator_atomic_type_copy]; $iterator_atomic_types = \array_merge($iterator_atomic_types, $iterator_atomic_type->extra_types); } else { $iterator_atomic_types = [$iterator_atomic_type]; } foreach ($iterator_atomic_types as $iterator_atomic_type) { if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam || $iterator_atomic_type instanceof \Psalm\Type\Atomic\TObjectWithProperties) { throw new \UnexpectedValueException('Shouldn’t get a generic param here'); } $has_valid_iterator = \true; if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject && \strtolower($iterator_atomic_type->value) === 'simplexmlelement') { if ($value_type) { $value_type = \Psalm\Type::combineUnionTypes($value_type, new \Psalm\Type\Union([clone $iterator_atomic_type])); } else { $value_type = new \Psalm\Type\Union([clone $iterator_atomic_type]); } if ($key_type) { $key_type = \Psalm\Type::combineUnionTypes($key_type, \Psalm\Type::getString()); } else { $key_type = \Psalm\Type::getString(); } } if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TIterable || (\strtolower($iterator_atomic_type->value) === 'traversable' || $codebase->classImplements($iterator_atomic_type->value, 'Traversable') || $codebase->interfaceExists($iterator_atomic_type->value) && $codebase->interfaceExtends($iterator_atomic_type->value, 'Traversable'))) { if (\strtolower($iterator_atomic_type->value) === 'iteratoraggregate' || $codebase->classImplements($iterator_atomic_type->value, 'IteratorAggregate') || $codebase->interfaceExists($iterator_atomic_type->value) && $codebase->interfaceExtends($iterator_atomic_type->value, 'IteratorAggregate')) { $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($foreach_expr, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier('getIterator', $foreach_expr->getAttributes())); $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('PossiblyUndefinedMethod', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyUndefinedMethod']); } \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_method_call, $context); if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('PossiblyUndefinedMethod', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyUndefinedMethod']); } $iterator_class_type = $statements_analyzer->node_data->getType($fake_method_call) ?: null; $statements_analyzer->node_data = $old_data_provider; if ($iterator_class_type) { foreach ($iterator_class_type->getAtomicTypes() as $array_atomic_type) { $key_type_part = null; $value_type_part = null; if ($array_atomic_type instanceof \Psalm\Type\Atomic\TArray || $array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { if ($array_atomic_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $array_atomic_type = $array_atomic_type->getGenericArrayType(); } [$key_type_part, $value_type_part] = $array_atomic_type->type_params; } else { if ($array_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject && $codebase->classExists($array_atomic_type->value) && $codebase->classImplements($array_atomic_type->value, 'Traversable')) { $generic_storage = $codebase->classlike_storage_provider->get($array_atomic_type->value); // The collection might be an iterator, in which case // we want to call the iterator function /** @psalm-suppress PossiblyUndefinedStringArrayOffset */ if (!isset($generic_storage->template_type_extends['Traversable']) || $generic_storage->template_type_extends['Traversable']['TKey']->isMixed() && $generic_storage->template_type_extends['Traversable']['TValue']->isMixed()) { self::handleIterable($statements_analyzer, $array_atomic_type, $fake_method_call, $codebase, $context, $key_type, $value_type, $has_valid_iterator); continue; } } if ($array_atomic_type instanceof \Psalm\Type\Atomic\TIterable || $array_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject && ($array_atomic_type->value === 'Traversable' || $codebase->classOrInterfaceExists($array_atomic_type->value) && $codebase->classImplements($array_atomic_type->value, 'Traversable'))) { self::getKeyValueParamsForTraversableObject($array_atomic_type, $codebase, $key_type_part, $value_type_part); } } if (!$key_type_part || !$value_type_part) { break; } if (!$key_type) { $key_type = $key_type_part; } else { $key_type = \Psalm\Type::combineUnionTypes($key_type, $key_type_part); } if (!$value_type) { $value_type = $value_type_part; } else { $value_type = \Psalm\Type::combineUnionTypes($value_type, $value_type_part); } } } } elseif ($codebase->classImplements($iterator_atomic_type->value, 'Iterator') || $codebase->interfaceExists($iterator_atomic_type->value) && $codebase->interfaceExtends($iterator_atomic_type->value, 'Iterator')) { $iterator_value_type = self::getFakeMethodCallType($statements_analyzer, $foreach_expr, $context, 'current'); $iterator_key_type = self::getFakeMethodCallType($statements_analyzer, $foreach_expr, $context, 'key'); if ($iterator_value_type && !$iterator_value_type->isMixed()) { if (!$value_type) { $value_type = $iterator_value_type; } else { $value_type = \Psalm\Type::combineUnionTypes($value_type, $iterator_value_type); } } if ($iterator_key_type && !$iterator_key_type->isMixed()) { if (!$key_type) { $key_type = $iterator_key_type; } else { $key_type = \Psalm\Type::combineUnionTypes($key_type, $iterator_key_type); } } } if (!$key_type && !$value_type) { self::getKeyValueParamsForTraversableObject($iterator_atomic_type, $codebase, $key_type, $value_type); } return; } if (!$codebase->classlikes->classOrInterfaceExists($iterator_atomic_type->value)) { return; } } } public static function getKeyValueParamsForTraversableObject(\Psalm\Type\Atomic $iterator_atomic_type, \Psalm\Codebase $codebase, ?\Psalm\Type\Union &$key_type, ?\Psalm\Type\Union &$value_type) : void { if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TIterable || $iterator_atomic_type instanceof \Psalm\Type\Atomic\TGenericObject && \strtolower($iterator_atomic_type->value) === 'traversable') { $value_type_part = $iterator_atomic_type->type_params[1]; if (!$value_type) { $value_type = $value_type_part; } else { $value_type = \Psalm\Type::combineUnionTypes($value_type, $value_type_part); } $key_type_part = $iterator_atomic_type->type_params[0]; if (!$key_type) { $key_type = $key_type_part; } else { $key_type = \Psalm\Type::combineUnionTypes($key_type, $key_type_part); } return; } if ($iterator_atomic_type instanceof \Psalm\Type\Atomic\TNamedObject && ($codebase->classImplements($iterator_atomic_type->value, 'Traversable') || $codebase->interfaceExtends($iterator_atomic_type->value, 'Traversable'))) { $generic_storage = $codebase->classlike_storage_provider->get($iterator_atomic_type->value); if (!isset($generic_storage->template_type_extends['Traversable'])) { return; } if ($generic_storage->template_types || $iterator_atomic_type instanceof \Psalm\Type\Atomic\TGenericObject) { // if we're just being passed the non-generic class itself, assume // that it's inside the calling class $passed_type_params = $iterator_atomic_type instanceof \Psalm\Type\Atomic\TGenericObject ? $iterator_atomic_type->type_params : \array_values(\array_map( /** @param array $arr */ function (array $arr) use($iterator_atomic_type) : Type\Union { if (isset($arr[$iterator_atomic_type->value])) { return $arr[$iterator_atomic_type->value][0]; } return \Psalm\Type::getMixed(); }, $generic_storage->template_types )); } else { $passed_type_params = null; } $key_type = self::getExtendedType('TKey', 'Traversable', $generic_storage->name, $generic_storage->template_type_extends, $generic_storage->template_types, $passed_type_params); $value_type = self::getExtendedType('TValue', 'Traversable', $generic_storage->name, $generic_storage->template_type_extends, $generic_storage->template_types, $passed_type_params); return; } } private static function getFakeMethodCallType(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $foreach_expr, \Psalm\Context $context, string $method_name) : ?\Psalm\Type\Union { $old_data_provider = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $statements_analyzer->node_data; $fake_method_call = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall($foreach_expr, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($method_name, $foreach_expr->getAttributes())); $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('PossiblyUndefinedMethod', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['PossiblyUndefinedMethod']); } $was_inside_call = $context->inside_call; $context->inside_call = \true; \Psalm\Internal\Analyzer\Statements\Expression\Call\MethodCallAnalyzer::analyze($statements_analyzer, $fake_method_call, $context); $context->inside_call = $was_inside_call; if (!\in_array('PossiblyInvalidMethodCall', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyInvalidMethodCall']); } if (!\in_array('PossiblyUndefinedMethod', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['PossiblyUndefinedMethod']); } $iterator_class_type = $statements_analyzer->node_data->getType($fake_method_call) ?: null; $statements_analyzer->node_data = $old_data_provider; return $iterator_class_type; } /** * @param array> $template_type_extends * @param array> $class_template_types * @param array $calling_type_params */ private static function getExtendedType(string $template_name, string $template_class, string $calling_class, array $template_type_extends, ?array $class_template_types = null, ?array $calling_type_params = null) : ?\Psalm\Type\Union { if ($calling_class === $template_class) { if (isset($class_template_types[$template_name]) && $calling_type_params) { $offset = \array_search($template_name, \array_keys($class_template_types)); if ($offset !== \false && isset($calling_type_params[$offset])) { return $calling_type_params[$offset]; } } return null; } if (isset($template_type_extends[$template_class][$template_name])) { $extended_type = $template_type_extends[$template_class][$template_name]; $return_type = null; foreach ($extended_type->getAtomicTypes() as $extended_atomic_type) { if (!$extended_atomic_type instanceof \Psalm\Type\Atomic\TTemplateParam) { if (!$return_type) { $return_type = $extended_type; } else { $return_type = \Psalm\Type::combineUnionTypes($return_type, $extended_type); } continue; } $candidate_type = self::getExtendedType($extended_atomic_type->param_name, $extended_atomic_type->defining_class, $calling_class, $template_type_extends, $class_template_types, $calling_type_params); if ($candidate_type) { if (!$return_type) { $return_type = $candidate_type; } else { $return_type = \Psalm\Type::combineUnionTypes($return_type, $candidate_type); } } } if ($return_type) { return $return_type; } } return null; } } getCodebase(); $if_scope = new \Psalm\Internal\Scope\IfScope(); // We need to clone the original context for later use if we're exiting in this if conditional if (!$stmt->else && !$stmt->elseifs && $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr) { $final_actions = \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($stmt->stmts, $statements_analyzer->node_data, $codebase->config->exit_functions, $context->break_types); $has_leaving_statements = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END] || \count($final_actions) && !\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE, $final_actions, \true); if ($has_leaving_statements) { $if_scope->mic_drop_context = clone $context; } } try { $if_conditional_scope = self::analyzeIfConditional($statements_analyzer, $stmt->cond, $context, $codebase, $if_scope, $context->branch_point ?: (int) $stmt->getAttribute('startFilePos')); $if_context = $if_conditional_scope->if_context; $original_context = $if_conditional_scope->original_context; $cond_referenced_var_ids = $if_conditional_scope->cond_referenced_var_ids; $cond_assigned_var_ids = $if_conditional_scope->cond_assigned_var_ids; } catch (\Psalm\Exception\ScopeAnalysisException $e) { return \false; } $mixed_var_ids = []; foreach ($if_context->vars_in_scope as $var_id => $type) { if ($type->hasMixed() && isset($context->vars_in_scope[$var_id])) { $mixed_var_ids[] = $var_id; } } $cond_object_id = \spl_object_id($stmt->cond); $if_clauses = \Psalm\Type\Algebra::getFormula($cond_object_id, $cond_object_id, $stmt->cond, $context->self, $statements_analyzer, $codebase); if (\count($if_clauses) > 200) { $if_clauses = []; } $if_clauses = \array_values(\array_map( /** * @return Clause */ function (\Psalm\Internal\Clause $c) use($mixed_var_ids, $cond_object_id) : Clause { $keys = \array_keys($c->possibilities); $mixed_var_ids = \array_diff($mixed_var_ids, $keys); foreach ($keys as $key) { foreach ($mixed_var_ids as $mixed_var_id) { if (\preg_match('/^' . \preg_quote($mixed_var_id, '/') . '(\\[|-)/', $key)) { return new \Psalm\Internal\Clause([], $cond_object_id, $cond_object_id, \true); } } } return $c; }, $if_clauses )); $entry_clauses = $context->clauses; // this will see whether any of the clauses in set A conflict with the clauses in set B \Psalm\Internal\Analyzer\AlgebraAnalyzer::checkForParadox($context->clauses, $if_clauses, $statements_analyzer, $stmt->cond, $cond_assigned_var_ids); // if we have assignments in the if, we may have duplicate clauses if ($cond_assigned_var_ids) { $if_clauses = \Psalm\Type\Algebra::simplifyCNF($if_clauses); } $if_context_clauses = \array_merge($entry_clauses, $if_clauses); $if_context->clauses = \Psalm\Type\Algebra::simplifyCNF($if_context_clauses); if ($if_context->reconciled_expression_clauses) { $reconciled_expression_clauses = $if_context->reconciled_expression_clauses; $if_context->clauses = \array_values(\array_filter($if_context->clauses, function ($c) use($reconciled_expression_clauses) : bool { return !\in_array($c->hash, $reconciled_expression_clauses); })); if (\count($if_context->clauses) === 1 && $if_context->clauses[0]->wedge && !$if_context->clauses[0]->possibilities) { $if_context->clauses = []; $if_context->reconciled_expression_clauses = []; } } // define this before we alter local claues after reconciliation $if_scope->reasonable_clauses = $if_context->clauses; try { $if_scope->negated_clauses = \Psalm\Type\Algebra::negateFormula($if_clauses); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { try { $if_scope->negated_clauses = \Psalm\Type\Algebra::getFormula($cond_object_id, $cond_object_id, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($stmt->cond), $context->self, $statements_analyzer, $codebase, \false); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { $if_scope->negated_clauses = []; } } $if_scope->negated_types = \Psalm\Type\Algebra::getTruthsFromFormula(\Psalm\Type\Algebra::simplifyCNF(\array_merge($context->clauses, $if_scope->negated_clauses))); $active_if_types = []; $reconcilable_if_types = \Psalm\Type\Algebra::getTruthsFromFormula($if_context->clauses, \spl_object_id($stmt->cond), $cond_referenced_var_ids, $active_if_types); if (\array_filter($context->clauses, function ($clause) : bool { return !!$clause->possibilities; })) { $omit_keys = \array_reduce( $context->clauses, /** * @param array $carry * @return array */ function (array $carry, \Psalm\Internal\Clause $clause) : array { return \array_merge($carry, \array_keys($clause->possibilities)); }, [] ); $omit_keys = \array_combine($omit_keys, $omit_keys); $omit_keys = \array_diff_key($omit_keys, \Psalm\Type\Algebra::getTruthsFromFormula($context->clauses)); $cond_referenced_var_ids = \array_diff_key($cond_referenced_var_ids, $omit_keys); } // if the if has an || in the conditional, we cannot easily reason about it if ($reconcilable_if_types) { $changed_var_ids = []; $if_vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($reconcilable_if_types, $active_if_types, $if_context->vars_in_scope, $changed_var_ids, $cond_referenced_var_ids, $statements_analyzer, $statements_analyzer->getTemplateTypeMap() ?: [], $if_context->inside_loop, $context->check_variables ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot ? $stmt->cond->expr : $stmt->cond, $context->include_location) : null); $if_context->vars_in_scope = $if_vars_in_scope_reconciled; foreach ($reconcilable_if_types as $var_id => $_) { $if_context->vars_possibly_in_scope[$var_id] = \true; } if ($changed_var_ids) { $if_context->clauses = \Psalm\Context::removeReconciledClauses($if_context->clauses, $changed_var_ids)[0]; } $if_scope->if_cond_changed_var_ids = $changed_var_ids; } $old_if_context = clone $if_context; $context->vars_possibly_in_scope = \array_merge($if_context->vars_possibly_in_scope, $context->vars_possibly_in_scope); $context->referenced_var_ids = \array_merge($if_context->referenced_var_ids, $context->referenced_var_ids); $temp_else_context = clone $original_context; $changed_var_ids = []; if ($if_scope->negated_types) { $else_vars_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($if_scope->negated_types, [], $temp_else_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, $statements_analyzer->getTemplateTypeMap() ?: [], $context->inside_loop, $context->check_variables ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot ? $stmt->cond->expr : $stmt->cond, $context->include_location) : null); $temp_else_context->vars_in_scope = $else_vars_reconciled; } // we calculate the vars redefined in a hypothetical else statement to determine // which vars of the if we can safely change $pre_assignment_else_redefined_vars = \array_intersect_key($temp_else_context->getRedefinedVars($context->vars_in_scope, \true), $changed_var_ids); // check the if if (self::analyzeIfBlock($statements_analyzer, $stmt, $if_scope, $if_conditional_scope, $if_context, $old_if_context, $context, $pre_assignment_else_redefined_vars) === \false) { return \false; } // check the else $else_context = clone $original_context; // check the elseifs foreach ($stmt->elseifs as $elseif) { if (self::analyzeElseIfBlock($statements_analyzer, $elseif, $if_scope, $else_context, $context, $codebase, $else_context->branch_point ?: (int) $stmt->getAttribute('startFilePos')) === \false) { return \false; } } if ($stmt->else) { if ($codebase->alter_code) { $else_context->branch_point = $else_context->branch_point ?: (int) $stmt->getAttribute('startFilePos'); } } if (self::analyzeElseBlock($statements_analyzer, $stmt->else, $if_scope, $else_context, $context) === \false) { return \false; } if ($context->loop_scope) { $context->loop_scope->final_actions = \array_unique(\array_merge($context->loop_scope->final_actions, $if_scope->final_actions)); } $context->vars_possibly_in_scope = \array_merge($context->vars_possibly_in_scope, $if_scope->new_vars_possibly_in_scope); $context->possibly_assigned_var_ids = \array_merge($context->possibly_assigned_var_ids, $if_scope->possibly_assigned_var_ids ?: []); // vars can only be defined/redefined if there was an else (defined in every block) $context->assigned_var_ids = \array_merge($context->assigned_var_ids, $if_scope->assigned_var_ids ?: []); if ($if_scope->new_vars) { foreach ($if_scope->new_vars as $var_id => $type) { if (isset($context->vars_possibly_in_scope[$var_id]) && $statements_analyzer->data_flow_graph) { $type->parent_nodes += $statements_analyzer->getParentNodesForPossiblyUndefinedVariable($var_id); } $context->vars_in_scope[$var_id] = $type; } } if ($if_scope->redefined_vars) { foreach ($if_scope->redefined_vars as $var_id => $type) { $context->vars_in_scope[$var_id] = $type; $if_scope->updated_vars[$var_id] = \true; if ($if_scope->reasonable_clauses) { $if_scope->reasonable_clauses = \Psalm\Context::filterClauses($var_id, $if_scope->reasonable_clauses, isset($context->vars_in_scope[$var_id]) ? $context->vars_in_scope[$var_id] : null, $statements_analyzer); } } } if ($if_scope->possible_param_types) { foreach ($if_scope->possible_param_types as $var => $type) { $context->possible_param_types[$var] = $type; } } if ($if_scope->reasonable_clauses && (\count($if_scope->reasonable_clauses) > 1 || !$if_scope->reasonable_clauses[0]->wedge)) { $context->clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($if_scope->reasonable_clauses, $context->clauses)); } if ($if_scope->possibly_redefined_vars) { foreach ($if_scope->possibly_redefined_vars as $var_id => $type) { if (isset($context->vars_in_scope[$var_id])) { if (!$type->failed_reconciliation && !isset($if_scope->updated_vars[$var_id])) { $combined_type = \Psalm\Type::combineUnionTypes($context->vars_in_scope[$var_id], $type, $codebase); if (!$combined_type->equals($context->vars_in_scope[$var_id])) { $context->removeDescendents($var_id, $combined_type); } $context->vars_in_scope[$var_id] = $combined_type; } else { $context->vars_in_scope[$var_id]->parent_nodes += $type->parent_nodes; } } } } $context->possibly_assigned_var_ids += $if_scope->possibly_assigned_var_ids; if (!\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE, $if_scope->final_actions, \true)) { $context->has_returned = \true; } return null; } public static function analyzeIfConditional(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $cond, \Psalm\Context $outer_context, \Psalm\Codebase $codebase, \Psalm\Internal\Scope\IfScope $if_scope, ?int $branch_point) : \Psalm\Internal\Scope\IfConditionalScope { $entry_clauses = []; // used when evaluating elseifs if ($if_scope->negated_clauses) { $entry_clauses = \array_merge($outer_context->clauses, $if_scope->negated_clauses); $changed_var_ids = []; if ($if_scope->negated_types) { $vars_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($if_scope->negated_types, [], $outer_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, [], $outer_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot ? $cond->expr : $cond, $outer_context->include_location, \false)); if ($changed_var_ids) { $outer_context = clone $outer_context; $outer_context->vars_in_scope = $vars_reconciled; $entry_clauses = \array_values(\array_filter($entry_clauses, function (\Psalm\Internal\Clause $c) use($changed_var_ids) : bool { return \count($c->possibilities) > 1 || $c->wedge || !isset($changed_var_ids[\array_keys($c->possibilities)[0]]); })); } } } // get the first expression in the if, which should be evaluated on its own // this allows us to update the context of $matches in // if (!preg_match('/a/', 'aa', $matches)) { // exit // } // echo $matches[0]; $externally_applied_if_cond_expr = self::getDefinitelyEvaluatedExpressionAfterIf($cond); $internally_applied_if_cond_expr = self::getDefinitelyEvaluatedExpressionInsideIf($cond); $was_inside_conditional = $outer_context->inside_conditional; $outer_context->inside_conditional = \true; $pre_condition_vars_in_scope = $outer_context->vars_in_scope; $referenced_var_ids = $outer_context->referenced_var_ids; $outer_context->referenced_var_ids = []; $pre_assigned_var_ids = $outer_context->assigned_var_ids; $outer_context->assigned_var_ids = []; $if_context = null; if ($internally_applied_if_cond_expr !== $externally_applied_if_cond_expr) { $if_context = clone $outer_context; } if ($externally_applied_if_cond_expr) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $externally_applied_if_cond_expr, $outer_context) === \false) { throw new \Psalm\Exception\ScopeAnalysisException(); } } $first_cond_assigned_var_ids = $outer_context->assigned_var_ids; $outer_context->assigned_var_ids = \array_merge($pre_assigned_var_ids, $first_cond_assigned_var_ids); $first_cond_referenced_var_ids = $outer_context->referenced_var_ids; $outer_context->referenced_var_ids = \array_merge($referenced_var_ids, $first_cond_referenced_var_ids); if (!$was_inside_conditional) { $outer_context->inside_conditional = \false; } if (!$if_context) { $if_context = clone $outer_context; } $if_conditional_context = clone $if_context; $if_conditional_context->if_context = $if_context; $if_conditional_context->if_scope = $if_scope; if ($codebase->alter_code) { $if_context->branch_point = $branch_point; } // we need to clone the current context so our ongoing updates // to $outer_context don't mess with elseif/else blocks $original_context = clone $outer_context; if ($internally_applied_if_cond_expr !== $cond || $externally_applied_if_cond_expr !== $cond) { $assigned_var_ids = $first_cond_assigned_var_ids; $if_conditional_context->assigned_var_ids = []; $referenced_var_ids = $first_cond_referenced_var_ids; $if_conditional_context->referenced_var_ids = []; $if_conditional_context->inside_conditional = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $cond, $if_conditional_context) === \false) { throw new \Psalm\Exception\ScopeAnalysisException(); } $if_conditional_context->inside_conditional = \false; /** @var array */ $more_cond_referenced_var_ids = $if_conditional_context->referenced_var_ids; $if_conditional_context->referenced_var_ids = \array_merge($more_cond_referenced_var_ids, $referenced_var_ids); $cond_referenced_var_ids = \array_merge($first_cond_referenced_var_ids, $more_cond_referenced_var_ids); /** @var array */ $more_cond_assigned_var_ids = $if_conditional_context->assigned_var_ids; $if_conditional_context->assigned_var_ids = \array_merge($more_cond_assigned_var_ids, $assigned_var_ids); $cond_assigned_var_ids = \array_merge($first_cond_assigned_var_ids, $more_cond_assigned_var_ids); } else { $cond_referenced_var_ids = $first_cond_referenced_var_ids; $cond_assigned_var_ids = $first_cond_assigned_var_ids; } $newish_var_ids = \array_map( /** * @param Type\Union $_ * * @return true */ function (\Psalm\Type\Union $_) : bool { return \true; }, \array_diff_key($if_conditional_context->vars_in_scope, $pre_condition_vars_in_scope, $cond_referenced_var_ids, $cond_assigned_var_ids) ); $cond_type = $statements_analyzer->node_data->getType($cond); if ($cond_type !== null) { if ($cond_type->isFalse()) { if ($cond_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DocblockTypeContradiction('if (false) is impossible', new \Psalm\CodeLocation($statements_analyzer, $cond), 'false falsy'), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TypeDoesNotContainType('if (false) is impossible', new \Psalm\CodeLocation($statements_analyzer, $cond), 'false falsy'), $statements_analyzer->getSuppressedIssues())) { // fall through } } } elseif ($cond_type->isTrue()) { if ($cond_type->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantConditionGivenDocblockType('if (true) is redundant', new \Psalm\CodeLocation($statements_analyzer, $cond), 'true falsy'), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\RedundantCondition('if (true) is redundant', new \Psalm\CodeLocation($statements_analyzer, $cond), 'true falsy'), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } // get all the var ids that were referened in the conditional, but not assigned in it $cond_referenced_var_ids = \array_diff_key($cond_referenced_var_ids, $cond_assigned_var_ids); $cond_referenced_var_ids = \array_merge($newish_var_ids, $cond_referenced_var_ids); return new \Psalm\Internal\Scope\IfConditionalScope($if_context, $original_context, $cond_referenced_var_ids, $cond_assigned_var_ids, $entry_clauses); } /** * @param array $pre_assignment_else_redefined_vars * * @return false|null */ protected static function analyzeIfBlock(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_ $stmt, \Psalm\Internal\Scope\IfScope $if_scope, \Psalm\Internal\Scope\IfConditionalScope $if_conditional_scope, \Psalm\Context $if_context, \Psalm\Context $old_if_context, \Psalm\Context $outer_context, array $pre_assignment_else_redefined_vars) : ?bool { $codebase = $statements_analyzer->getCodebase(); $if_context->parent_context = $outer_context; $assigned_var_ids = $if_context->assigned_var_ids; $possibly_assigned_var_ids = $if_context->possibly_assigned_var_ids; $if_context->assigned_var_ids = []; $if_context->possibly_assigned_var_ids = []; if ($statements_analyzer->analyze($stmt->stmts, $if_context) === \false) { return \false; } $final_actions = \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($stmt->stmts, $statements_analyzer->node_data, $codebase->config->exit_functions, $outer_context->break_types); $has_ending_statements = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END]; $has_leaving_statements = $has_ending_statements || \count($final_actions) && !\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE, $final_actions, \true); $has_break_statement = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK]; $has_continue_statement = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE]; $if_scope->final_actions = $final_actions; /** @var array */ $new_assigned_var_ids = $if_context->assigned_var_ids; /** @var array */ $new_possibly_assigned_var_ids = $if_context->possibly_assigned_var_ids; $if_context->assigned_var_ids = \array_merge($assigned_var_ids, $new_assigned_var_ids); $if_context->possibly_assigned_var_ids = \array_merge($possibly_assigned_var_ids, $new_possibly_assigned_var_ids); foreach ($if_context->byref_constraints as $var_id => $byref_constraint) { if (isset($outer_context->byref_constraints[$var_id]) && $byref_constraint->type && ($outer_constraint_type = $outer_context->byref_constraints[$var_id]->type) && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $byref_constraint->type, $outer_constraint_type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ConflictingReferenceConstraint('There is more than one pass-by-reference constraint on ' . $var_id, new \Psalm\CodeLocation($statements_analyzer, $stmt, $outer_context->include_location, \true)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { $outer_context->byref_constraints[$var_id] = $byref_constraint; } } $mic_drop = \false; if (!$has_leaving_statements) { $if_scope->new_vars = \array_diff_key($if_context->vars_in_scope, $outer_context->vars_in_scope); $if_scope->redefined_vars = $if_context->getRedefinedVars($outer_context->vars_in_scope); $if_scope->possibly_redefined_vars = $if_scope->redefined_vars; $if_scope->assigned_var_ids = $new_assigned_var_ids; $if_scope->possibly_assigned_var_ids = $new_possibly_assigned_var_ids; $changed_var_ids = $new_assigned_var_ids; // if the variable was only set in the conditional, it's not possibly redefined foreach ($if_scope->possibly_redefined_vars as $var_id => $_) { if (!isset($new_possibly_assigned_var_ids[$var_id]) && isset($if_scope->if_cond_changed_var_ids[$var_id])) { unset($if_scope->possibly_redefined_vars[$var_id]); } } if ($if_scope->reasonable_clauses) { // remove all reasonable clauses that would be negated by the if stmts foreach ($changed_var_ids as $var_id => $_) { $if_scope->reasonable_clauses = \Psalm\Context::filterClauses($var_id, $if_scope->reasonable_clauses, isset($if_context->vars_in_scope[$var_id]) ? $if_context->vars_in_scope[$var_id] : null, $statements_analyzer); } } } else { if (!$has_break_statement) { $if_scope->reasonable_clauses = []; } } if ($has_leaving_statements && !$has_break_statement && !$stmt->else && !$stmt->elseifs) { // If we're assigning inside if ($if_conditional_scope->cond_assigned_var_ids && $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr && $if_scope->mic_drop_context) { self::addConditionallyAssignedVarsToContext($statements_analyzer, $stmt->cond, $if_scope->mic_drop_context, $outer_context, $if_conditional_scope->cond_assigned_var_ids); } if ($if_scope->negated_types) { $changed_var_ids = []; $outer_context_vars_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($if_scope->negated_types, [], $outer_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, $statements_analyzer->getTemplateTypeMap() ?: [], $outer_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot ? $stmt->cond->expr : $stmt->cond, $outer_context->include_location, \false)); foreach ($changed_var_ids as $changed_var_id => $_) { $outer_context->removeVarFromConflictingClauses($changed_var_id); } $changed_var_ids += $new_assigned_var_ids; foreach ($changed_var_ids as $var_id => $_) { $if_scope->negated_clauses = \Psalm\Context::filterClauses($var_id, $if_scope->negated_clauses); } foreach ($changed_var_ids as $var_id => $_) { $first_appearance = $statements_analyzer->getFirstAppearance($var_id); if ($first_appearance && isset($outer_context->vars_in_scope[$var_id]) && isset($outer_context_vars_reconciled[$var_id]) && $outer_context->vars_in_scope[$var_id]->hasMixed() && !$outer_context_vars_reconciled[$var_id]->hasMixed()) { if (!$outer_context->collect_initializations && !$outer_context->collect_mutations && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath() && (!($parent_source = $statements_analyzer->getSource()) instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer || !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)) { $codebase->analyzer->decrementMixedCount($statements_analyzer->getFilePath()); } \Psalm\IssueBuffer::remove($statements_analyzer->getFilePath(), 'MixedAssignment', $first_appearance->raw_file_start); } } $outer_context->vars_in_scope = $outer_context_vars_reconciled; $mic_drop = \true; } $outer_context->clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($outer_context->clauses, $if_scope->negated_clauses)); } // update the parent context as necessary, but only if we can safely reason about type negation. // We only update vars that changed both at the start of the if block and then again by an assignment // in the if statement. if ($if_scope->negated_types && !$mic_drop) { $vars_to_update = \array_intersect(\array_keys($pre_assignment_else_redefined_vars), \array_keys($if_scope->negated_types)); $extra_vars_to_update = []; // if there's an object-like array in there, we also need to update the root array variable foreach ($vars_to_update as $var_id) { $bracked_pos = \strpos($var_id, '['); if ($bracked_pos !== \false) { $extra_vars_to_update[] = \substr($var_id, 0, $bracked_pos); } } if ($extra_vars_to_update) { $vars_to_update = \array_unique(\array_merge($extra_vars_to_update, $vars_to_update)); } //update $if_context vars to include the pre-assignment else vars if (!$stmt->else && !$has_leaving_statements) { foreach ($pre_assignment_else_redefined_vars as $var_id => $type) { if (isset($if_context->vars_in_scope[$var_id])) { $if_context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($if_context->vars_in_scope[$var_id], $type, $codebase); } } } $outer_context->update($old_if_context, $if_context, $has_leaving_statements, $vars_to_update, $if_scope->updated_vars); } if (!$has_ending_statements) { $vars_possibly_in_scope = \array_diff_key($if_context->vars_possibly_in_scope, $outer_context->vars_possibly_in_scope); if ($if_context->loop_scope) { if (!$has_continue_statement && !$has_break_statement) { $if_scope->new_vars_possibly_in_scope = $vars_possibly_in_scope; } $if_context->loop_scope->vars_possibly_in_scope = \array_merge($vars_possibly_in_scope, $if_context->loop_scope->vars_possibly_in_scope); } elseif (!$has_leaving_statements) { $if_scope->new_vars_possibly_in_scope = $vars_possibly_in_scope; } } if ($outer_context->collect_exceptions) { $outer_context->mergeExceptions($if_context); } return null; } /** * @param Context $elseif_context * * @return false|null */ protected static function analyzeElseIfBlock(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ElseIf_ $elseif, \Psalm\Internal\Scope\IfScope $if_scope, \Psalm\Context $else_context, \Psalm\Context $outer_context, \Psalm\Codebase $codebase, ?int $branch_point) : ?bool { $pre_conditional_context = clone $else_context; try { $if_conditional_scope = self::analyzeIfConditional($statements_analyzer, $elseif->cond, $else_context, $codebase, $if_scope, $branch_point); $elseif_context = $if_conditional_scope->if_context; $cond_referenced_var_ids = $if_conditional_scope->cond_referenced_var_ids; $cond_assigned_var_ids = $if_conditional_scope->cond_assigned_var_ids; $entry_clauses = $if_conditional_scope->entry_clauses; } catch (\Psalm\Exception\ScopeAnalysisException $e) { return \false; } $mixed_var_ids = []; foreach ($elseif_context->vars_in_scope as $var_id => $type) { if ($type->hasMixed()) { $mixed_var_ids[] = $var_id; } } $elseif_cond_id = \spl_object_id($elseif->cond); $elseif_clauses = \Psalm\Type\Algebra::getFormula($elseif_cond_id, $elseif_cond_id, $elseif->cond, $else_context->self, $statements_analyzer, $codebase); $elseif_clauses = \array_map( /** * @return Clause */ function (\Psalm\Internal\Clause $c) use($mixed_var_ids, $elseif_cond_id) : Clause { $keys = \array_keys($c->possibilities); $mixed_var_ids = \array_diff($mixed_var_ids, $keys); foreach ($keys as $key) { foreach ($mixed_var_ids as $mixed_var_id) { if (\preg_match('/^' . \preg_quote($mixed_var_id, '/') . '(\\[|-)/', $key)) { return new \Psalm\Internal\Clause([], $elseif_cond_id, $elseif_cond_id, \true); } } } return $c; }, $elseif_clauses ); $entry_clauses = \array_map( /** * @return Clause */ function (\Psalm\Internal\Clause $c) use($cond_assigned_var_ids, $elseif_cond_id) : Clause { $keys = \array_keys($c->possibilities); foreach ($keys as $key) { foreach ($cond_assigned_var_ids as $conditional_assigned_var_id => $_) { if (\preg_match('/^' . \preg_quote($conditional_assigned_var_id, '/') . '(\\[|-|$)/', $key)) { return new \Psalm\Internal\Clause([], $elseif_cond_id, $elseif_cond_id, \true); } } } return $c; }, $entry_clauses ); // this will see whether any of the clauses in set A conflict with the clauses in set B \Psalm\Internal\Analyzer\AlgebraAnalyzer::checkForParadox($entry_clauses, $elseif_clauses, $statements_analyzer, $elseif->cond, $cond_assigned_var_ids); $elseif_context_clauses = \array_merge($entry_clauses, $elseif_clauses); if ($elseif_context->reconciled_expression_clauses) { $reconciled_expression_clauses = $elseif_context->reconciled_expression_clauses; $elseif_context_clauses = \array_values(\array_filter($elseif_context_clauses, function ($c) use($reconciled_expression_clauses) : bool { return !\in_array($c->hash, $reconciled_expression_clauses); })); } $elseif_context->clauses = \Psalm\Type\Algebra::simplifyCNF($elseif_context_clauses); $active_elseif_types = []; try { if (\array_filter($entry_clauses, function ($clause) : bool { return !!$clause->possibilities; })) { $omit_keys = \array_reduce( $entry_clauses, /** * @param array $carry * @return array */ function (array $carry, \Psalm\Internal\Clause $clause) : array { return \array_merge($carry, \array_keys($clause->possibilities)); }, [] ); $omit_keys = \array_combine($omit_keys, $omit_keys); $omit_keys = \array_diff_key($omit_keys, \Psalm\Type\Algebra::getTruthsFromFormula($entry_clauses)); $cond_referenced_var_ids = \array_diff_key($cond_referenced_var_ids, $omit_keys); } $reconcilable_elseif_types = \Psalm\Type\Algebra::getTruthsFromFormula($elseif_context->clauses, \spl_object_id($elseif->cond), $cond_referenced_var_ids, $active_elseif_types); $negated_elseif_types = \Psalm\Type\Algebra::getTruthsFromFormula(\Psalm\Type\Algebra::negateFormula($elseif_clauses)); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { $reconcilable_elseif_types = []; $negated_elseif_types = []; } $all_negated_vars = \array_unique(\array_merge(\array_keys($negated_elseif_types), \array_keys($if_scope->negated_types))); foreach ($all_negated_vars as $var_id) { if (isset($negated_elseif_types[$var_id])) { if (isset($if_scope->negated_types[$var_id])) { $if_scope->negated_types[$var_id] = \array_merge($if_scope->negated_types[$var_id], $negated_elseif_types[$var_id]); } else { $if_scope->negated_types[$var_id] = $negated_elseif_types[$var_id]; } } } $changed_var_ids = []; // if the elseif has an || in the conditional, we cannot easily reason about it if ($reconcilable_elseif_types) { $elseif_vars_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($reconcilable_elseif_types, $active_elseif_types, $elseif_context->vars_in_scope, $changed_var_ids, $cond_referenced_var_ids, $statements_analyzer, $statements_analyzer->getTemplateTypeMap() ?: [], $elseif_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $elseif->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot ? $elseif->cond->expr : $elseif->cond, $outer_context->include_location)); $elseif_context->vars_in_scope = $elseif_vars_reconciled; if ($changed_var_ids) { $elseif_context->clauses = \Psalm\Context::removeReconciledClauses($elseif_context->clauses, $changed_var_ids)[0]; } } $pre_stmts_assigned_var_ids = $elseif_context->assigned_var_ids; $elseif_context->assigned_var_ids = []; $pre_stmts_possibly_assigned_var_ids = $elseif_context->possibly_assigned_var_ids; $elseif_context->possibly_assigned_var_ids = []; if ($statements_analyzer->analyze($elseif->stmts, $elseif_context) === \false) { return \false; } /** @var array */ $new_stmts_assigned_var_ids = $elseif_context->assigned_var_ids; $elseif_context->assigned_var_ids = $pre_stmts_assigned_var_ids + $new_stmts_assigned_var_ids; /** @var array */ $new_stmts_possibly_assigned_var_ids = $elseif_context->possibly_assigned_var_ids; $elseif_context->possibly_assigned_var_ids = $pre_stmts_possibly_assigned_var_ids + $new_stmts_possibly_assigned_var_ids; foreach ($elseif_context->byref_constraints as $var_id => $byref_constraint) { if (isset($outer_context->byref_constraints[$var_id]) && ($outer_constraint_type = $outer_context->byref_constraints[$var_id]->type) && $byref_constraint->type && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $byref_constraint->type, $outer_constraint_type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ConflictingReferenceConstraint('There is more than one pass-by-reference constraint on ' . $var_id, new \Psalm\CodeLocation($statements_analyzer, $elseif, $outer_context->include_location, \true)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { $outer_context->byref_constraints[$var_id] = $byref_constraint; } } $final_actions = \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($elseif->stmts, $statements_analyzer->node_data, $codebase->config->exit_functions, $outer_context->break_types); // has a return/throw at end $has_ending_statements = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END]; $has_leaving_statements = $has_ending_statements || \count($final_actions) && !\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE, $final_actions, \true); $has_break_statement = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK]; $has_continue_statement = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE]; $if_scope->final_actions = \array_merge($final_actions, $if_scope->final_actions); // update the parent context as necessary $elseif_redefined_vars = $elseif_context->getRedefinedVars($outer_context->vars_in_scope); if (!$has_leaving_statements) { if ($if_scope->new_vars === null) { $if_scope->new_vars = \array_diff_key($elseif_context->vars_in_scope, $outer_context->vars_in_scope); } else { foreach ($if_scope->new_vars as $new_var => $type) { if (!$elseif_context->hasVariable($new_var)) { unset($if_scope->new_vars[$new_var]); } else { $if_scope->new_vars[$new_var] = \Psalm\Type::combineUnionTypes($type, $elseif_context->vars_in_scope[$new_var], $codebase); } } } $possibly_redefined_vars = $elseif_redefined_vars; foreach ($possibly_redefined_vars as $var_id => $_) { if (!isset($new_stmts_assigned_var_ids[$var_id]) && isset($changed_var_ids[$var_id])) { unset($possibly_redefined_vars[$var_id]); } } $assigned_var_ids = \array_merge($new_stmts_assigned_var_ids, $cond_assigned_var_ids); if ($if_scope->assigned_var_ids === null) { $if_scope->assigned_var_ids = $assigned_var_ids; } else { $if_scope->assigned_var_ids = \array_intersect_key($assigned_var_ids, $if_scope->assigned_var_ids); } if ($if_scope->redefined_vars === null) { $if_scope->redefined_vars = $elseif_redefined_vars; $if_scope->possibly_redefined_vars = $possibly_redefined_vars; } else { foreach ($if_scope->redefined_vars as $redefined_var => $type) { if (!isset($elseif_redefined_vars[$redefined_var])) { unset($if_scope->redefined_vars[$redefined_var]); } else { $if_scope->redefined_vars[$redefined_var] = \Psalm\Type::combineUnionTypes($elseif_redefined_vars[$redefined_var], $type, $codebase); if (isset($outer_context->vars_in_scope[$redefined_var]) && $if_scope->redefined_vars[$redefined_var]->equals($outer_context->vars_in_scope[$redefined_var])) { unset($if_scope->redefined_vars[$redefined_var]); } } } foreach ($possibly_redefined_vars as $var => $type) { if (isset($if_scope->possibly_redefined_vars[$var])) { $if_scope->possibly_redefined_vars[$var] = \Psalm\Type::combineUnionTypes($type, $if_scope->possibly_redefined_vars[$var], $codebase); } else { $if_scope->possibly_redefined_vars[$var] = $type; } } } $reasonable_clause_count = \count($if_scope->reasonable_clauses); if ($reasonable_clause_count && $reasonable_clause_count < 20000 && $elseif_clauses) { $if_scope->reasonable_clauses = \Psalm\Type\Algebra::combineOredClauses($if_scope->reasonable_clauses, $elseif_clauses, \spl_object_id($elseif->cond)); } else { $if_scope->reasonable_clauses = []; } } else { $if_scope->reasonable_clauses = []; } if ($negated_elseif_types) { if ($has_leaving_statements) { $changed_var_ids = []; $leaving_vars_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($negated_elseif_types, [], $pre_conditional_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, $statements_analyzer->getTemplateTypeMap() ?: [], $elseif_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $elseif, $outer_context->include_location)); $implied_outer_context = clone $elseif_context; $implied_outer_context->vars_in_scope = $leaving_vars_reconciled; $outer_context->update($elseif_context, $implied_outer_context, \false, \array_keys($negated_elseif_types), $if_scope->updated_vars); } } if (!$has_ending_statements) { $vars_possibly_in_scope = \array_diff_key($elseif_context->vars_possibly_in_scope, $outer_context->vars_possibly_in_scope); $possibly_assigned_var_ids = $new_stmts_possibly_assigned_var_ids; if ($has_leaving_statements && $elseif_context->loop_scope) { if (!$has_continue_statement && !$has_break_statement) { $if_scope->new_vars_possibly_in_scope = \array_merge($vars_possibly_in_scope, $if_scope->new_vars_possibly_in_scope); $if_scope->possibly_assigned_var_ids = \array_merge($possibly_assigned_var_ids, $if_scope->possibly_assigned_var_ids); } $elseif_context->loop_scope->vars_possibly_in_scope = \array_merge($vars_possibly_in_scope, $elseif_context->loop_scope->vars_possibly_in_scope); } elseif (!$has_leaving_statements) { $if_scope->new_vars_possibly_in_scope = \array_merge($vars_possibly_in_scope, $if_scope->new_vars_possibly_in_scope); $if_scope->possibly_assigned_var_ids = \array_merge($possibly_assigned_var_ids, $if_scope->possibly_assigned_var_ids); } } if ($outer_context->collect_exceptions) { $outer_context->mergeExceptions($elseif_context); } try { $if_scope->negated_clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($if_scope->negated_clauses, \Psalm\Type\Algebra::negateFormula($elseif_clauses))); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { $if_scope->negated_clauses = []; } return null; } /** * @return false|null */ protected static function analyzeElseBlock(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, ?\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Else_ $else, \Psalm\Internal\Scope\IfScope $if_scope, \Psalm\Context $else_context, \Psalm\Context $outer_context) : ?bool { $codebase = $statements_analyzer->getCodebase(); if (!$else && !$if_scope->negated_clauses && !$else_context->clauses) { $if_scope->final_actions = \array_merge([\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE], $if_scope->final_actions); $if_scope->assigned_var_ids = []; $if_scope->new_vars = []; $if_scope->redefined_vars = []; $if_scope->reasonable_clauses = []; return null; } $else_context->clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($else_context->clauses, $if_scope->negated_clauses)); $else_types = \Psalm\Type\Algebra::getTruthsFromFormula($else_context->clauses); if (!$else && !$else_types) { $if_scope->final_actions = \array_merge([\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE], $if_scope->final_actions); $if_scope->assigned_var_ids = []; $if_scope->new_vars = []; $if_scope->redefined_vars = []; $if_scope->reasonable_clauses = []; return null; } $original_context = clone $else_context; if ($else_types) { $changed_var_ids = []; $else_vars_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($else_types, [], $else_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, [], $else_context->inside_loop, $else ? new \Psalm\CodeLocation($statements_analyzer->getSource(), $else, $outer_context->include_location) : null); $else_context->vars_in_scope = $else_vars_reconciled; $else_context->clauses = \Psalm\Context::removeReconciledClauses($else_context->clauses, $changed_var_ids)[0]; } $old_else_context = clone $else_context; $pre_stmts_assigned_var_ids = $else_context->assigned_var_ids; $else_context->assigned_var_ids = []; $pre_possibly_assigned_var_ids = $else_context->possibly_assigned_var_ids; $else_context->possibly_assigned_var_ids = []; if ($else) { if ($statements_analyzer->analyze($else->stmts, $else_context) === \false) { return \false; } } /** @var array */ $new_assigned_var_ids = $else_context->assigned_var_ids; $else_context->assigned_var_ids = $pre_stmts_assigned_var_ids; /** @var array */ $new_possibly_assigned_var_ids = $else_context->possibly_assigned_var_ids; $else_context->possibly_assigned_var_ids = $pre_possibly_assigned_var_ids + $new_possibly_assigned_var_ids; if ($else) { foreach ($else_context->byref_constraints as $var_id => $byref_constraint) { if (isset($outer_context->byref_constraints[$var_id]) && ($outer_constraint_type = $outer_context->byref_constraints[$var_id]->type) && $byref_constraint->type && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $byref_constraint->type, $outer_constraint_type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ConflictingReferenceConstraint('There is more than one pass-by-reference constraint on ' . $var_id, new \Psalm\CodeLocation($statements_analyzer, $else, $outer_context->include_location, \true)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { $outer_context->byref_constraints[$var_id] = $byref_constraint; } } } $final_actions = $else ? \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($else->stmts, $statements_analyzer->node_data, $codebase->config->exit_functions, $outer_context->break_types) : [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE]; // has a return/throw at end $has_ending_statements = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END]; $has_leaving_statements = $has_ending_statements || \count($final_actions) && !\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_NONE, $final_actions, \true); $has_break_statement = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK]; $has_continue_statement = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE]; $if_scope->final_actions = \array_merge($final_actions, $if_scope->final_actions); $else_redefined_vars = $else_context->getRedefinedVars($original_context->vars_in_scope); // if it doesn't end in a return if (!$has_leaving_statements) { if ($if_scope->new_vars === null && $else) { $if_scope->new_vars = \array_diff_key($else_context->vars_in_scope, $outer_context->vars_in_scope); } elseif ($if_scope->new_vars !== null) { foreach ($if_scope->new_vars as $new_var => $type) { if (!$else_context->hasVariable($new_var)) { unset($if_scope->new_vars[$new_var]); } else { $if_scope->new_vars[$new_var] = \Psalm\Type::combineUnionTypes($type, $else_context->vars_in_scope[$new_var], $codebase); } } } if ($if_scope->assigned_var_ids === null) { $if_scope->assigned_var_ids = $new_assigned_var_ids; } else { $if_scope->assigned_var_ids = \array_intersect_key($new_assigned_var_ids, $if_scope->assigned_var_ids); } if ($if_scope->redefined_vars === null) { $if_scope->redefined_vars = $else_redefined_vars; $if_scope->possibly_redefined_vars = $if_scope->redefined_vars; } else { foreach ($if_scope->redefined_vars as $redefined_var => $type) { if (!isset($else_redefined_vars[$redefined_var])) { unset($if_scope->redefined_vars[$redefined_var]); } else { $if_scope->redefined_vars[$redefined_var] = \Psalm\Type::combineUnionTypes($else_redefined_vars[$redefined_var], $type, $codebase); } } foreach ($else_redefined_vars as $var => $type) { if (isset($if_scope->possibly_redefined_vars[$var])) { $if_scope->possibly_redefined_vars[$var] = \Psalm\Type::combineUnionTypes($type, $if_scope->possibly_redefined_vars[$var], $codebase); } else { $if_scope->possibly_redefined_vars[$var] = $type; } } } $if_scope->reasonable_clauses = []; } // update the parent context as necessary if ($if_scope->negatable_if_types) { $outer_context->update($old_else_context, $else_context, $has_leaving_statements, \array_keys($if_scope->negatable_if_types), $if_scope->updated_vars); } if (!$has_ending_statements) { $vars_possibly_in_scope = \array_diff_key($else_context->vars_possibly_in_scope, $outer_context->vars_possibly_in_scope); $possibly_assigned_var_ids = $new_possibly_assigned_var_ids; if ($has_leaving_statements && $else_context->loop_scope) { if (!$has_continue_statement && !$has_break_statement) { $if_scope->new_vars_possibly_in_scope = \array_merge($vars_possibly_in_scope, $if_scope->new_vars_possibly_in_scope); $if_scope->possibly_assigned_var_ids = \array_merge($possibly_assigned_var_ids, $if_scope->possibly_assigned_var_ids); } $else_context->loop_scope->vars_possibly_in_scope = \array_merge($vars_possibly_in_scope, $else_context->loop_scope->vars_possibly_in_scope); } elseif (!$has_leaving_statements) { $if_scope->new_vars_possibly_in_scope = \array_merge($vars_possibly_in_scope, $if_scope->new_vars_possibly_in_scope); $if_scope->possibly_assigned_var_ids = \array_merge($possibly_assigned_var_ids, $if_scope->possibly_assigned_var_ids); } } if ($outer_context->collect_exceptions) { $outer_context->mergeExceptions($else_context); } return null; } /** * Returns statements that are definitely evaluated before any statements after the end of the * if/elseif/else blocks */ private static function getDefinitelyEvaluatedExpressionAfterIf(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt) : ?\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { if ($stmt->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && $stmt->left->name->parts === ['true']) { return self::getDefinitelyEvaluatedExpressionAfterIf($stmt->right); } if ($stmt->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && $stmt->right->name->parts === ['true']) { return self::getDefinitelyEvaluatedExpressionAfterIf($stmt->left); } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalAnd || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor) { return self::getDefinitelyEvaluatedExpressionAfterIf($stmt->left); } return $stmt; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot) { $inner_stmt = self::getDefinitelyEvaluatedExpressionInsideIf($stmt->expr); if ($inner_stmt !== $stmt->expr) { return $inner_stmt; } } return $stmt; } /** * Returns statements that are definitely evaluated before any statements inside * the if block */ private static function getDefinitelyEvaluatedExpressionInsideIf(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt) : ?\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical) { if ($stmt->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && $stmt->left->name->parts === ['true']) { return self::getDefinitelyEvaluatedExpressionInsideIf($stmt->right); } if ($stmt->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && $stmt->right->name->parts === ['true']) { return self::getDefinitelyEvaluatedExpressionInsideIf($stmt->left); } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor) { return self::getDefinitelyEvaluatedExpressionInsideIf($stmt->left); } return $stmt; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot) { $inner_stmt = self::getDefinitelyEvaluatedExpressionAfterIf($stmt->expr); if ($inner_stmt !== $stmt->expr) { return $inner_stmt; } } return $stmt; } /** * Returns all expressions inside an ored expression * @return non-empty-list */ private static function getDefinitelyEvaluatedOredExpressions(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt) : array { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalOr || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\LogicalXor) { return \array_merge(self::getDefinitelyEvaluatedOredExpressions($stmt->left), self::getDefinitelyEvaluatedOredExpressions($stmt->right)); } return [$stmt]; } /** * @param array $cond_assigned_var_ids */ public static function addConditionallyAssignedVarsToContext(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $cond, \Psalm\Context $mic_drop_context, \Psalm\Context $outer_context, array $cond_assigned_var_ids) : void { // this filters out coercions to expeccted types in ArgumentAnalyzer $cond_assigned_var_ids = \array_filter($cond_assigned_var_ids); if (!$cond_assigned_var_ids) { return; } $exprs = self::getDefinitelyEvaluatedOredExpressions($cond); // if there was no assignment in the first expression it's safe to proceed $old_node_data = $statements_analyzer->node_data; $statements_analyzer->node_data = clone $old_node_data; $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantConditionGivenDocblockType']); } if (!\in_array('TypeDoesNotContainType', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['TypeDoesNotContainType']); } foreach ($exprs as $expr) { $fake_negated_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified('assert'), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($expr, $expr->getAttributes()), \false, \false, $expr->getAttributes())], $expr->getAttributes()); $mic_drop_context->inside_negation = !$mic_drop_context->inside_negation; \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $fake_negated_expr, $mic_drop_context); $mic_drop_context->inside_negation = !$mic_drop_context->inside_negation; } if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantConditionGivenDocblockType']); } if (!\in_array('TypeDoesNotContainType', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['TypeDoesNotContainType']); } $statements_analyzer->node_data = $old_node_data; foreach ($cond_assigned_var_ids as $var_id => $_) { if (isset($mic_drop_context->vars_in_scope[$var_id])) { $outer_context->vars_in_scope[$var_id] = clone $mic_drop_context->vars_in_scope[$var_id]; } } } } alter_code) { $case_context->branch_point = $case_context->branch_point ?: (int) $stmt->getAttribute('startFilePos'); } $case_context->parent_context = $context; $case_scope = $case_context->case_scope = new \Psalm\Internal\Scope\CaseScope($case_context); $case_equality_expr = null; $old_node_data = $statements_analyzer->node_data; $fake_switch_condition = \false; if ($switch_var_id && \substr($switch_var_id, 0, 15) === '$__tmp_switch__') { $switch_condition = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable(\substr($switch_var_id, 1), $stmt->cond->getAttributes()); $fake_switch_condition = \true; } else { $switch_condition = $stmt->cond; } if ($case->cond) { $was_inside_conditional = $case_context->inside_conditional; $case_context->inside_conditional = \true; if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $case->cond, $case_context) === \false) { /** @psalm-suppress PossiblyNullPropertyAssignmentValue */ $case_scope->parent_context = null; $case_context->case_scope = null; $case_context->parent_context = null; return \false; } if (!$was_inside_conditional) { $case_context->inside_conditional = \false; } $statements_analyzer->node_data = clone $statements_analyzer->node_data; $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $traverser->addVisitor(new \Psalm\Internal\PhpVisitor\ConditionCloningVisitor($statements_analyzer->node_data)); /** @var PhpParser\Node\Expr */ $switch_condition = $traverser->traverse([$switch_condition])[0]; if ($fake_switch_condition) { $statements_analyzer->node_data->setType($switch_condition, $case_context->vars_in_scope[$switch_var_id] ?? \Psalm\Type::getMixed()); } if ($switch_condition instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($switch_condition->name) && isset($context->vars_in_scope['$' . $switch_condition->name])) { $switch_var_type = $context->vars_in_scope['$' . $switch_condition->name]; $type_statements = []; foreach ($switch_var_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TDependentGetClass) { $type_statements[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name(['get_class']), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable(\substr($type->typeof, 1)))]); } elseif ($type instanceof \Psalm\Type\Atomic\TDependentGetType) { $type_statements[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name(['gettype']), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable(\substr($type->typeof, 1)))]); } elseif ($type instanceof \Psalm\Type\Atomic\TDependentGetDebugType) { $type_statements[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name(['get_debug_type']), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable(\substr($type->typeof, 1)))]); } else { $type_statements = null; break; } } if ($type_statements && \count($type_statements) === 1) { $switch_condition = $type_statements[0]; if ($fake_switch_condition) { $statements_analyzer->node_data->setType($switch_condition, $case_context->vars_in_scope[$switch_var_id] ?? \Psalm\Type::getMixed()); } } } if (($switch_condition_type = $statements_analyzer->node_data->getType($switch_condition)) && ($case_cond_type = $statements_analyzer->node_data->getType($case->cond)) && ($switch_condition_type->isString() && $case_cond_type->isString() || $switch_condition_type->isInt() && $case_cond_type->isInt() || $switch_condition_type->isFloat() && $case_cond_type->isFloat())) { $case_equality_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical($switch_condition, $case->cond, $case->cond->getAttributes()); } else { $case_equality_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal($switch_condition, $case->cond, $case->cond->getAttributes()); } } $continue_case_equality_expr = \false; if ($case->stmts) { $case_stmts = \array_merge($switch_scope->leftover_statements, $case->stmts); } else { $continue_case_equality_expr = \count($switch_scope->leftover_statements) === 1; $case_stmts = $switch_scope->leftover_statements; } if (!$has_leaving_statements && !$is_last) { if (!$case_equality_expr) { $case_equality_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified(['rand']), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(0)), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(1))], $case->getAttributes()); } $switch_scope->leftover_case_equality_expr = $switch_scope->leftover_case_equality_expr ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr($switch_scope->leftover_case_equality_expr, $case_equality_expr, $case->cond ? $case->cond->getAttributes() : $case->getAttributes()) : $case_equality_expr; if ($continue_case_equality_expr && $switch_scope->leftover_statements[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_) { $case_if_stmt = $switch_scope->leftover_statements[0]; $case_if_stmt->cond = $switch_scope->leftover_case_equality_expr; } else { $case_if_stmt = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_($switch_scope->leftover_case_equality_expr, ['stmts' => $case_stmts]); $switch_scope->leftover_statements = [$case_if_stmt]; } /** @psalm-suppress PossiblyNullPropertyAssignmentValue */ $case_scope->parent_context = null; $case_context->case_scope = null; $case_context->parent_context = null; $statements_analyzer->node_data = $old_node_data; return null; } if ($switch_scope->leftover_case_equality_expr) { $case_or_default_equality_expr = $case_equality_expr; if (!$case_or_default_equality_expr) { $case_or_default_equality_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified(['rand']), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(0)), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber(1))], $case->getAttributes()); } $case_equality_expr = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr($switch_scope->leftover_case_equality_expr, $case_or_default_equality_expr, $case_or_default_equality_expr->getAttributes()); } if ($case_equality_expr && $switch_condition instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($switch_condition->name) && isset($context->vars_in_scope['$' . $switch_condition->name])) { $new_case_equality_expr = self::simplifyCaseEqualityExpression($case_equality_expr, $switch_condition); if ($new_case_equality_expr) { \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $new_case_equality_expr->args[1]->value, $case_context); $case_equality_expr = $new_case_equality_expr; } } $case_context->break_types[] = 'switch'; $switch_scope->leftover_statements = []; $switch_scope->leftover_case_equality_expr = null; $case_clauses = []; if ($case_equality_expr) { $case_equality_expr_id = \spl_object_id($case_equality_expr); $case_clauses = \Psalm\Type\Algebra::getFormula($case_equality_expr_id, $case_equality_expr_id, $case_equality_expr, $context->self, $statements_analyzer, $codebase, \false, \false); } if ($switch_scope->negated_clauses && \count($switch_scope->negated_clauses) < 50) { $entry_clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($original_context->clauses, $switch_scope->negated_clauses)); } else { $entry_clauses = $original_context->clauses; } if ($case_clauses && $case->cond) { // this will see whether any of the clauses in set A conflict with the clauses in set B \Psalm\Internal\Analyzer\AlgebraAnalyzer::checkForParadox($entry_clauses, $case_clauses, $statements_analyzer, $case->cond, []); if (\count($entry_clauses) + \count($case_clauses) < 50) { $case_context->clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($entry_clauses, $case_clauses)); } else { $case_context->clauses = \array_merge($entry_clauses, $case_clauses); } } else { $case_context->clauses = $entry_clauses; } $reconcilable_if_types = \Psalm\Type\Algebra::getTruthsFromFormula($case_context->clauses); // if the if has an || in the conditional, we cannot easily reason about it if ($reconcilable_if_types) { $changed_var_ids = []; $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantConditionGivenDocblockType']); } $case_vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($reconcilable_if_types, [], $case_context->vars_in_scope, $changed_var_ids, $case->cond && $switch_var_id ? [$switch_var_id => \true] : [], $statements_analyzer, [], $case_context->inside_loop, new \Psalm\CodeLocation($statements_analyzer->getSource(), $case->cond ? $case->cond : $case, $context->include_location)); if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantConditionGivenDocblockType']); } $case_context->vars_in_scope = $case_vars_in_scope_reconciled; foreach ($reconcilable_if_types as $var_id => $_) { $case_context->vars_possibly_in_scope[$var_id] = \true; } if ($changed_var_ids) { $case_context->clauses = \Psalm\Context::removeReconciledClauses($case_context->clauses, $changed_var_ids)[0]; } } if ($case_clauses && $case_equality_expr) { try { $negated_case_clauses = \Psalm\Type\Algebra::negateFormula($case_clauses); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { $case_equality_expr_id = \spl_object_id($case_equality_expr); try { $negated_case_clauses = \Psalm\Type\Algebra::getFormula($case_equality_expr_id, $case_equality_expr_id, new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot($case_equality_expr), $context->self, $statements_analyzer, $codebase, \false, \false); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { $negated_case_clauses = []; } } $switch_scope->negated_clauses = \array_merge($switch_scope->negated_clauses, $negated_case_clauses); } $pre_possibly_assigned_var_ids = $case_context->possibly_assigned_var_ids; $case_context->possibly_assigned_var_ids = []; $pre_assigned_var_ids = $case_context->assigned_var_ids; $case_context->assigned_var_ids = []; $statements_analyzer->analyze($case_stmts, $case_context); $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $traverser->addVisitor(new \Psalm\Internal\PhpVisitor\TypeMappingVisitor($statements_analyzer->node_data, $old_node_data)); $traverser->traverse([$case]); $statements_analyzer->node_data = $old_node_data; /** @var array */ $new_case_assigned_var_ids = $case_context->assigned_var_ids; $case_context->assigned_var_ids = $pre_assigned_var_ids + $new_case_assigned_var_ids; /** @var array */ $new_case_possibly_assigned_var_ids = $case_context->possibly_assigned_var_ids; $case_context->possibly_assigned_var_ids = $pre_possibly_assigned_var_ids + $new_case_possibly_assigned_var_ids; $context->referenced_var_ids = \array_merge($context->referenced_var_ids, $case_context->referenced_var_ids); if ($case_exit_type !== 'return_throw') { if (self::handleNonReturningCase($statements_analyzer, $switch_var_id, $case, $context, $case_context, $original_context, $case_exit_type, $switch_scope) === \false) { /** @psalm-suppress PossiblyNullPropertyAssignmentValue */ $case_scope->parent_context = null; $case_context->case_scope = null; $case_context->parent_context = null; return \false; } } // augment the information with data from break statements if ($case_scope->break_vars !== null) { if ($switch_scope->possibly_redefined_vars === null) { $switch_scope->possibly_redefined_vars = \array_intersect_key($case_scope->break_vars, $context->vars_in_scope); } else { foreach ($case_scope->break_vars as $var_id => $type) { if (isset($context->vars_in_scope[$var_id])) { if (!isset($switch_scope->possibly_redefined_vars[$var_id])) { $switch_scope->possibly_redefined_vars[$var_id] = clone $type; } else { $switch_scope->possibly_redefined_vars[$var_id] = \Psalm\Type::combineUnionTypes(clone $type, $switch_scope->possibly_redefined_vars[$var_id]); } } } } if ($switch_scope->new_vars_in_scope !== null) { foreach ($switch_scope->new_vars_in_scope as $var_id => $type) { if (isset($case_scope->break_vars[$var_id])) { if (!isset($case_context->vars_in_scope[$var_id])) { unset($switch_scope->new_vars_in_scope[$var_id]); } else { $switch_scope->new_vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes(clone $case_scope->break_vars[$var_id], $type); } } else { unset($switch_scope->new_vars_in_scope[$var_id]); } } } if ($switch_scope->redefined_vars !== null) { foreach ($switch_scope->redefined_vars as $var_id => $type) { if (isset($case_scope->break_vars[$var_id])) { $switch_scope->redefined_vars[$var_id] = \Psalm\Type::combineUnionTypes(clone $case_scope->break_vars[$var_id], $type); } else { unset($switch_scope->redefined_vars[$var_id]); } } } } /** @psalm-suppress PossiblyNullPropertyAssignmentValue */ $case_scope->parent_context = null; $case_context->case_scope = null; $case_context->parent_context = null; return null; } /** * @param array $new_case_assigned_var_ids * @param array $new_case_possibly_assigned_var_ids * @return null|false */ private static function handleNonReturningCase(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, ?string $switch_var_id, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Case_ $case, \Psalm\Context $context, \Psalm\Context $case_context, \Psalm\Context $original_context, string $case_exit_type, \Psalm\Internal\Scope\SwitchScope $switch_scope) : ?bool { if (!$case->cond && $switch_var_id && isset($case_context->vars_in_scope[$switch_var_id]) && $case_context->vars_in_scope[$switch_var_id]->isEmpty()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ParadoxicalCondition('All possible case statements have been met, default is impossible here', new \Psalm\CodeLocation($statements_analyzer->getSource(), $case)), $statements_analyzer->getSuppressedIssues())) { return \false; } } // if we're leaving this block, add vars to outer for loop scope if ($case_exit_type === 'continue') { if (!$context->loop_scope) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ContinueOutsideLoop('Continue called when not in loop', new \Psalm\CodeLocation($statements_analyzer->getSource(), $case)))) { return \false; } } } else { $case_redefined_vars = $case_context->getRedefinedVars($original_context->vars_in_scope); if ($switch_scope->possibly_redefined_vars === null) { $switch_scope->possibly_redefined_vars = $case_redefined_vars; } else { foreach ($case_redefined_vars as $var_id => $type) { if (!isset($switch_scope->possibly_redefined_vars[$var_id])) { $switch_scope->possibly_redefined_vars[$var_id] = clone $type; } else { $switch_scope->possibly_redefined_vars[$var_id] = \Psalm\Type::combineUnionTypes(clone $type, $switch_scope->possibly_redefined_vars[$var_id]); } } } if ($switch_scope->redefined_vars === null) { $switch_scope->redefined_vars = $case_redefined_vars; } else { foreach ($switch_scope->redefined_vars as $var_id => $type) { if (!isset($case_redefined_vars[$var_id])) { unset($switch_scope->redefined_vars[$var_id]); } else { $switch_scope->redefined_vars[$var_id] = \Psalm\Type::combineUnionTypes($type, clone $case_redefined_vars[$var_id]); } } } $context_new_vars = \array_diff_key($case_context->vars_in_scope, $context->vars_in_scope); if ($switch_scope->new_vars_in_scope === null) { $switch_scope->new_vars_in_scope = $context_new_vars; $switch_scope->new_vars_possibly_in_scope = \array_diff_key($case_context->vars_possibly_in_scope, $context->vars_possibly_in_scope); } else { foreach ($switch_scope->new_vars_in_scope as $new_var => $type) { if (!$case_context->hasVariable($new_var)) { unset($switch_scope->new_vars_in_scope[$new_var]); } else { $switch_scope->new_vars_in_scope[$new_var] = \Psalm\Type::combineUnionTypes(clone $case_context->vars_in_scope[$new_var], $type); } } $switch_scope->new_vars_possibly_in_scope = \array_merge(\array_diff_key($case_context->vars_possibly_in_scope, $context->vars_possibly_in_scope), $switch_scope->new_vars_possibly_in_scope); } } if ($context->collect_exceptions) { $context->mergeExceptions($case_context); } return null; } private static function simplifyCaseEqualityExpression(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $case_equality_expr, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable $var) : ?\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall { if ($case_equality_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr) { $nested_or_options = self::getOptionsFromNestedOr($case_equality_expr, $var); if ($nested_or_options) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified(['in_array']), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg($var), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_($nested_or_options)), new \_HumbugBoxd02f763d3c56\PhpParser\Node\Arg(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified(['true'])))]); } } return null; } /** * @param array $in_array_values * @return ?array */ private static function getOptionsFromNestedOr(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $case_equality_expr, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable $var, array $in_array_values = []) : ?array { if ($case_equality_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical && $case_equality_expr->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $case_equality_expr->left->name === $var->name) { $in_array_values[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($case_equality_expr->right); return $in_array_values; } if (!$case_equality_expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr) { return null; } if (!$case_equality_expr->right instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Identical || !$case_equality_expr->right->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || $case_equality_expr->right->left->name !== $var->name) { return null; } $in_array_values[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayItem($case_equality_expr->right->right); return self::getOptionsFromNestedOr($case_equality_expr->left, $var, $in_array_values); } } break_types[] = 'loop'; $codebase = $statements_analyzer->getCodebase(); if ($codebase->alter_code) { $do_context->branch_point = $do_context->branch_point ?: (int) $stmt->getAttribute('startFilePos'); } $loop_scope = new \Psalm\Internal\Scope\LoopScope($do_context, $context); $loop_scope->protected_var_ids = $context->protected_var_ids; self::analyzeDoNaively($statements_analyzer, $stmt, $do_context, $loop_scope); $mixed_var_ids = []; foreach ($do_context->vars_in_scope as $var_id => $type) { if ($type->hasMixed()) { $mixed_var_ids[] = $var_id; } } $cond_id = \spl_object_id($stmt->cond); $while_clauses = \Psalm\Type\Algebra::getFormula($cond_id, $cond_id, $stmt->cond, $context->self, $statements_analyzer, $codebase); $while_clauses = \array_values(\array_filter($while_clauses, function (\Psalm\Internal\Clause $c) use($mixed_var_ids) : bool { $keys = \array_keys($c->possibilities); $mixed_var_ids = \array_diff($mixed_var_ids, $keys); foreach ($keys as $key) { foreach ($mixed_var_ids as $mixed_var_id) { if (\preg_match('/^' . \preg_quote($mixed_var_id, '/') . '(\\[|-)/', $key)) { return \false; } } } return \true; })); if (!$while_clauses) { $while_clauses = [new \Psalm\Internal\Clause([], $cond_id, $cond_id, \true)]; } \Psalm\Internal\Analyzer\Statements\Block\LoopAnalyzer::analyze($statements_analyzer, $stmt->stmts, [$stmt->cond], [], $loop_scope, $inner_loop_context, \true, \true); // because it's a do {} while, inner loop vars belong to the main context if (!$inner_loop_context) { throw new \UnexpectedValueException('Should never be null'); } $negated_while_clauses = \Psalm\Type\Algebra::negateFormula($while_clauses); $negated_while_types = \Psalm\Type\Algebra::getTruthsFromFormula(\Psalm\Type\Algebra::simplifyCNF(\array_merge($context->clauses, $negated_while_clauses))); //var_dump($do_context->vars_in_scope); if ($negated_while_types) { $changed_var_ids = []; $inner_loop_context->vars_in_scope = \Psalm\Type\Reconciler::reconcileKeyedTypes($negated_while_types, [], $inner_loop_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, [], \true, new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt->cond)); } foreach ($inner_loop_context->vars_in_scope as $var_id => $type) { // if there are break statements in the loop it's not certain // that the loop has finished executing, so the assertions at the end // the loop in the while conditional may not hold if (\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK, $loop_scope->final_actions, \true)) { if (isset($loop_scope->possibly_defined_loop_parent_vars[$var_id])) { $context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($type, $loop_scope->possibly_defined_loop_parent_vars[$var_id]); } } else { $context->vars_in_scope[$var_id] = $type; } } $do_context->loop_scope = null; $context->vars_possibly_in_scope = \array_merge($context->vars_possibly_in_scope, $do_context->vars_possibly_in_scope); $context->referenced_var_ids = \array_merge($context->referenced_var_ids, $do_context->referenced_var_ids); if ($context->collect_exceptions) { $context->mergeExceptions($inner_loop_context); } } private static function analyzeDoNaively(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Do_ $stmt, \Psalm\Context $context, \Psalm\Internal\Scope\LoopScope $loop_scope) : void { $do_context = clone $context; $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantConditionGivenDocblockType']); } if (!\in_array('TypeDoesNotContainType', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['TypeDoesNotContainType']); } $do_context->loop_scope = $loop_scope; $statements_analyzer->analyze($stmt->stmts, $do_context); if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantConditionGivenDocblockType']); } if (!\in_array('TypeDoesNotContainType', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['TypeDoesNotContainType']); } } } $stmts * @param PhpParser\Node\Expr[] $pre_conditions * @param PhpParser\Node\Expr[] $post_expressions * * @return false|null */ public static function analyze(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, array $stmts, array $pre_conditions, array $post_expressions, \Psalm\Internal\Scope\LoopScope $loop_scope, \Psalm\Context &$inner_context = null, bool $is_do = \false, bool $always_enters_loop = \false) : ?bool { $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $assignment_mapper = new \Psalm\Internal\PhpVisitor\AssignmentMapVisitor($loop_scope->loop_context->self); $traverser->addVisitor($assignment_mapper); $traverser->traverse(\array_merge($pre_conditions, $stmts, $post_expressions)); $assignment_map = $assignment_mapper->getAssignmentMap(); $assignment_depth = 0; $always_assigned_before_loop_body_vars = []; $pre_condition_clauses = []; $original_protected_var_ids = $loop_scope->loop_parent_context->protected_var_ids; $codebase = $statements_analyzer->getCodebase(); $inner_do_context = null; if ($pre_conditions) { foreach ($pre_conditions as $i => $pre_condition) { $pre_condition_id = \spl_object_id($pre_condition); $pre_condition_clauses[$i] = \Psalm\Type\Algebra::getFormula($pre_condition_id, $pre_condition_id, $pre_condition, $loop_scope->loop_context->self, $statements_analyzer, $codebase); } } else { $always_assigned_before_loop_body_vars = \Psalm\Context::getNewOrUpdatedVarIds($loop_scope->loop_parent_context, $loop_scope->loop_context); } $final_actions = \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($stmts, $statements_analyzer->node_data, \Psalm\Config::getInstance()->exit_functions, $loop_scope->loop_context->break_types); $does_always_break = $final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK]; $has_continue = \in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE, $final_actions, \true); if ($assignment_map) { $first_var_id = \array_keys($assignment_map)[0]; $assignment_depth = self::getAssignmentMapDepth($first_var_id, $assignment_map); } if ($has_continue) { // this intuuitively feels right to me – if there's a continue statement, // maybe more assignment intrigue is possible $assignment_depth++; } $loop_scope->loop_context->parent_context = $loop_scope->loop_parent_context; $pre_outer_context = $loop_scope->loop_parent_context; if ($assignment_depth === 0 || $does_always_break) { $inner_context = clone $loop_scope->loop_context; foreach ($inner_context->vars_in_scope as $context_var_id => $context_type) { $inner_context->vars_in_scope[$context_var_id] = clone $context_type; } $inner_context->loop_scope = $loop_scope; $inner_context->parent_context = $loop_scope->loop_context; $old_referenced_var_ids = $inner_context->referenced_var_ids; $inner_context->referenced_var_ids = []; foreach ($pre_conditions as $condition_offset => $pre_condition) { self::applyPreConditionToLoopContext($statements_analyzer, $pre_condition, $pre_condition_clauses[$condition_offset], $inner_context, $loop_scope->loop_parent_context, $is_do); } $inner_context->protected_var_ids = $loop_scope->protected_var_ids; $statements_analyzer->analyze($stmts, $inner_context); self::updateLoopScopeContexts($loop_scope, $loop_scope->loop_parent_context); foreach ($post_expressions as $post_expression) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $post_expression, $loop_scope->loop_context) === \false) { return \false; } } $inner_context->referenced_var_ids = $old_referenced_var_ids + $inner_context->referenced_var_ids; $loop_scope->loop_parent_context->vars_possibly_in_scope = \array_merge($inner_context->vars_possibly_in_scope, $loop_scope->loop_parent_context->vars_possibly_in_scope); } else { $pre_outer_context = clone $loop_scope->loop_parent_context; $analyzer = $statements_analyzer->getCodebase()->analyzer; $original_mixed_counts = $analyzer->getMixedCountsForFile($statements_analyzer->getFilePath()); $pre_condition_vars_in_scope = $loop_scope->loop_context->vars_in_scope; \Psalm\IssueBuffer::startRecording(); if (!$is_do) { foreach ($pre_conditions as $condition_offset => $pre_condition) { self::applyPreConditionToLoopContext($statements_analyzer, $pre_condition, $pre_condition_clauses[$condition_offset], $loop_scope->loop_context, $loop_scope->loop_parent_context, $is_do); } } // record all the vars that existed before we did the first pass through the loop $pre_loop_context = clone $loop_scope->loop_context; $inner_context = clone $loop_scope->loop_context; foreach ($inner_context->vars_in_scope as $context_var_id => $context_type) { $inner_context->vars_in_scope[$context_var_id] = clone $context_type; } $inner_context->parent_context = $loop_scope->loop_context; $inner_context->loop_scope = $loop_scope; $old_referenced_var_ids = $inner_context->referenced_var_ids; $inner_context->referenced_var_ids = []; $inner_context->protected_var_ids = $loop_scope->protected_var_ids; $statements_analyzer->analyze($stmts, $inner_context); self::updateLoopScopeContexts($loop_scope, $pre_outer_context); $inner_context->protected_var_ids = $original_protected_var_ids; if ($is_do) { $inner_do_context = clone $inner_context; foreach ($pre_conditions as $condition_offset => $pre_condition) { $always_assigned_before_loop_body_vars = \array_merge(self::applyPreConditionToLoopContext($statements_analyzer, $pre_condition, $pre_condition_clauses[$condition_offset], $inner_context, $loop_scope->loop_parent_context, $is_do), $always_assigned_before_loop_body_vars); } } $always_assigned_before_loop_body_vars = \array_unique($always_assigned_before_loop_body_vars); foreach ($post_expressions as $post_expression) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $post_expression, $inner_context) === \false) { return \false; } } $inner_context->referenced_var_ids = \array_intersect_key($old_referenced_var_ids, $inner_context->referenced_var_ids); $recorded_issues = \Psalm\IssueBuffer::clearRecordingLevel(); \Psalm\IssueBuffer::stopRecording(); for ($i = 0; $i < $assignment_depth; ++$i) { $vars_to_remove = []; $loop_scope->iteration_count++; $has_changes = \false; // reset the $inner_context to what it was before we started the analysis, // but union the types with what's in the loop scope foreach ($inner_context->vars_in_scope as $var_id => $type) { if (\in_array($var_id, $always_assigned_before_loop_body_vars, \true)) { // set the vars to whatever the while/foreach loop expects them to be if (!isset($pre_loop_context->vars_in_scope[$var_id]) || !$type->equals($pre_loop_context->vars_in_scope[$var_id])) { $has_changes = \true; } } elseif (isset($pre_outer_context->vars_in_scope[$var_id])) { if (!$type->equals($pre_outer_context->vars_in_scope[$var_id])) { $has_changes = \true; // widen the foreach context type with the initial context type $inner_context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($inner_context->vars_in_scope[$var_id], $pre_outer_context->vars_in_scope[$var_id]); // if there's a change, invalidate related clauses $pre_loop_context->removeVarFromConflictingClauses($var_id); $loop_scope->loop_parent_context->possibly_assigned_var_ids[$var_id] = \true; } if (isset($loop_scope->loop_context->vars_in_scope[$var_id]) && !$type->equals($loop_scope->loop_context->vars_in_scope[$var_id])) { $has_changes = \true; // widen the foreach context type with the initial context type $inner_context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($inner_context->vars_in_scope[$var_id], $loop_scope->loop_context->vars_in_scope[$var_id]); // if there's a change, invalidate related clauses $pre_loop_context->removeVarFromConflictingClauses($var_id); } } else { // give an opportunity to redeemed UndefinedVariable issues if ($recorded_issues) { $has_changes = \true; } // if we're in a do block we don't want to remove vars before evaluating // the where conditional if (!$is_do) { $vars_to_remove[] = $var_id; } } } $inner_context->has_returned = \false; $loop_scope->loop_parent_context->vars_possibly_in_scope = \array_merge($inner_context->vars_possibly_in_scope, $loop_scope->loop_parent_context->vars_possibly_in_scope); // if there are no changes to the types, no need to re-examine if (!$has_changes) { break; } // remove vars that were defined in the foreach foreach ($vars_to_remove as $var_id) { unset($inner_context->vars_in_scope[$var_id]); } $inner_context->clauses = $pre_loop_context->clauses; $analyzer->setMixedCountsForFile($statements_analyzer->getFilePath(), $original_mixed_counts); \Psalm\IssueBuffer::startRecording(); foreach ($pre_loop_context->vars_in_scope as $var_id => $_) { if (!isset($pre_condition_vars_in_scope[$var_id]) && isset($inner_context->vars_in_scope[$var_id]) && \strpos($var_id, '->') === \false && \strpos($var_id, '[') === \false) { $inner_context->vars_in_scope[$var_id]->possibly_undefined = \true; } } if (!$is_do) { foreach ($pre_conditions as $condition_offset => $pre_condition) { self::applyPreConditionToLoopContext($statements_analyzer, $pre_condition, $pre_condition_clauses[$condition_offset], $inner_context, $loop_scope->loop_parent_context, \false); } } foreach ($always_assigned_before_loop_body_vars as $var_id) { if (!isset($inner_context->vars_in_scope[$var_id]) || $inner_context->vars_in_scope[$var_id]->getId() !== $pre_loop_context->vars_in_scope[$var_id]->getId() || $inner_context->vars_in_scope[$var_id]->from_docblock !== $pre_loop_context->vars_in_scope[$var_id]->from_docblock) { if (isset($pre_loop_context->vars_in_scope[$var_id])) { $inner_context->vars_in_scope[$var_id] = clone $pre_loop_context->vars_in_scope[$var_id]; } else { unset($inner_context->vars_in_scope[$var_id]); } } } $inner_context->clauses = $pre_loop_context->clauses; $inner_context->protected_var_ids = $loop_scope->protected_var_ids; $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $traverser->addVisitor(new \Psalm\Internal\PhpVisitor\NodeCleanerVisitor($statements_analyzer->node_data)); $traverser->traverse($stmts); $statements_analyzer->analyze($stmts, $inner_context); self::updateLoopScopeContexts($loop_scope, $pre_outer_context); $inner_context->protected_var_ids = $original_protected_var_ids; if ($is_do) { $inner_do_context = clone $inner_context; foreach ($pre_conditions as $condition_offset => $pre_condition) { self::applyPreConditionToLoopContext($statements_analyzer, $pre_condition, $pre_condition_clauses[$condition_offset], $inner_context, $loop_scope->loop_parent_context, $is_do); } } foreach ($post_expressions as $post_expression) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $post_expression, $inner_context) === \false) { return \false; } } $recorded_issues = \Psalm\IssueBuffer::clearRecordingLevel(); \Psalm\IssueBuffer::stopRecording(); } if ($recorded_issues) { foreach ($recorded_issues as $recorded_issue) { // if we're not in any loops then this will just result in the issue being emitted \Psalm\IssueBuffer::bubbleUp($recorded_issue); } } } $does_sometimes_break = \in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK, $loop_scope->final_actions, \true); $does_always_break = $loop_scope->final_actions === [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK]; if ($does_sometimes_break) { if ($loop_scope->possibly_redefined_loop_parent_vars !== null) { foreach ($loop_scope->possibly_redefined_loop_parent_vars as $var => $type) { $loop_scope->loop_parent_context->vars_in_scope[$var] = \Psalm\Type::combineUnionTypes($type, $loop_scope->loop_parent_context->vars_in_scope[$var]); $loop_scope->loop_parent_context->possibly_assigned_var_ids[$var] = \true; } } } foreach ($loop_scope->loop_parent_context->vars_in_scope as $var_id => $type) { if (!isset($loop_scope->loop_context->vars_in_scope[$var_id])) { continue; } if ($loop_scope->loop_context->vars_in_scope[$var_id]->getId() !== $type->getId()) { $loop_scope->loop_parent_context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($loop_scope->loop_parent_context->vars_in_scope[$var_id], $loop_scope->loop_context->vars_in_scope[$var_id]); $loop_scope->loop_parent_context->removeVarFromConflictingClauses($var_id); } else { $loop_scope->loop_parent_context->vars_in_scope[$var_id]->parent_nodes += $loop_scope->loop_context->vars_in_scope[$var_id]->parent_nodes; } } if (!$does_always_break) { foreach ($loop_scope->loop_parent_context->vars_in_scope as $var_id => $type) { if (!isset($inner_context->vars_in_scope[$var_id])) { unset($loop_scope->loop_parent_context->vars_in_scope[$var_id]); continue; } if ($inner_context->vars_in_scope[$var_id]->hasMixed()) { $inner_context->vars_in_scope[$var_id]->parent_nodes += $loop_scope->loop_parent_context->vars_in_scope[$var_id]->parent_nodes; $loop_scope->loop_parent_context->vars_in_scope[$var_id] = $inner_context->vars_in_scope[$var_id]; $loop_scope->loop_parent_context->removeVarFromConflictingClauses($var_id); continue; } if ($inner_context->vars_in_scope[$var_id]->getId() !== $type->getId()) { $loop_scope->loop_parent_context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($loop_scope->loop_parent_context->vars_in_scope[$var_id], $inner_context->vars_in_scope[$var_id]); $loop_scope->loop_parent_context->removeVarFromConflictingClauses($var_id); } else { $loop_scope->loop_parent_context->vars_in_scope[$var_id]->parent_nodes = \array_merge($loop_scope->loop_parent_context->vars_in_scope[$var_id]->parent_nodes, $inner_context->vars_in_scope[$var_id]->parent_nodes); } } } if ($pre_conditions && $pre_condition_clauses && !\Psalm\Internal\Analyzer\ScopeAnalyzer::doesEverBreak($stmts)) { // if the loop contains an assertion and there are no break statements, we can negate that assertion // and apply it to the current context try { $negated_pre_condition_clauses = \Psalm\Type\Algebra::negateFormula(\array_merge(...$pre_condition_clauses)); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { $negated_pre_condition_clauses = []; } $negated_pre_condition_types = \Psalm\Type\Algebra::getTruthsFromFormula($negated_pre_condition_clauses); if ($negated_pre_condition_types) { $changed_var_ids = []; $vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($negated_pre_condition_types, [], $inner_context->vars_in_scope, $changed_var_ids, [], $statements_analyzer, [], \true, new \Psalm\CodeLocation($statements_analyzer->getSource(), $pre_conditions[0])); foreach ($changed_var_ids as $var_id => $_) { if (isset($vars_in_scope_reconciled[$var_id]) && isset($loop_scope->loop_parent_context->vars_in_scope[$var_id])) { $loop_scope->loop_parent_context->vars_in_scope[$var_id] = $vars_in_scope_reconciled[$var_id]; } $loop_scope->loop_parent_context->removeVarFromConflictingClauses($var_id); } } } $loop_scope->loop_context->referenced_var_ids = \array_merge(\array_intersect_key($inner_context->referenced_var_ids, $pre_outer_context->vars_in_scope), $loop_scope->loop_context->referenced_var_ids); if ($always_enters_loop) { foreach ($inner_context->vars_in_scope as $var_id => $type) { // if there are break statements in the loop it's not certain // that the loop has finished executing, so the assertions at the end // the loop in the while conditional may not hold if (\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_BREAK, $loop_scope->final_actions, \true) || \in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE, $loop_scope->final_actions, \true)) { if (isset($loop_scope->possibly_defined_loop_parent_vars[$var_id])) { $loop_scope->loop_parent_context->vars_in_scope[$var_id] = \Psalm\Type::combineUnionTypes($type, $loop_scope->possibly_defined_loop_parent_vars[$var_id]); } } else { $loop_scope->loop_parent_context->vars_in_scope[$var_id] = $type; } } } if ($inner_do_context) { $inner_context = $inner_do_context; } return null; } private static function updateLoopScopeContexts(\Psalm\Internal\Scope\LoopScope $loop_scope, \Psalm\Context $pre_outer_context) : void { $updated_loop_vars = []; if (!\in_array(\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_CONTINUE, $loop_scope->final_actions, \true)) { $loop_scope->loop_context->vars_in_scope = $pre_outer_context->vars_in_scope; } else { if ($loop_scope->redefined_loop_vars !== null) { foreach ($loop_scope->redefined_loop_vars as $var => $type) { $loop_scope->loop_context->vars_in_scope[$var] = $type; $updated_loop_vars[$var] = \true; } } if ($loop_scope->possibly_redefined_loop_vars) { foreach ($loop_scope->possibly_redefined_loop_vars as $var => $type) { if ($loop_scope->loop_context->hasVariable($var)) { if (!isset($updated_loop_vars[$var])) { $loop_scope->loop_context->vars_in_scope[$var] = \Psalm\Type::combineUnionTypes($loop_scope->loop_context->vars_in_scope[$var], $type); } else { $loop_scope->loop_context->vars_in_scope[$var]->parent_nodes += $type->parent_nodes; } } } } } // merge vars possibly in scope at the end of each loop $loop_scope->loop_context->vars_possibly_in_scope = \array_merge($loop_scope->loop_context->vars_possibly_in_scope, $loop_scope->vars_possibly_in_scope); } /** * @param list $pre_condition_clauses * * @return list */ private static function applyPreConditionToLoopContext(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $pre_condition, array $pre_condition_clauses, \Psalm\Context $loop_context, \Psalm\Context $outer_context, bool $is_do) : array { $pre_referenced_var_ids = $loop_context->referenced_var_ids; $loop_context->referenced_var_ids = []; $loop_context->inside_conditional = \true; $suppressed_issues = $statements_analyzer->getSuppressedIssues(); if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['RedundantConditionGivenDocblockType']); } if (!\in_array('TypeDoesNotContainType', $suppressed_issues, \true)) { $statements_analyzer->addSuppressedIssues(['TypeDoesNotContainType']); } if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $pre_condition, $loop_context) === \false) { return []; } $loop_context->inside_conditional = \false; $new_referenced_var_ids = $loop_context->referenced_var_ids; $loop_context->referenced_var_ids = \array_merge($pre_referenced_var_ids, $new_referenced_var_ids); $always_assigned_before_loop_body_vars = \Psalm\Context::getNewOrUpdatedVarIds($outer_context, $loop_context); $loop_context->clauses = \Psalm\Type\Algebra::simplifyCNF(\array_merge($outer_context->clauses, $pre_condition_clauses)); $active_while_types = []; $reconcilable_while_types = \Psalm\Type\Algebra::getTruthsFromFormula($loop_context->clauses, \spl_object_id($pre_condition), $new_referenced_var_ids); $changed_var_ids = []; if ($reconcilable_while_types) { $pre_condition_vars_in_scope_reconciled = \Psalm\Type\Reconciler::reconcileKeyedTypes($reconcilable_while_types, $active_while_types, $loop_context->vars_in_scope, $changed_var_ids, $new_referenced_var_ids, $statements_analyzer, [], \true, new \Psalm\CodeLocation($statements_analyzer->getSource(), $pre_condition)); $loop_context->vars_in_scope = $pre_condition_vars_in_scope_reconciled; } if (!\in_array('RedundantCondition', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantCondition']); } if (!\in_array('RedundantConditionGivenDocblockType', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['RedundantConditionGivenDocblockType']); } if (!\in_array('TypeDoesNotContainType', $suppressed_issues, \true)) { $statements_analyzer->removeSuppressedIssues(['TypeDoesNotContainType']); } if ($is_do) { return []; } foreach ($always_assigned_before_loop_body_vars as $var_id) { $loop_context->clauses = \Psalm\Context::filterClauses($var_id, $loop_context->clauses, null, $statements_analyzer); } return $always_assigned_before_loop_body_vars; } /** * @param array> $assignment_map * */ private static function getAssignmentMapDepth(string $first_var_id, array $assignment_map) : int { $max_depth = 0; $assignment_var_ids = $assignment_map[$first_var_id]; unset($assignment_map[$first_var_id]); foreach ($assignment_var_ids as $assignment_var_id => $_) { $depth = 1; if (isset($assignment_map[$assignment_var_id])) { $depth = 1 + self::getAssignmentMapDepth($assignment_var_id, $assignment_map); } if ($depth > $max_depth) { $max_depth = $depth; } } return $max_depth; } } 'int', 'string' => 'string', 'float' => 'float', 'bool' => 'bool', 'false' => 'false', 'object' => 'object', 'empty' => 'empty', 'callable' => 'callable', 'array' => 'array', 'iterable' => 'iterable', 'null' => 'null', 'mixed' => 'mixed']; public const GETTYPE_TYPES = ['boolean' => \true, 'integer' => \true, 'double' => \true, 'string' => \true, 'array' => \true, 'object' => \true, 'resource' => \true, 'resource (closed)' => \true, 'NULL' => \true, 'unknown type' => \true]; /** * @var PhpParser\Node\Stmt\ClassLike */ protected $class; /** * @var StatementsSource */ protected $source; /** @var FileAnalyzer */ public $file_analyzer; /** * @var string */ protected $fq_class_name; /** * The parent class * * @var string|null */ protected $parent_fq_class_name; /** * @var PhpParser\Node\Stmt[] */ protected $leftover_stmts = []; /** @var ClassLikeStorage */ protected $storage; public function __construct(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike $class, \Psalm\Internal\Analyzer\SourceAnalyzer $source, string $fq_class_name) { $this->class = $class; $this->source = $source; $this->file_analyzer = $source->getFileAnalyzer(); $this->fq_class_name = $fq_class_name; $codebase = $source->getCodebase(); $this->storage = $codebase->classlike_storage_provider->get($fq_class_name); } public function __destruct() { $this->source = null; $this->file_analyzer = null; } public function getMethodMutations(string $method_name, \Psalm\Context $context) : void { $project_analyzer = $this->getFileAnalyzer()->project_analyzer; $codebase = $project_analyzer->getCodebase(); foreach ($this->class->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && \strtolower($stmt->name->name) === \strtolower($method_name)) { $method_analyzer = new \Psalm\Internal\Analyzer\MethodAnalyzer($stmt, $this); $method_analyzer->analyze($context, new \Psalm\Internal\Provider\NodeDataProvider(), null, \true); $context->clauses = []; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { foreach ($stmt->traits as $trait) { $fq_trait_name = self::getFQCLNFromNameObject($trait, $this->source->getAliases()); $trait_file_analyzer = $project_analyzer->getFileAnalyzerForClassLike($fq_trait_name); $trait_node = $codebase->classlikes->getTraitNode($fq_trait_name); $trait_storage = $codebase->classlike_storage_provider->get($fq_trait_name); $trait_aliases = $trait_storage->aliases; if ($trait_aliases === null) { continue; } $trait_analyzer = new \Psalm\Internal\Analyzer\TraitAnalyzer($trait_node, $trait_file_analyzer, $fq_trait_name, $trait_aliases); foreach ($trait_node->stmts as $trait_stmt) { if ($trait_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && \strtolower($trait_stmt->name->name) === \strtolower($method_name)) { $method_analyzer = new \Psalm\Internal\Analyzer\MethodAnalyzer($trait_stmt, $trait_analyzer); $actual_method_id = $method_analyzer->getMethodId(); if ($context->self && $context->self !== $this->fq_class_name) { $analyzed_method_id = $method_analyzer->getMethodId($context->self); $declaring_method_id = $codebase->methods->getDeclaringMethodId($analyzed_method_id); if ((string) $actual_method_id !== (string) $declaring_method_id) { break; } } $method_analyzer->analyze($context, new \Psalm\Internal\Provider\NodeDataProvider(), null, \true); } } $trait_file_analyzer->clearSourceBeforeDestruction(); } } } } public function getFunctionLikeAnalyzer(string $method_name) : ?\Psalm\Internal\Analyzer\MethodAnalyzer { foreach ($this->class->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && \strtolower($stmt->name->name) === \strtolower($method_name)) { return new \Psalm\Internal\Analyzer\MethodAnalyzer($stmt, $this); } } return null; } /** * @param array $suppressed_issues * @param bool $inferred - whether or not the type was inferred */ public static function checkFullyQualifiedClassLikeName(\Psalm\StatementsSource $statements_source, string $fq_class_name, \Psalm\CodeLocation $code_location, ?string $calling_fq_class_name, ?string $calling_method_id, array $suppressed_issues, bool $inferred = \true, bool $allow_trait = \false, bool $allow_interface = \true, bool $from_docblock = \false) : ?bool { $codebase = $statements_source->getCodebase(); if ($fq_class_name === '') { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedClass('Class or interface does not exist', $code_location, 'empty string'), $suppressed_issues)) { return \false; } return null; } $fq_class_name = \preg_replace('/^\\\\/', '', $fq_class_name); if (\in_array($fq_class_name, ['callable', 'iterable', 'self', 'static', 'parent'], \true)) { return \true; } if (\preg_match('/(^|\\\\)(int|float|bool|string|void|null|false|true|object|mixed)$/i', $fq_class_name) || \strtolower($fq_class_name) === 'resource') { $class_name_parts = \explode('\\', $fq_class_name); $class_name = \array_pop($class_name_parts); if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ReservedWord($class_name . ' is a reserved word', $code_location, $class_name), $suppressed_issues)) { // fall through } return null; } $class_exists = $codebase->classlikes->classExists($fq_class_name, !$inferred ? $code_location : null, $calling_fq_class_name, $calling_method_id); $interface_exists = $codebase->classlikes->interfaceExists($fq_class_name, !$inferred ? $code_location : null, $calling_fq_class_name, $calling_method_id); if (!$class_exists && !$interface_exists) { if (!$allow_trait || !$codebase->classlikes->traitExists($fq_class_name, $code_location)) { if ($from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedDocblockClass('Docblock-defined class or interface ' . $fq_class_name . ' does not exist', $code_location, $fq_class_name), $suppressed_issues)) { return \false; } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedClass('Class or interface ' . $fq_class_name . ' does not exist', $code_location, $fq_class_name), $suppressed_issues)) { return \false; } } } return null; } elseif ($interface_exists && !$allow_interface) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedClass('Class ' . $fq_class_name . ' does not exist', $code_location, $fq_class_name), $suppressed_issues)) { return \false; } } $aliased_name = $codebase->classlikes->getUnAliasedName($fq_class_name); try { $class_storage = $codebase->classlike_storage_provider->get($aliased_name); } catch (\InvalidArgumentException $e) { if (!$inferred) { throw $e; } return null; } foreach ($class_storage->invalid_dependencies as $dependency_class_name) { // if the implemented/extended class is stubbed, it may not yet have // been hydrated if ($codebase->classlike_storage_provider->has($dependency_class_name)) { continue; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingDependency($fq_class_name . ' depends on class or interface ' . $dependency_class_name . ' that does not exist', $code_location, $fq_class_name), $suppressed_issues)) { return \false; } } if (!$inferred) { if ($class_exists && !$codebase->classHasCorrectCasing($fq_class_name) || $interface_exists && !$codebase->interfaceHasCorrectCasing($fq_class_name)) { if ($codebase->classlikes->isUserDefined(\strtolower($aliased_name))) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidClass('Class or interface ' . $fq_class_name . ' has wrong casing', $code_location, $fq_class_name), $suppressed_issues)) { // fall through here } } } } if (!$inferred) { $plugin_classes = $codebase->config->after_classlike_exists_checks; if ($plugin_classes) { $file_manipulations = []; foreach ($plugin_classes as $plugin_fq_class_name) { $plugin_fq_class_name::afterClassLikeExistenceCheck($fq_class_name, $code_location, $statements_source, $codebase, $file_manipulations); } if ($file_manipulations) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($code_location->file_path, $file_manipulations); } } } return \true; } /** * Gets the fully-qualified class name from a Name object * * */ public static function getFQCLNFromNameObject(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $class_name, \Psalm\Aliases $aliases) : string { /** @var string|null */ $resolved_name = $class_name->getAttribute('resolvedName'); if ($resolved_name) { return $resolved_name; } if ($class_name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified) { return \implode('\\', $class_name->parts); } if (\in_array($class_name->parts[0], ['self', 'static', 'parent'], \true)) { return $class_name->parts[0]; } return \Psalm\Type::getFQCLNFromString(\implode('\\', $class_name->parts), $aliases); } /** * @return array */ public function getAliasedClassesFlipped() : array { if ($this->source instanceof \Psalm\Internal\Analyzer\NamespaceAnalyzer || $this->source instanceof \Psalm\Internal\Analyzer\FileAnalyzer) { return $this->source->getAliasedClassesFlipped(); } return []; } /** * @return array */ public function getAliasedClassesFlippedReplaceable() : array { if ($this->source instanceof \Psalm\Internal\Analyzer\NamespaceAnalyzer || $this->source instanceof \Psalm\Internal\Analyzer\FileAnalyzer) { return $this->source->getAliasedClassesFlippedReplaceable(); } return []; } public function getFQCLN() : string { return $this->fq_class_name; } public function getClassName() : ?string { return $this->class->name ? $this->class->name->name : null; } /** * @return array>|null */ public function getTemplateTypeMap() : ?array { return $this->storage->template_types; } public function getParentFQCLN() : ?string { return $this->parent_fq_class_name; } public function isStatic() : bool { return \false; } /** * Gets the Psalm type from a particular value * * @param mixed $value * */ public static function getTypeFromValue($value) : \Psalm\Type\Union { switch (\gettype($value)) { case 'boolean': if ($value) { return \Psalm\Type::getTrue(); } return \Psalm\Type::getFalse(); case 'integer': return \Psalm\Type::getInt(\false, $value); case 'double': return \Psalm\Type::getFloat($value); case 'string': return \Psalm\Type::getString($value); case 'array': return \Psalm\Type::getArray(); case 'NULL': return \Psalm\Type::getNull(); default: return \Psalm\Type::getMixed(); } } /** * @param string[] $suppressed_issues */ public static function checkPropertyVisibility(string $property_id, \Psalm\Context $context, \Psalm\Internal\Analyzer\SourceAnalyzer $source, \Psalm\CodeLocation $code_location, array $suppressed_issues, bool $emit_issues = \true) : ?bool { [$fq_class_name, $property_name] = \explode('::$', $property_id); $codebase = $source->getCodebase(); if ($codebase->properties->property_visibility_provider->has($fq_class_name)) { $property_visible = $codebase->properties->property_visibility_provider->isPropertyVisible($source, $fq_class_name, $property_name, \true, $context, $code_location); if ($property_visible !== null) { return $property_visible; } } $declaring_property_class = $codebase->properties->getDeclaringClassForProperty($property_id, \true); $appearing_property_class = $codebase->properties->getAppearingClassForProperty($property_id, \true); if (!$declaring_property_class || !$appearing_property_class) { throw new \UnexpectedValueException('Appearing/Declaring classes are not defined for ' . $property_id); } // if the calling class is the same, we know the property exists, so it must be visible if ($appearing_property_class === $context->self) { return $emit_issues ? null : \true; } if ($source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer && \strtolower($declaring_property_class) === \strtolower((string) $source->getFQCLN())) { return $emit_issues ? null : \true; } $class_storage = $codebase->classlike_storage_provider->get($declaring_property_class); if (!isset($class_storage->properties[$property_name])) { throw new \UnexpectedValueException('$storage should not be null for ' . $property_id); } $storage = $class_storage->properties[$property_name]; switch ($storage->visibility) { case self::VISIBILITY_PUBLIC: return $emit_issues ? null : \true; case self::VISIBILITY_PRIVATE: if (!$context->self || $appearing_property_class !== $context->self) { if ($emit_issues && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleProperty('Cannot access private property ' . $property_id . ' from context ' . $context->self, $code_location), $suppressed_issues)) { // fall through } return null; } return $emit_issues ? null : \true; case self::VISIBILITY_PROTECTED: if ($appearing_property_class === $context->self) { return null; } if (!$context->self) { if ($emit_issues && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleProperty('Cannot access protected property ' . $property_id, $code_location), $suppressed_issues)) { // fall through } return null; } if ($codebase->classExtends($appearing_property_class, $context->self)) { return $emit_issues ? null : \true; } if (!$codebase->classExtends($context->self, $appearing_property_class)) { if ($emit_issues && \Psalm\IssueBuffer::accepts(new \Psalm\Issue\InaccessibleProperty('Cannot access protected property ' . $property_id . ' from context ' . $context->self, $code_location), $suppressed_issues)) { // fall through } return null; } } return $emit_issues ? null : \true; } /** * @return array */ public static function getClassesForFile(\Psalm\Codebase $codebase, string $file_path) : array { try { return $codebase->file_storage_provider->get($file_path)->classlikes_in_file; } catch (\InvalidArgumentException $e) { return []; } } public function getFileAnalyzer() : \Psalm\Internal\Analyzer\FileAnalyzer { return $this->file_analyzer; } } \\[\\]\\-\\{\\}:|?\\\\]*|\\$[a-zA-Z_0-9_]+)'; /** * @param array>|null $template_type_map * @param array $type_aliases * * @throws DocblockParseException if there was a problem parsing the docblock * * @return list */ public static function getTypeFromComment(\_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $comment, \Psalm\FileSource $source, \Psalm\Aliases $aliases, ?array $template_type_map = null, ?array $type_aliases = null) : array { $parsed_docblock = \Psalm\DocComment::parsePreservingLength($comment); return self::arrayToDocblocks($comment, $parsed_docblock, $source, $aliases, $template_type_map, $type_aliases); } /** * @param array>|null $template_type_map * @param array $type_aliases * * @return list * * @throws DocblockParseException if there was a problem parsing the docblock */ public static function arrayToDocblocks(\_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $comment, \Psalm\Internal\Scanner\ParsedDocblock $parsed_docblock, \Psalm\FileSource $source, \Psalm\Aliases $aliases, ?array $template_type_map = null, ?array $type_aliases = null) : array { $var_id = null; $var_type_tokens = null; $original_type = null; $var_comments = []; $comment_text = $comment->getText(); $var_line_number = $comment->getStartLine(); if (isset($parsed_docblock->combined_tags['var'])) { foreach ($parsed_docblock->combined_tags['var'] as $offset => $var_line) { $var_line = \trim($var_line); if (!$var_line) { continue; } $type_start = null; $type_end = null; $line_parts = self::splitDocLine($var_line); $line_number = $comment->getStartLine() + \substr_count($comment_text, "\n", 0, $offset); if ($line_parts && $line_parts[0]) { $type_start = $offset + $comment->getStartFilePos(); $type_end = $type_start + \strlen($line_parts[0]); $line_parts[0] = self::sanitizeDocblockType($line_parts[0]); if ($line_parts[0] === '' || $line_parts[0][0] === '$' && !\preg_match('/^\\$this(\\||$)/', $line_parts[0])) { throw new \Psalm\Exception\IncorrectDocblockException('Misplaced variable'); } try { $var_type_tokens = \Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($line_parts[0], $aliases, $template_type_map, $type_aliases); } catch (\Psalm\Exception\TypeParseTreeException $e) { throw new \Psalm\Exception\DocblockParseException($line_parts[0] . ' is not a valid type'); } $original_type = $line_parts[0]; $var_line_number = $line_number; if (\count($line_parts) > 1 && $line_parts[1][0] === '$') { $var_id = $line_parts[1]; } } if (!$var_type_tokens || !$original_type) { continue; } try { $defined_type = \Psalm\Internal\Type\TypeParser::parseTokens($var_type_tokens, null, $template_type_map ?: [], $type_aliases ?: []); } catch (\Psalm\Exception\TypeParseTreeException $e) { throw new \Psalm\Exception\DocblockParseException($line_parts[0] . ' is not a valid type' . ' (from ' . $source->getFilePath() . ':' . $comment->getStartLine() . ')'); } $defined_type->setFromDocblock(); $var_comment = new \Psalm\Internal\Scanner\VarDocblockComment(); $var_comment->type = $defined_type; $var_comment->original_type = $original_type; $var_comment->var_id = $var_id; $var_comment->line_number = $var_line_number; $var_comment->type_start = $type_start; $var_comment->type_end = $type_end; self::decorateVarDocblockComment($var_comment, $parsed_docblock); $var_comments[] = $var_comment; } } if (!$var_comments && (isset($parsed_docblock->tags['deprecated']) || isset($parsed_docblock->tags['internal']) || isset($parsed_docblock->tags['readonly']) || isset($parsed_docblock->tags['psalm-readonly']) || isset($parsed_docblock->tags['psalm-readonly-allow-private-mutation']) || isset($parsed_docblock->tags['psalm-taint-escape']) || isset($parsed_docblock->tags['psalm-internal']))) { $var_comment = new \Psalm\Internal\Scanner\VarDocblockComment(); self::decorateVarDocblockComment($var_comment, $parsed_docblock); $var_comments[] = $var_comment; } return $var_comments; } private static function decorateVarDocblockComment(\Psalm\Internal\Scanner\VarDocblockComment $var_comment, \Psalm\Internal\Scanner\ParsedDocblock $parsed_docblock) : void { $var_comment->deprecated = isset($parsed_docblock->tags['deprecated']); $var_comment->internal = isset($parsed_docblock->tags['internal']); $var_comment->readonly = isset($parsed_docblock->tags['readonly']) || isset($parsed_docblock->tags['psalm-readonly']) || isset($parsed_docblock->tags['psalm-readonly-allow-private-mutation']); $var_comment->allow_private_mutation = isset($parsed_docblock->tags['psalm-allow-private-mutation']) || isset($parsed_docblock->tags['psalm-readonly-allow-private-mutation']); if (isset($parsed_docblock->tags['psalm-taint-escape'])) { foreach ($parsed_docblock->tags['psalm-taint-escape'] as $param) { $param = \trim($param); $var_comment->removed_taints[] = $param; } } if (isset($parsed_docblock->tags['psalm-internal'])) { $psalm_internal = \reset($parsed_docblock->tags['psalm-internal']); if (!$psalm_internal) { throw new \Psalm\Exception\DocblockParseException('psalm-internal annotation used without specifying namespace'); } $var_comment->psalm_internal = \reset($parsed_docblock->tags['psalm-internal']); $var_comment->internal = \true; } } /** * @psalm-pure */ private static function sanitizeDocblockType(string $docblock_type) : string { $docblock_type = \preg_replace('@^[ \\t]*\\*@m', '', $docblock_type); $docblock_type = \preg_replace('/,\\n\\s+\\}/', '}', $docblock_type); return \str_replace("\n", '', $docblock_type); } /** * @param array $type_aliases * * @return array * * @throws DocblockParseException if there was a problem parsing the docblock */ public static function getTypeAliasesFromComment(\_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $comment, \Psalm\Aliases $aliases, ?array $type_aliases, ?string $self_fqcln) : array { $parsed_docblock = \Psalm\DocComment::parsePreservingLength($comment); if (!isset($parsed_docblock->tags['psalm-type'])) { return []; } return self::getTypeAliasesFromCommentLines($parsed_docblock->tags['psalm-type'], $aliases, $type_aliases, $self_fqcln); } /** * @param array $type_alias_comment_lines * @param array $type_aliases * * @return array * * @throws DocblockParseException if there was a problem parsing the docblock */ private static function getTypeAliasesFromCommentLines(array $type_alias_comment_lines, \Psalm\Aliases $aliases, ?array $type_aliases, ?string $self_fqcln) : array { $type_alias_tokens = []; foreach ($type_alias_comment_lines as $var_line) { $var_line = \trim($var_line); if (!$var_line) { continue; } $var_line = \preg_replace('/[ \\t]+/', ' ', \preg_replace('@^[ \\t]*\\*@m', '', $var_line)); $var_line = \preg_replace('/,\\n\\s+\\}/', '}', $var_line); $var_line = \str_replace("\n", '', $var_line); $var_line_parts = \preg_split('/( |=)/', $var_line, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); if (!$var_line_parts) { continue; } $type_alias = \array_shift($var_line_parts); if (!isset($var_line_parts[0])) { continue; } if ($var_line_parts[0] === ' ') { \array_shift($var_line_parts); } if ($var_line_parts[0] === '=') { \array_shift($var_line_parts); } if (!isset($var_line_parts[0])) { continue; } if ($var_line_parts[0] === ' ') { \array_shift($var_line_parts); } $type_string = \str_replace("\n", '', \implode('', $var_line_parts)); $type_string = \preg_replace('/>[^>^\\}]*$/', '>', $type_string); $type_string = \preg_replace('/\\}[^>^\\}]*$/', '}', $type_string); try { $type_tokens = \Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($type_string, $aliases, null, $type_alias_tokens + $type_aliases, $self_fqcln); } catch (\Psalm\Exception\TypeParseTreeException $e) { throw new \Psalm\Exception\DocblockParseException($type_string . ' is not a valid type'); } $type_alias_tokens[$type_alias] = new \Psalm\Internal\Type\TypeAlias\InlineTypeAlias($type_tokens); } return $type_alias_tokens; } /** * @throws DocblockParseException if there was a problem parsing the docblock */ public static function extractFunctionDocblockInfo(\_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $comment) : \Psalm\Internal\Scanner\FunctionDocblockComment { $parsed_docblock = \Psalm\DocComment::parsePreservingLength($comment); $comment_text = $comment->getText(); $info = new \Psalm\Internal\Scanner\FunctionDocblockComment(); self::checkDuplicatedTags($parsed_docblock); if (isset($parsed_docblock->combined_tags['return'])) { self::extractReturnType($comment, $parsed_docblock->combined_tags['return'], $info); } if (isset($parsed_docblock->combined_tags['param'])) { foreach ($parsed_docblock->combined_tags['param'] as $offset => $param) { $line_parts = self::splitDocLine($param); if (\count($line_parts) === 1 && isset($line_parts[0][0]) && $line_parts[0][0] === '$') { continue; } if (\count($line_parts) > 1) { if (\preg_match('/^&?(\\.\\.\\.)?&?\\$[A-Za-z0-9_]+,?$/', $line_parts[1]) && $line_parts[0][0] !== '{') { $line_parts[1] = \str_replace('&', '', $line_parts[1]); $line_parts[1] = \preg_replace('/,$/', '', $line_parts[1]); $start = $offset + $comment->getStartFilePos(); $end = $start + \strlen($line_parts[0]); $line_parts[0] = self::sanitizeDocblockType($line_parts[0]); if ($line_parts[0] === '' || $line_parts[0][0] === '$' && !\preg_match('/^\\$this(\\||$)/', $line_parts[0])) { throw new \Psalm\Exception\IncorrectDocblockException('Misplaced variable'); } $info->params[] = ['name' => \trim($line_parts[1]), 'type' => $line_parts[0], 'line_number' => $comment->getStartLine() + \substr_count($comment_text, "\n", 0, $offset), 'start' => $start, 'end' => $end]; } } else { throw new \Psalm\Exception\DocblockParseException('Badly-formatted @param'); } } } if (isset($parsed_docblock->tags['param-out'])) { foreach ($parsed_docblock->tags['param-out'] as $offset => $param) { $line_parts = self::splitDocLine($param); if (\count($line_parts) === 1 && isset($line_parts[0][0]) && $line_parts[0][0] === '$') { continue; } if (\count($line_parts) > 1) { if (!\preg_match('/\\[[^\\]]+\\]/', $line_parts[0]) && \preg_match('/^(\\.\\.\\.)?&?\\$[A-Za-z0-9_]+,?$/', $line_parts[1]) && $line_parts[0][0] !== '{') { if ($line_parts[1][0] === '&') { $line_parts[1] = \substr($line_parts[1], 1); } $line_parts[0] = \str_replace("\n", '', \preg_replace('@^[ \\t]*\\*@m', '', $line_parts[0])); if ($line_parts[0] === '' || $line_parts[0][0] === '$' && !\preg_match('/^\\$this(\\||$)/', $line_parts[0])) { throw new \Psalm\Exception\IncorrectDocblockException('Misplaced variable'); } $line_parts[1] = \preg_replace('/,$/', '', $line_parts[1]); $info->params_out[] = ['name' => \trim($line_parts[1]), 'type' => \str_replace("\n", '', $line_parts[0]), 'line_number' => $comment->getStartLine() + \substr_count($comment_text, "\n", 0, $offset)]; } } else { throw new \Psalm\Exception\DocblockParseException('Badly-formatted @param'); } } } if (isset($parsed_docblock->tags['psalm-self-out'])) { foreach ($parsed_docblock->tags['psalm-self-out'] as $offset => $param) { $line_parts = self::splitDocLine($param); if (\count($line_parts) > 0) { $line_parts[0] = \str_replace("\n", '', \preg_replace('@^[ \\t]*\\*@m', '', $line_parts[0])); $info->self_out = ['type' => \str_replace("\n", '', $line_parts[0]), 'line_number' => $comment->getStartLine() + \substr_count($comment_text, "\n", 0, $offset)]; } } } if (isset($parsed_docblock->tags['psalm-flow'])) { foreach ($parsed_docblock->tags['psalm-flow'] as $param) { $info->flows[] = \trim($param); } } if (isset($parsed_docblock->tags['psalm-taint-sink'])) { foreach ($parsed_docblock->tags['psalm-taint-sink'] as $param) { $param_parts = \preg_split('/\\s+/', \trim($param)); if (\count($param_parts) === 2) { $info->taint_sink_params[] = ['name' => $param_parts[1], 'taint' => $param_parts[0]]; } } } // support for MediaWiki taint plugin if (isset($parsed_docblock->tags['param-taint'])) { foreach ($parsed_docblock->tags['param-taint'] as $param) { $param_parts = \preg_split('/\\s+/', \trim($param)); if (\count($param_parts) === 2) { $taint_type = $param_parts[1]; if (\substr($taint_type, 0, 5) === 'exec_') { $taint_type = \substr($taint_type, 5); if ($taint_type === 'tainted') { $taint_type = 'input'; } if ($taint_type === 'misc') { $taint_type = 'text'; } $info->taint_sink_params[] = ['name' => $param_parts[0], 'taint' => $taint_type]; } } } } if (isset($parsed_docblock->tags['psalm-taint-source'])) { foreach ($parsed_docblock->tags['psalm-taint-source'] as $param) { $param_parts = \preg_split('/\\s+/', \trim($param)); if ($param_parts[0]) { $info->taint_source_types[] = $param_parts[0]; } } } elseif (isset($parsed_docblock->tags['return-taint'])) { // support for MediaWiki taint plugin foreach ($parsed_docblock->tags['return-taint'] as $param) { $param_parts = \preg_split('/\\s+/', \trim($param)); if ($param_parts[0]) { if ($param_parts[0] === 'tainted') { $param_parts[0] = 'input'; } if ($param_parts[0] === 'misc') { $param_parts[0] = 'text'; } if ($param_parts[0] !== 'none') { $info->taint_source_types[] = $param_parts[0]; } } } } if (isset($parsed_docblock->tags['psalm-taint-unescape'])) { foreach ($parsed_docblock->tags['psalm-taint-unescape'] as $param) { $param = \trim($param); $info->added_taints[] = $param; } } if (isset($parsed_docblock->tags['psalm-taint-escape'])) { foreach ($parsed_docblock->tags['psalm-taint-escape'] as $param) { $param = \trim($param); $info->removed_taints[] = $param; } } if (isset($parsed_docblock->tags['psalm-assert-untainted'])) { foreach ($parsed_docblock->tags['psalm-assert-untainted'] as $param) { $param = \trim($param); $info->assert_untainted_params[] = ['name' => $param]; } } if (isset($parsed_docblock->tags['psalm-taint-specialize'])) { $info->specialize_call = \true; } if (isset($parsed_docblock->tags['global'])) { foreach ($parsed_docblock->tags['global'] as $offset => $global) { $line_parts = self::splitDocLine($global); if (\count($line_parts) === 1 && isset($line_parts[0][0]) && $line_parts[0][0] === '$') { continue; } if (\count($line_parts) > 1) { if (!\preg_match('/\\[[^\\]]+\\]/', $line_parts[0]) && \preg_match('/^(\\.\\.\\.)?&?\\$[A-Za-z0-9_]+,?$/', $line_parts[1]) && $line_parts[0][0] !== '{') { if ($line_parts[1][0] === '&') { $line_parts[1] = \substr($line_parts[1], 1); } if ($line_parts[0][0] === '$' && !\preg_match('/^\\$this(\\||$)/', $line_parts[0])) { throw new \Psalm\Exception\IncorrectDocblockException('Misplaced variable'); } $line_parts[1] = \preg_replace('/,$/', '', $line_parts[1]); $info->globals[] = ['name' => $line_parts[1], 'type' => $line_parts[0], 'line_number' => $comment->getStartLine() + \substr_count($comment_text, "\n", 0, $offset)]; } } else { throw new \Psalm\Exception\DocblockParseException('Badly-formatted @param'); } } } if (isset($parsed_docblock->tags['deprecated'])) { $info->deprecated = \true; } if (isset($parsed_docblock->tags['internal'])) { $info->internal = \true; } if (isset($parsed_docblock->tags['psalm-internal'])) { $psalm_internal = \reset($parsed_docblock->tags['psalm-internal']); if ($psalm_internal) { $info->psalm_internal = $psalm_internal; } else { throw new \Psalm\Exception\DocblockParseException('@psalm-internal annotation used without specifying namespace'); } $info->psalm_internal = \reset($parsed_docblock->tags['psalm-internal']); $info->internal = \true; } if (isset($parsed_docblock->tags['psalm-suppress'])) { foreach ($parsed_docblock->tags['psalm-suppress'] as $offset => $suppress_entry) { foreach (\Psalm\DocComment::parseSuppressList($suppress_entry) as $issue_offset => $suppressed_issue) { $info->suppressed_issues[$issue_offset + $offset + $comment->getStartFilePos()] = $suppressed_issue; } } } if (isset($parsed_docblock->tags['throws'])) { foreach ($parsed_docblock->tags['throws'] as $offset => $throws_entry) { $throws_class = \preg_split('/[\\s]+/', $throws_entry)[0]; if (!$throws_class) { throw new \Psalm\Exception\IncorrectDocblockException('Unexpectedly empty @throws'); } $info->throws[] = [$throws_class, $offset + $comment->getStartFilePos(), $comment->getStartLine() + \substr_count($comment->getText(), "\n", 0, $offset)]; } } if (\strpos(\strtolower($parsed_docblock->description), '@inheritdoc') !== \false || isset($parsed_docblock->tags['inheritdoc']) || isset($parsed_docblock->tags['inheritDoc'])) { $info->inheritdoc = \true; } if (isset($parsed_docblock->combined_tags['template'])) { foreach ($parsed_docblock->combined_tags['template'] as $template_line) { $template_type = \preg_split('/[\\s]+/', \preg_replace('@^[ \\t]*\\*@m', '', $template_line)); $template_name = \array_shift($template_type); if (!$template_name) { throw new \Psalm\Exception\IncorrectDocblockException('Empty @template tag'); } if (\count($template_type) > 1 && \in_array(\strtolower($template_type[0]), ['as', 'super', 'of'], \true)) { $template_modifier = \strtolower(\array_shift($template_type)); $info->templates[] = [$template_name, $template_modifier, \implode(' ', $template_type), \false]; } else { $info->templates[] = [$template_name, null, null, \false]; } } } if (isset($parsed_docblock->tags['psalm-assert'])) { foreach ($parsed_docblock->tags['psalm-assert'] as $assertion) { $line_parts = self::splitDocLine($assertion); if (\count($line_parts) < 2 || $line_parts[1][0] !== '$') { throw new \Psalm\Exception\IncorrectDocblockException('Misplaced variable'); } $line_parts[0] = self::sanitizeDocblockType($line_parts[0]); $info->assertions[] = ['type' => $line_parts[0], 'param_name' => \substr($line_parts[1], 1)]; } } if (isset($parsed_docblock->tags['psalm-assert-if-true'])) { foreach ($parsed_docblock->tags['psalm-assert-if-true'] as $assertion) { $line_parts = self::splitDocLine($assertion); if (\count($line_parts) < 2 || $line_parts[1][0] !== '$') { throw new \Psalm\Exception\IncorrectDocblockException('Misplaced variable'); } $info->if_true_assertions[] = ['type' => $line_parts[0], 'param_name' => \substr($line_parts[1], 1)]; } } if (isset($parsed_docblock->tags['psalm-assert-if-false'])) { foreach ($parsed_docblock->tags['psalm-assert-if-false'] as $assertion) { $line_parts = self::splitDocLine($assertion); if (\count($line_parts) < 2 || $line_parts[1][0] !== '$') { throw new \Psalm\Exception\IncorrectDocblockException('Misplaced variable'); } $info->if_false_assertions[] = ['type' => $line_parts[0], 'param_name' => \substr($line_parts[1], 1)]; } } $info->variadic = isset($parsed_docblock->tags['psalm-variadic']); $info->pure = isset($parsed_docblock->tags['psalm-pure']) || isset($parsed_docblock->tags['pure']); if (isset($parsed_docblock->tags['psalm-mutation-free'])) { $info->mutation_free = \true; } if (isset($parsed_docblock->tags['psalm-external-mutation-free'])) { $info->external_mutation_free = \true; } if (isset($parsed_docblock->tags['no-named-arguments'])) { $info->no_named_args = \true; } $info->ignore_nullable_return = isset($parsed_docblock->tags['psalm-ignore-nullable-return']); $info->ignore_falsable_return = isset($parsed_docblock->tags['psalm-ignore-falsable-return']); $info->stub_override = isset($parsed_docblock->tags['psalm-stub-override']); return $info; } /** * @param array $return_specials */ private static function extractReturnType(\_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $comment, array $return_specials, \Psalm\Internal\Scanner\FunctionDocblockComment $info) : void { foreach ($return_specials as $offset => $return_block) { $return_lines = \explode("\n", $return_block); if (!\trim($return_lines[0])) { return; } $return_block = \trim($return_block); if (!$return_block) { return; } $line_parts = self::splitDocLine($return_block); if ($line_parts[0][0] !== '{') { if ($line_parts[0][0] === '$' && !\preg_match('/^\\$this(\\||$)/', $line_parts[0])) { throw new \Psalm\Exception\IncorrectDocblockException('Misplaced variable'); } $start = $offset + $comment->getStartFilePos(); $end = $start + \strlen($line_parts[0]); $line_parts[0] = self::sanitizeDocblockType($line_parts[0]); $info->return_type = \array_shift($line_parts); $info->return_type_description = $line_parts ? \implode(' ', $line_parts) : null; $info->return_type_line_number = $comment->getStartLine() + \substr_count($comment->getText(), "\n", 0, $offset); $info->return_type_start = $start; $info->return_type_end = $end; } else { throw new \Psalm\Exception\DocblockParseException('Badly-formatted @return type'); } break; } } /** * @throws DocblockParseException if there was a problem parsing the docblock * * @psalm-suppress MixedArrayAccess */ public static function extractClassLikeDocblockInfo(\_HumbugBoxd02f763d3c56\PhpParser\Node $node, \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $comment, \Psalm\Aliases $aliases) : \Psalm\Internal\Scanner\ClassLikeDocblockComment { $parsed_docblock = \Psalm\DocComment::parsePreservingLength($comment); $codebase = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance()->getCodebase(); $info = new \Psalm\Internal\Scanner\ClassLikeDocblockComment(); if (isset($parsed_docblock->combined_tags['template'])) { foreach ($parsed_docblock->combined_tags['template'] as $offset => $template_line) { $template_type = \preg_split('/[\\s]+/', \preg_replace('@^[ \\t]*\\*@m', '', $template_line)); $template_name = \array_shift($template_type); if (!$template_name) { throw new \Psalm\Exception\IncorrectDocblockException('Empty @template tag'); } if (\count($template_type) > 1 && \in_array(\strtolower($template_type[0]), ['as', 'super', 'of'], \true)) { $template_modifier = \strtolower(\array_shift($template_type)); $info->templates[] = [$template_name, $template_modifier, \implode(' ', $template_type), \false, $offset]; } else { $info->templates[] = [$template_name, null, null, \false, $offset]; } } } if (isset($parsed_docblock->combined_tags['template-covariant'])) { foreach ($parsed_docblock->combined_tags['template-covariant'] as $offset => $template_line) { $template_type = \preg_split('/[\\s]+/', \preg_replace('@^[ \\t]*\\*@m', '', $template_line)); $template_name = \array_shift($template_type); if (!$template_name) { throw new \Psalm\Exception\IncorrectDocblockException('Empty @template-covariant tag'); } if (\count($template_type) > 1 && \in_array(\strtolower($template_type[0]), ['as', 'super', 'of'], \true)) { $template_modifier = \strtolower(\array_shift($template_type)); $info->templates[] = [$template_name, $template_modifier, \implode(' ', $template_type), \true, $offset]; } else { $info->templates[] = [$template_name, null, null, \true, $offset]; } } } if (isset($parsed_docblock->combined_tags['extends'])) { foreach ($parsed_docblock->combined_tags['extends'] as $template_line) { $info->template_extends[] = \trim(\preg_replace('@^[ \\t]*\\*@m', '', $template_line)); } } if (isset($parsed_docblock->tags['psalm-require-extends']) && \count($extension_requirements = $parsed_docblock->tags['psalm-require-extends']) > 0) { $info->extension_requirement = \trim(\preg_replace('@^[ \\t]*\\*@m', '', $extension_requirements[\array_key_first($extension_requirements)])); } if (isset($parsed_docblock->tags['psalm-require-implements'])) { foreach ($parsed_docblock->tags['psalm-require-implements'] as $implementation_requirement) { $info->implementation_requirements[] = \trim(\preg_replace('@^[ \\t]*\\*@m', '', $implementation_requirement)); } } if (isset($parsed_docblock->combined_tags['implements'])) { foreach ($parsed_docblock->combined_tags['implements'] as $template_line) { $info->template_implements[] = \trim(\preg_replace('@^[ \\t]*\\*@m', '', $template_line)); } } if (isset($parsed_docblock->tags['psalm-yield'])) { $yield = \reset($parsed_docblock->tags['psalm-yield']); $info->yield = \trim(\preg_replace('@^[ \\t]*\\*@m', '', $yield)); } if (isset($parsed_docblock->tags['deprecated'])) { $info->deprecated = \true; } if (isset($parsed_docblock->tags['internal'])) { $info->internal = \true; } if (isset($parsed_docblock->tags['final'])) { $info->final = \true; } if (isset($parsed_docblock->tags['psalm-consistent-constructor'])) { $info->consistent_constructor = \true; } if (isset($parsed_docblock->tags['psalm-internal'])) { $psalm_internal = \reset($parsed_docblock->tags['psalm-internal']); if ($psalm_internal) { $info->psalm_internal = $psalm_internal; } else { throw new \Psalm\Exception\DocblockParseException('psalm-internal annotation used without specifying namespace'); } $info->internal = \true; } if (isset($parsed_docblock->tags['mixin'])) { foreach ($parsed_docblock->tags['mixin'] as $rawMixin) { $mixin = \trim($rawMixin); $doc_line_parts = self::splitDocLine($mixin); $mixin = $doc_line_parts[0]; if ($mixin) { $info->mixins[] = $mixin; } else { throw new \Psalm\Exception\DocblockParseException('@mixin annotation used without specifying class'); } } // backwards compatibility if ($info->mixins) { /** @psalm-suppress DeprecatedProperty */ $info->mixin = \reset($info->mixins); } } if (isset($parsed_docblock->tags['psalm-seal-properties'])) { $info->sealed_properties = \true; } if (isset($parsed_docblock->tags['psalm-seal-methods'])) { $info->sealed_methods = \true; } if (isset($parsed_docblock->tags['psalm-immutable']) || isset($parsed_docblock->tags['psalm-mutation-free'])) { $info->mutation_free = \true; $info->external_mutation_free = \true; $info->taint_specialize = \true; } if (isset($parsed_docblock->tags['psalm-external-mutation-free'])) { $info->external_mutation_free = \true; } if (isset($parsed_docblock->tags['psalm-taint-specialize'])) { $info->taint_specialize = \true; } if (isset($parsed_docblock->tags['psalm-override-property-visibility'])) { $info->override_property_visibility = \true; } if (isset($parsed_docblock->tags['psalm-override-method-visibility'])) { $info->override_method_visibility = \true; } if (isset($parsed_docblock->tags['psalm-suppress'])) { foreach ($parsed_docblock->tags['psalm-suppress'] as $offset => $suppress_entry) { foreach (\Psalm\DocComment::parseSuppressList($suppress_entry) as $issue_offset => $suppressed_issue) { $info->suppressed_issues[$issue_offset + $offset + $comment->getStartFilePos()] = $suppressed_issue; } } } if (isset($parsed_docblock->tags['psalm-import-type'])) { foreach ($parsed_docblock->tags['psalm-import-type'] as $offset => $imported_type_entry) { $info->imported_types[] = ['line_number' => $comment->getStartLine() + \substr_count($comment->getText(), "\n", 0, $offset), 'start_offset' => $comment->getStartFilePos() + $offset, 'end_offset' => $comment->getStartFilePos() + $offset + \strlen($imported_type_entry), 'parts' => self::splitDocLine($imported_type_entry) ?: []]; } } if (isset($parsed_docblock->combined_tags['method'])) { foreach ($parsed_docblock->combined_tags['method'] as $offset => $method_entry) { $method_entry = \preg_replace('/[ \\t]+/', ' ', \trim($method_entry)); $docblock_lines = []; $is_static = \false; $has_return = \false; if (!\preg_match('/^([a-z_A-Z][a-z_0-9A-Z]+) *\\(/', $method_entry, $matches)) { $doc_line_parts = self::splitDocLine($method_entry); if ($doc_line_parts[0] === 'static' && !\strpos($doc_line_parts[1], '(')) { $is_static = \true; \array_shift($doc_line_parts); } if (\count($doc_line_parts) > 1) { $docblock_lines[] = '@return ' . \array_shift($doc_line_parts); $has_return = \true; $method_entry = \implode(' ', $doc_line_parts); } } $method_entry = \trim(\preg_replace('/\\/\\/.*/', '', $method_entry)); $method_entry = \preg_replace('/array\\(([0-9a-zA-Z_\'\\" ]+,)*([0-9a-zA-Z_\'\\" ]+)\\)/', '[]', $method_entry); $end_of_method_regex = '/(?create(); } catch (\Psalm\Exception\TypeParseTreeException $e) { throw new \Psalm\Exception\DocblockParseException($method_entry . ' is not a valid method'); } if (!$method_tree instanceof \Psalm\Internal\Type\ParseTree\MethodWithReturnTypeTree && !$method_tree instanceof \Psalm\Internal\Type\ParseTree\MethodTree) { throw new \Psalm\Exception\DocblockParseException($method_entry . ' is not a valid method'); } if ($method_tree instanceof \Psalm\Internal\Type\ParseTree\MethodWithReturnTypeTree) { if (!$has_return) { $docblock_lines[] = '@return ' . \Psalm\Internal\Type\TypeParser::getTypeFromTree($method_tree->children[1], $codebase)->toNamespacedString($aliases->namespace, $aliases->uses, null, \false); } $method_tree = $method_tree->children[0]; } if (!$method_tree instanceof \Psalm\Internal\Type\ParseTree\MethodTree) { throw new \Psalm\Exception\DocblockParseException($method_entry . ' is not a valid method'); } $args = []; foreach ($method_tree->children as $method_tree_child) { if (!$method_tree_child instanceof \Psalm\Internal\Type\ParseTree\MethodParamTree) { throw new \Psalm\Exception\DocblockParseException($method_entry . ' is not a valid method'); } $args[] = ($method_tree_child->byref ? '&' : '') . ($method_tree_child->variadic ? '...' : '') . $method_tree_child->name . ($method_tree_child->default != '' ? ' = ' . $method_tree_child->default : ''); if ($method_tree_child->children) { try { $param_type = \Psalm\Internal\Type\TypeParser::getTypeFromTree($method_tree_child->children[0], $codebase); } catch (\Exception $e) { throw new \Psalm\Exception\DocblockParseException('Badly-formatted @method string ' . $method_entry . ' - ' . $e); } $param_type_string = $param_type->toNamespacedString('\\', [], null, \false); $docblock_lines[] = '@param ' . $param_type_string . ' ' . ($method_tree_child->variadic ? '...' : '') . $method_tree_child->name; } } $function_string = 'function ' . $method_tree->value . '(' . \implode(', ', $args) . ')'; if ($is_static) { $function_string = 'static ' . $function_string; } $function_docblock = $docblock_lines ? "/**\n * " . \implode("\n * ", $docblock_lines) . "\n*/\n" : ""; $php_string = 'php_major_version . '.' . $codebase->php_minor_version); } catch (\Exception $e) { throw new \Psalm\Exception\DocblockParseException('Badly-formatted @method string ' . $method_entry); } if (!$statements || !$statements[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ || !isset($statements[0]->stmts[0]) || !$statements[0]->stmts[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { throw new \Psalm\Exception\DocblockParseException('Badly-formatted @method string ' . $method_entry); } /** @var \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc */ $node_doc_comment = $node->getDocComment(); $statements[0]->stmts[0]->setAttribute('startLine', $node_doc_comment->getStartLine()); $statements[0]->stmts[0]->setAttribute('startFilePos', $node_doc_comment->getStartFilePos()); $statements[0]->stmts[0]->setAttribute('endFilePos', $node->getAttribute('startFilePos')); if ($doc_comment = $statements[0]->stmts[0]->getDocComment()) { $statements[0]->stmts[0]->setDocComment(new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc($doc_comment->getText(), $comment->getStartLine() + \substr_count($comment->getText(), "\n", 0, $offset), $node_doc_comment->getStartFilePos())); } $info->methods[] = $statements[0]->stmts[0]; } } if (isset($parsed_docblock->tags['psalm-stub-override'])) { $info->stub_override = \true; } self::addMagicPropertyToInfo($comment, $info, $parsed_docblock->tags, 'property'); self::addMagicPropertyToInfo($comment, $info, $parsed_docblock->tags, 'psalm-property'); self::addMagicPropertyToInfo($comment, $info, $parsed_docblock->tags, 'property-read'); self::addMagicPropertyToInfo($comment, $info, $parsed_docblock->tags, 'psalm-property-read'); self::addMagicPropertyToInfo($comment, $info, $parsed_docblock->tags, 'property-write'); self::addMagicPropertyToInfo($comment, $info, $parsed_docblock->tags, 'psalm-property-write'); return $info; } /** * @param array> $specials * @param 'property'|'psalm-property'|'property-read'| * 'psalm-property-read'|'property-write'|'psalm-property-write' $property_tag * * @throws DocblockParseException * */ protected static function addMagicPropertyToInfo(\_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $comment, \Psalm\Internal\Scanner\ClassLikeDocblockComment $info, array $specials, string $property_tag) : void { $magic_property_comments = isset($specials[$property_tag]) ? $specials[$property_tag] : []; foreach ($magic_property_comments as $offset => $property) { $line_parts = self::splitDocLine($property); if (\count($line_parts) === 1 && isset($line_parts[0][0]) && $line_parts[0][0] === '$') { continue; } if (\count($line_parts) > 1) { if (\preg_match('/^&?\\$[A-Za-z0-9_]+,?$/', $line_parts[1]) && $line_parts[0][0] !== '{') { $line_parts[1] = \str_replace('&', '', $line_parts[1]); $line_parts[1] = \preg_replace('/,$/', '', $line_parts[1]); $start = $offset + $comment->getStartFilePos(); $end = $start + \strlen($line_parts[0]); $line_parts[0] = \str_replace("\n", '', \preg_replace('@^[ \\t]*\\*@m', '', $line_parts[0])); if ($line_parts[0] === '' || $line_parts[0][0] === '$' && !\preg_match('/^\\$this(\\||$)/', $line_parts[0])) { throw new \Psalm\Exception\IncorrectDocblockException('Misplaced variable'); } $name = \trim($line_parts[1]); if (!\preg_match('/^\\$([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)$/', $name)) { throw new \Psalm\Exception\DocblockParseException('Badly-formatted @property name'); } $info->properties[] = ['name' => $name, 'type' => $line_parts[0], 'line_number' => $comment->getStartLine() + \substr_count($comment->getText(), "\n", 0, $offset), 'tag' => $property_tag, 'start' => $start, 'end' => $end]; } } else { throw new \Psalm\Exception\DocblockParseException('Badly-formatted @property'); } } } /** * @throws DocblockParseException if an invalid string is found * * @return list * * @psalm-pure */ public static function splitDocLine(string $return_block) : array { $brackets = ''; $type = ''; $expects_callable_return = \false; $return_block = \str_replace("\t", ' ', $return_block); $quote_char = null; $escaped = \false; for ($i = 0, $l = \strlen($return_block); $i < $l; ++$i) { $char = $return_block[$i]; $next_char = $i < $l - 1 ? $return_block[$i + 1] : null; $last_char = $i > 0 ? $return_block[$i - 1] : null; if ($quote_char) { if ($char === $quote_char && $i > 1 && !$escaped) { $quote_char = null; $type .= $char; continue; } if ($char === '\\' && !$escaped && ($next_char === $quote_char || $next_char === '\\')) { $escaped = \true; $type .= $char; continue; } $escaped = \false; $type .= $char; continue; } if ($char === '"' || $char === '\'') { $quote_char = $char; $type .= $char; continue; } if ($char === ':' && $last_char === ')') { $expects_callable_return = \true; $type .= $char; continue; } if ($char === '[' || $char === '{' || $char === '(' || $char === '<') { $brackets .= $char; } elseif ($char === ']' || $char === '}' || $char === ')' || $char === '>') { $last_bracket = \substr($brackets, -1); $brackets = \substr($brackets, 0, -1); if ($char === ']' && $last_bracket !== '[' || $char === '}' && $last_bracket !== '{' || $char === ')' && $last_bracket !== '(' || $char === '>' && $last_bracket !== '<') { throw new \Psalm\Exception\DocblockParseException('Invalid string ' . $return_block); } } elseif ($char === ' ') { if ($brackets) { $expects_callable_return = \false; $type .= ' '; continue; } if ($next_char === '|' || $next_char === '&') { $nexter_char = $i < $l - 2 ? $return_block[$i + 2] : null; if ($nexter_char === ' ') { ++$i; $type .= $next_char . ' '; continue; } } if ($last_char === '|' || $last_char === '&') { $type .= ' '; continue; } if ($next_char === ':') { ++$i; $type .= ' :'; $expects_callable_return = \true; continue; } if ($expects_callable_return) { $type .= ' '; $expects_callable_return = \false; continue; } $remaining = \trim(\preg_replace('@^[ \\t]*\\* *@m', ' ', \substr($return_block, $i + 1))); if ($remaining) { return \array_merge([\rtrim($type)], \preg_split('/[ \\s]+/', $remaining)); } return [$type]; } $expects_callable_return = \false; $type .= $char; } return [$type]; } /** * @throws DocblockParseException if a duplicate is found */ private static function checkDuplicatedTags(\Psalm\Internal\Scanner\ParsedDocblock $parsed_docblock) : void { if (\count($parsed_docblock->tags['return'] ?? []) > 1 || \count($parsed_docblock->tags['psalm-return'] ?? []) > 1 || \count($parsed_docblock->tags['phpstan-return'] ?? []) > 1) { throw new \Psalm\Exception\DocblockParseException('Found duplicated @return or prefixed @return tag'); } self::checkDuplicatedParams($parsed_docblock->tags['param'] ?? []); self::checkDuplicatedParams($parsed_docblock->tags['psalm-param'] ?? []); self::checkDuplicatedParams($parsed_docblock->tags['phpstan-param'] ?? []); } /** * @param array $param * * * @throws DocblockParseException if a duplicate is found */ private static function checkDuplicatedParams(array $param) : void { $list_names = self::extractAllParamNames($param); if (\count($list_names) !== \count(\array_unique($list_names))) { throw new \Psalm\Exception\DocblockParseException('Found duplicated @param or prefixed @param tag'); } } /** * @param array $lines * * @return list * * @psalm-pure */ private static function extractAllParamNames(array $lines) : array { $names = []; foreach ($lines as $line) { $split_by_dollar = \explode('$', $line, 2); if (\count($split_by_dollar) > 1) { $split_by_space = \explode(' ', $split_by_dollar[1], 2); $names[] = $split_by_space[0]; } } return $names; } } $stmts * */ public static function doesEverBreak(array $stmts) : bool { if (empty($stmts)) { return \false; } for ($i = \count($stmts) - 1; $i >= 0; --$i) { $stmt = $stmts[$i]; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Break_) { return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_) { if (self::doesEverBreak($stmt->stmts)) { return \true; } if ($stmt->else && self::doesEverBreak($stmt->else->stmts)) { return \true; } foreach ($stmt->elseifs as $elseif) { if (self::doesEverBreak($elseif->stmts)) { return \true; } } } } return \false; } /** * @param array $stmts * @param bool $return_is_exit Exit and Throw statements are treated differently from return if this is false * @param list<'loop'|'switch'> $break_types * * @return list> */ public static function getControlActions(array $stmts, ?\Psalm\Internal\Provider\NodeDataProvider $nodes, array $exit_functions, array $break_types = [], bool $return_is_exit = \true) : array { if (empty($stmts)) { return [self::ACTION_NONE]; } $control_actions = []; for ($i = 0, $c = \count($stmts); $i < $c; ++$i) { $stmt = $stmts[$i]; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Throw_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression && $stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_) { if (!$return_is_exit && $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_) { return \array_merge($control_actions, [self::ACTION_RETURN]); } return [self::ACTION_END]; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression) { if ($stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $stmt->expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->expr->name->parts === ['trigger_error'] && isset($stmt->expr->args[1]) && $stmt->expr->args[1]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \in_array(\end($stmt->expr->args[1]->value->name->parts), ['E_ERROR', 'E_PARSE', 'E_CORE_ERROR', 'E_COMPILE_ERROR', 'E_USER_ERROR'])) { return [self::ACTION_END]; } // This allows calls to functions that always exit to act as exit statements themselves if ($nodes && ($stmt_expr_type = $nodes->getType($stmt->expr)) && $stmt_expr_type->isNever()) { return [self::ACTION_END]; } if ($exit_functions) { if ($stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall) { if ($stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { /** @var string|null */ $resolved_name = $stmt->expr->name->getAttribute('resolvedName'); if ($resolved_name && isset($exit_functions[\strtolower($resolved_name)])) { return [self::ACTION_END]; } } elseif ($stmt->expr->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { /** @var string|null */ $resolved_class_name = $stmt->expr->class->getAttribute('resolvedName'); if ($resolved_class_name && isset($exit_functions[\strtolower($resolved_class_name . '::' . $stmt->expr->name)])) { return [self::ACTION_END]; } } } } continue; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Continue_) { if ($break_types && \end($break_types) === 'switch' && (!$stmt->num || !$stmt->num instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || $stmt->num->value < 2)) { return \array_merge($control_actions, [self::ACTION_LEAVE_SWITCH]); } return \array_values(\array_unique(\array_merge($control_actions, [self::ACTION_CONTINUE]))); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Break_) { if ($break_types && \end($break_types) === 'switch' && (!$stmt->num || !$stmt->num instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || $stmt->num->value < 2)) { return [self::ACTION_LEAVE_SWITCH]; } return \array_values(\array_unique(\array_merge($control_actions, [self::ACTION_BREAK]))); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_) { $if_statement_actions = self::getControlActions($stmt->stmts, $nodes, $exit_functions, $break_types); $else_statement_actions = $stmt->else ? self::getControlActions($stmt->else->stmts, $nodes, $exit_functions, $break_types) : []; $all_same = \count($if_statement_actions) === 1 && $if_statement_actions == $else_statement_actions && $if_statement_actions !== [self::ACTION_NONE]; $all_elseif_actions = []; if ($stmt->elseifs) { foreach ($stmt->elseifs as $elseif) { $elseif_control_actions = self::getControlActions($elseif->stmts, $nodes, $exit_functions, $break_types); $all_same = $all_same && $elseif_control_actions == $if_statement_actions; if (!$all_same) { $all_elseif_actions = \array_merge($elseif_control_actions, $all_elseif_actions); } } } if ($all_same) { return $if_statement_actions; } $control_actions = \array_filter(\array_merge($control_actions, $if_statement_actions, $else_statement_actions, $all_elseif_actions), function ($action) { return $action !== self::ACTION_NONE; }); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Switch_) { $has_ended = \false; $has_non_breaking_default = \false; $has_default_terminator = \false; // iterate backwards in a case statement for ($d = \count($stmt->cases) - 1; $d >= 0; --$d) { $case = $stmt->cases[$d]; $case_actions = self::getControlActions($case->stmts, $nodes, $exit_functions, ['switch']); if (\array_intersect([self::ACTION_LEAVE_SWITCH, self::ACTION_BREAK, self::ACTION_CONTINUE], $case_actions)) { continue 2; } if (!$case->cond) { $has_non_breaking_default = \true; } $case_does_end = $case_actions == [self::ACTION_END]; if ($case_does_end) { $has_ended = \true; } if (!$case_does_end && !$has_ended) { continue 2; } if ($has_non_breaking_default && $case_does_end) { $has_default_terminator = \true; } } if ($has_default_terminator || isset($stmt->allMatched)) { return \array_values(\array_unique(\array_merge($control_actions, [self::ACTION_END]))); } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Do_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\While_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\For_) { $do_actions = self::getControlActions($stmt->stmts, $nodes, $exit_functions, \array_merge($break_types, ['loop'])); $control_actions = \array_filter(\array_merge($control_actions, $do_actions), function ($action) use($break_types) { return $action !== self::ACTION_NONE && ($break_types || $action !== self::ACTION_CONTINUE && $action !== self::ACTION_BREAK); }); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TryCatch) { $try_statement_actions = self::getControlActions($stmt->stmts, $nodes, $exit_functions, $break_types); if ($stmt->catches) { $all_same = \count($try_statement_actions) === 1; foreach ($stmt->catches as $catch) { $catch_actions = self::getControlActions($catch->stmts, $nodes, $exit_functions, $break_types); $all_same = $all_same && $try_statement_actions == $catch_actions; if (!$all_same) { $control_actions = \array_merge($control_actions, $catch_actions); } } if ($all_same && $try_statement_actions !== [self::ACTION_NONE]) { return \array_values(\array_unique(\array_merge($control_actions, $try_statement_actions))); } } elseif (!\in_array(self::ACTION_NONE, $try_statement_actions, \true)) { return \array_values(\array_unique(\array_merge($control_actions, $try_statement_actions))); } if ($stmt->finally) { if ($stmt->finally->stmts) { $finally_statement_actions = self::getControlActions($stmt->finally->stmts, $nodes, $exit_functions, $break_types); if (!\in_array(self::ACTION_NONE, $finally_statement_actions, \true)) { return \array_merge(\array_filter($control_actions, function ($action) { return $action !== self::ACTION_NONE; }), $finally_statement_actions); } } if (!$stmt->catches && !\in_array(self::ACTION_NONE, $try_statement_actions, \true)) { return \array_merge(\array_filter($control_actions, function ($action) { return $action !== self::ACTION_NONE; }), $try_statement_actions); } } $control_actions = \array_filter(\array_merge($control_actions, $try_statement_actions), function ($action) { return $action !== self::ACTION_NONE; }); } } $control_actions[] = self::ACTION_NONE; return \array_values(\array_unique($control_actions)); } /** * @param array $stmts * */ public static function onlyThrowsOrExits(\Psalm\NodeTypeProvider $type_provider, array $stmts) : bool { if (empty($stmts)) { return \false; } for ($i = \count($stmts) - 1; $i >= 0; --$i) { $stmt = $stmts[$i]; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Throw_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression && $stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_) { return \true; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression) { $stmt_type = $type_provider->getType($stmt->expr); if ($stmt_type && $stmt_type->isNever()) { return \true; } } } return \false; } } $new_types * @param array $existing_types * * @return array */ public static function combineKeyedTypes(array $new_types, array $existing_types) : array { $keys = \array_merge(\array_keys($new_types), \array_keys($existing_types)); $keys = \array_unique($keys); $result_types = []; if (empty($new_types)) { return $existing_types; } if (empty($existing_types)) { return $new_types; } foreach ($keys as $key) { if (!isset($existing_types[$key])) { $result_types[$key] = $new_types[$key]; continue; } if (!isset($new_types[$key])) { $result_types[$key] = $existing_types[$key]; continue; } $existing_var_types = $existing_types[$key]; $new_var_types = $new_types[$key]; if ($new_var_types->getId() === $existing_var_types->getId()) { $result_types[$key] = $new_var_types; } else { $result_types[$key] = \Psalm\Type::combineUnionTypes($new_var_types, $existing_var_types); } } return $result_types; } } source = $source; $this->file_analyzer = $source->getFileAnalyzer(); $this->aliases = $source->getAliases(); $this->class = $class; $this->fq_class_name = $fq_class_name; $codebase = $source->getCodebase(); $this->storage = $codebase->classlike_storage_provider->get($fq_class_name); $this->aliases = $aliases; } public function getNamespace() : ?string { return $this->aliases->namespace; } public function getAliases() : \Psalm\Aliases { return $this->aliases; } /** * @return array */ public function getAliasedClassesFlipped() : array { return []; } /** * @return array */ public function getAliasedClassesFlippedReplaceable() : array { return []; } } source = null; } public function getAliases() : \Psalm\Aliases { return $this->source->getAliases(); } /** * @return array */ public function getAliasedClassesFlipped() : array { return $this->source->getAliasedClassesFlipped(); } /** * @return array */ public function getAliasedClassesFlippedReplaceable() : array { return $this->source->getAliasedClassesFlippedReplaceable(); } public function getFQCLN() : ?string { return $this->source->getFQCLN(); } public function getClassName() : ?string { return $this->source->getClassName(); } public function getParentFQCLN() : ?string { return $this->source->getParentFQCLN(); } public function getFileName() : string { return $this->source->getFileName(); } public function getFilePath() : string { return $this->source->getFilePath(); } public function getRootFileName() : string { return $this->source->getRootFileName(); } public function getRootFilePath() : string { return $this->source->getRootFilePath(); } public function setRootFilePath(string $file_path, string $file_name) : void { $this->source->setRootFilePath($file_path, $file_name); } public function hasParentFilePath(string $file_path) : bool { return $this->source->hasParentFilePath($file_path); } public function hasAlreadyRequiredFilePath(string $file_path) : bool { return $this->source->hasAlreadyRequiredFilePath($file_path); } public function getRequireNesting() : int { return $this->source->getRequireNesting(); } /** * @psalm-mutation-free */ public function getSource() : \Psalm\StatementsSource { return $this->source; } /** * Get a list of suppressed issues * * @return array */ public function getSuppressedIssues() : array { return $this->source->getSuppressedIssues(); } /** * @param array $new_issues */ public function addSuppressedIssues(array $new_issues) : void { $this->source->addSuppressedIssues($new_issues); } /** * @param array $new_issues */ public function removeSuppressedIssues(array $new_issues) : void { $this->source->removeSuppressedIssues($new_issues); } public function getNamespace() : ?string { return $this->source->getNamespace(); } public function isStatic() : bool { return $this->source->isStatic(); } /** * @psalm-mutation-free */ public function getCodebase() : \Psalm\Codebase { return $this->source->getCodebase(); } /** * @psalm-mutation-free */ public function getProjectAnalyzer() : \Psalm\Internal\Analyzer\ProjectAnalyzer { return $this->source->getProjectAnalyzer(); } /** * @psalm-mutation-free */ public function getFileAnalyzer() : \Psalm\Internal\Analyzer\FileAnalyzer { return $this->source->getFileAnalyzer(); } /** * @return array>|null */ public function getTemplateTypeMap() : ?array { return $this->source->getTemplateTypeMap(); } public function getNodeTypeProvider() : \Psalm\NodeTypeProvider { return $this->source->getNodeTypeProvider(); } } */ protected $suppressed_issues; /** * @var bool */ protected $is_static = \false; /** * @var StatementsSource */ protected $source; /** * @var ?array */ protected $return_vars_in_scope = []; /** * @var ?array */ protected $return_vars_possibly_in_scope = []; /** * @var Type\Union|null */ private $local_return_type; /** * @var array */ protected static $no_effects_hashes = []; /** * @var bool */ public $track_mutations = \false; /** * @var bool */ public $inferred_impure = \false; /** * @var bool */ public $inferred_has_mutation = \false; /** * Holds param nodes for functions with func_get_args calls * * @var array */ public $param_nodes = []; /** * @var FunctionLikeStorage */ protected $storage; /** * @param Closure|Function_|ClassMethod|ArrowFunction $function */ public function __construct($function, \Psalm\Internal\Analyzer\SourceAnalyzer $source, \Psalm\Storage\FunctionLikeStorage $storage) { $this->function = $function; $this->source = $source; $this->suppressed_issues = $source->getSuppressedIssues(); $this->codebase = $source->getCodebase(); $this->storage = $storage; } /** * @param bool $add_mutations whether or not to add mutations to this method * @param ?array $byref_uses * * @return false|null */ public function analyze(\Psalm\Context $context, \Psalm\Internal\Provider\NodeDataProvider $type_provider, ?\Psalm\Context $global_context = null, bool $add_mutations = \false, ?array $byref_uses = null) : ?bool { $storage = $this->storage; $function_stmts = $this->function->getStmts() ?: []; if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction && isset($function_stmts[0]) && $function_stmts[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_ && $function_stmts[0]->expr) { $function_stmts[0]->setAttributes($function_stmts[0]->expr->getAttributes()); } $hash = null; $real_method_id = null; $method_id = null; $cased_method_id = null; $appearing_class_storage = null; if ($global_context) { foreach ($global_context->constants as $const_name => $var_type) { if (!$context->hasVariable($const_name)) { $context->vars_in_scope[$const_name] = clone $var_type; } } } $codebase = $this->codebase; $project_analyzer = $this->getProjectAnalyzer(); $implemented_docblock_param_types = []; $classlike_storage_provider = $codebase->classlike_storage_provider; if ($codebase->track_unused_suppressions && !isset($storage->suppressed_issues[0])) { foreach ($storage->suppressed_issues as $offset => $issue_name) { \Psalm\IssueBuffer::addUnusedSuppression($this->getFilePath(), $offset, $issue_name); } } foreach ($storage->docblock_issues as $docblock_issue) { \Psalm\IssueBuffer::add($docblock_issue); } $overridden_method_ids = []; if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { if (!$storage instanceof \Psalm\Storage\MethodStorage || !$this instanceof \Psalm\Internal\Analyzer\MethodAnalyzer) { throw new \UnexpectedValueException('$storage must be MethodStorage'); } $real_method_id = $this->getMethodId(); $method_id = $this->getMethodId($context->self); $fq_class_name = (string) $context->self; $appearing_class_storage = $classlike_storage_provider->get($fq_class_name); if ($add_mutations) { if (!$context->collect_initializations) { $hash = \md5($real_method_id . '::' . $context->getScopeSummary()); // if we know that the function has no effects on vars, we don't bother rechecking if (isset(self::$no_effects_hashes[$hash])) { return null; } } } elseif ($context->self) { if ($appearing_class_storage->template_types) { $template_params = []; foreach ($appearing_class_storage->template_types as $param_name => $template_map) { $key = \array_keys($template_map)[0]; $template_params[] = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParam($param_name, \reset($template_map)[0], $key)]); } $this_object_type = new \Psalm\Type\Atomic\TGenericObject($context->self, $template_params); $this_object_type->was_static = !$storage->final; } else { $this_object_type = new \Psalm\Type\Atomic\TNamedObject($context->self); $this_object_type->was_static = !$storage->final; } $context->vars_in_scope['$this'] = new \Psalm\Type\Union([$this_object_type]); if ($storage->external_mutation_free && !$storage->mutation_free_inferred) { $context->vars_in_scope['$this']->reference_free = \true; if ($this->function->name->name !== '__construct') { $context->vars_in_scope['$this']->allow_mutations = \false; } } $context->vars_possibly_in_scope['$this'] = \true; } if ($appearing_class_storage->has_visitor_issues) { return null; } $cased_method_id = $fq_class_name . '::' . $storage->cased_name; $overridden_method_ids = $codebase->methods->getOverriddenMethodIds($method_id); if ($this->function->name->name === '__construct') { $context->inside_constructor = \true; } $codeLocation = new \Psalm\CodeLocation($this, $this->function, null, \true); if ($overridden_method_ids && !$context->collect_initializations && !$context->collect_mutations) { foreach ($overridden_method_ids as $overridden_method_id) { $parent_method_storage = $codebase->methods->getStorage($overridden_method_id); $overridden_fq_class_name = $overridden_method_id->fq_class_name; $parent_storage = $classlike_storage_provider->get($overridden_fq_class_name); if ($this->function->name->name === '__construct' && !$parent_storage->preserve_constructor_signature) { continue; } $implementer_visibility = $storage->visibility; $implementer_appearing_method_id = $codebase->methods->getAppearingMethodId($method_id); $implementer_declaring_method_id = $real_method_id; $declaring_class_storage = $appearing_class_storage; if ($implementer_appearing_method_id && $implementer_appearing_method_id !== $implementer_declaring_method_id) { $appearing_fq_class_name = $implementer_appearing_method_id->fq_class_name; $appearing_method_name = $implementer_appearing_method_id->method_name; $declaring_fq_class_name = $implementer_declaring_method_id->fq_class_name; $appearing_class_storage = $classlike_storage_provider->get($appearing_fq_class_name); $declaring_class_storage = $classlike_storage_provider->get($declaring_fq_class_name); if (isset($appearing_class_storage->trait_visibility_map[$appearing_method_name])) { $implementer_visibility = $appearing_class_storage->trait_visibility_map[$appearing_method_name]; } } // we've already checked this in the class checker if (!isset($appearing_class_storage->class_implements[\strtolower($overridden_fq_class_name)])) { \Psalm\Internal\Analyzer\MethodComparator::compare($codebase, \count($overridden_method_ids) === 1 ? $this->function : null, $declaring_class_storage, $parent_storage, $storage, $parent_method_storage, $fq_class_name, $implementer_visibility, $codeLocation, $storage->suppressed_issues); } foreach ($parent_method_storage->params as $i => $guide_param) { if ($guide_param->type && (!$guide_param->signature_type || $guide_param->signature_type !== $guide_param->type && $storage->inheritdoc || !$parent_storage->user_defined)) { if (!isset($implemented_docblock_param_types[$i])) { $implemented_docblock_param_types[$i] = $guide_param->type; } } } } } \Psalm\Internal\Analyzer\MethodAnalyzer::checkMethodSignatureMustOmitReturnType($storage, $codeLocation); if (!$context->calling_method_id || !$context->collect_initializations) { $context->calling_method_id = \strtolower((string) $method_id); } } elseif ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_) { $function_name = $this->function->name->name; $namespace_prefix = $this->getNamespace(); $cased_method_id = ($namespace_prefix !== null ? $namespace_prefix . '\\' : '') . $function_name; $context->calling_function_id = \strtolower($cased_method_id); } else { // Closure if ($storage->return_type) { $closure_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $storage->return_type, $context->self, $context->self, $this->getParentFQCLN()); } else { $closure_return_type = \Psalm\Type::getMixed(); } $closure_type = new \Psalm\Type\Atomic\TClosure('Closure', $storage->params, $closure_return_type); if ($storage instanceof \Psalm\Storage\FunctionStorage) { $closure_type->byref_uses = $storage->byref_uses; $closure_type->is_pure = $storage->pure; } $type_provider->setType($this->function, new \Psalm\Type\Union([$closure_type])); } $this->suppressed_issues = $this->getSource()->getSuppressedIssues() + $storage->suppressed_issues; if ($storage instanceof \Psalm\Storage\MethodStorage && $storage->is_static) { $this->is_static = \true; } $statements_analyzer = new \Psalm\Internal\Analyzer\StatementsAnalyzer($this, $type_provider); if ($byref_uses) { $statements_analyzer->setByRefUses($byref_uses); } if ($storage->template_types) { foreach ($storage->template_types as $param_name => $_) { $fq_classlike_name = \Psalm\Type::getFQCLNFromString($param_name, $this->getAliases()); if ($codebase->classOrInterfaceExists($fq_classlike_name)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ReservedWord('Cannot use ' . $param_name . ' as template name since the class already exists', new \Psalm\CodeLocation($this, $this->function), 'resource'), $this->getSuppressedIssues())) { // fall through } } } } $template_types = $storage->template_types; if ($appearing_class_storage && $appearing_class_storage->template_types) { $template_types = \array_merge($template_types ?: [], $appearing_class_storage->template_types); } $params = $storage->params; if ($storage instanceof \Psalm\Storage\MethodStorage) { $non_null_param_types = \array_filter($storage->params, function (\Psalm\Storage\FunctionLikeParameter $p) : bool { return $p->type !== null && $p->has_docblock_type; }); } else { $non_null_param_types = \array_filter($storage->params, function (\Psalm\Storage\FunctionLikeParameter $p) : bool { return $p->type !== null; }); } if ($storage instanceof \Psalm\Storage\MethodStorage && $method_id instanceof \Psalm\Internal\MethodIdentifier && $overridden_method_ids) { $types_without_docblocks = \array_filter($storage->params, function (\Psalm\Storage\FunctionLikeParameter $p) : bool { return !$p->type || !$p->has_docblock_type; }); if ($types_without_docblocks) { $params = $codebase->methods->getMethodParams($method_id, $this); } } if ($codebase->alter_code) { $this->alterParams($codebase, $storage, $params, $context); } foreach ($codebase->methods_to_rename as $original_method_id => $new_method_name) { if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && $this instanceof \Psalm\Internal\Analyzer\MethodAnalyzer && \strtolower((string) $this->getMethodId()) === $original_method_id) { $file_manipulations = [new \Psalm\FileManipulation((int) $this->function->name->getAttribute('startFilePos'), (int) $this->function->name->getAttribute('endFilePos') + 1, $new_method_name)]; \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($this->getFilePath(), $file_manipulations); } } $check_stmts = $this->processParams($statements_analyzer, $storage, $cased_method_id, $params, $context, $implemented_docblock_param_types, (bool) $non_null_param_types, (bool) $template_types); if ($storage->pure) { $context->pure = \true; } if ($storage->mutation_free && $cased_method_id && !\strpos($cased_method_id, '__construct') && !($storage instanceof \Psalm\Storage\MethodStorage && $storage->mutation_free_inferred)) { $context->mutation_free = \true; } if ($storage instanceof \Psalm\Storage\MethodStorage && $storage->external_mutation_free && !$storage->mutation_free_inferred) { $context->external_mutation_free = \true; } if ($storage->unused_docblock_params) { foreach ($storage->unused_docblock_params as $param_name => $param_location) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblockParamName('Incorrect param name $' . $param_name . ' in docblock for ' . $cased_method_id, $param_location))) { } } } if ($storage->signature_return_type && $storage->signature_return_type_location) { [$start, $end] = $storage->signature_return_type_location->getSelectionBounds(); $codebase->analyzer->addOffsetReference($this->getFilePath(), $start, $end, (string) $storage->signature_return_type); } if (\Psalm\Internal\Analyzer\FunctionLike\ReturnTypeAnalyzer::checkReturnType($this->function, $project_analyzer, $this, $storage, $context) === \false) { $check_stmts = \false; } if (!$check_stmts) { return \false; } if ($context->collect_initializations || $context->collect_mutations) { $statements_analyzer->addSuppressedIssues(['DocblockTypeContradiction', 'InvalidReturnStatement', 'RedundantCondition', 'RedundantConditionGivenDocblockType', 'TypeDoesNotContainNull', 'TypeDoesNotContainType', 'LoopInvalidation']); if ($context->collect_initializations) { $statements_analyzer->addSuppressedIssues(['UndefinedInterfaceMethod', 'UndefinedMethod', 'PossiblyUndefinedMethod']); } } elseif ($cased_method_id && \strpos($cased_method_id, '__destruct')) { $statements_analyzer->addSuppressedIssues(['InvalidPropertyAssignmentValue', 'PossiblyNullPropertyAssignmentValue']); } $time = \microtime(\true); $project_analyzer = $statements_analyzer->getProjectAnalyzer(); if ($codebase->alter_code && (isset($project_analyzer->getIssuesToFix()['MissingPureAnnotation']) || isset($project_analyzer->getIssuesToFix()['MissingImmutableAnnotation']))) { $this->track_mutations = \true; } elseif ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { $this->track_mutations = \true; } $statements_analyzer->analyze($function_stmts, $context, $global_context, \true); if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['MissingPureAnnotation']) && !$this->inferred_impure && ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ || $this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) && $storage->params && !$overridden_method_ids) { $manipulator = \Psalm\Internal\FileManipulation\FunctionDocblockManipulator::getForFunction($project_analyzer, $this->source->getFilePath(), $this->function); $yield_types = []; $inferred_return_types = \Psalm\Internal\Analyzer\FunctionLike\ReturnTypeCollector::getReturnTypes($codebase, $type_provider, $function_stmts, $yield_types, \true); $inferred_return_type = $inferred_return_types ? \Psalm\Type::combineUnionTypeArray($inferred_return_types, $codebase) : null; if ($inferred_return_type && !$inferred_return_type->isVoid() && !$inferred_return_type->isFalse() && !$inferred_return_type->isNull() && !$inferred_return_type->isSingleIntLiteral() && !$inferred_return_type->isSingleStringLiteral() && !$inferred_return_type->isTrue() && $inferred_return_type->getId() !== 'array') { $manipulator->makePure(); } } if ($this->inferred_has_mutation && $context->self) { $this->codebase->analyzer->addMutableClass($context->self); } if (!$context->collect_initializations && !$context->collect_mutations && $project_analyzer->debug_performance && $cased_method_id) { $traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $node_counter = new \Psalm\Internal\PhpVisitor\NodeCounterVisitor(); $traverser->addVisitor($node_counter); $traverser->traverse($function_stmts); if ($node_counter->count > 5) { $time_taken = \microtime(\true) - $time; $codebase->analyzer->addFunctionTiming($cased_method_id, $time_taken / $node_counter->count); } } $this->examineParamTypes($statements_analyzer, $context, $codebase); foreach ($storage->params as $offset => $function_param) { // only complain if there's no type defined by a parent type if (!$function_param->type && $function_param->location && !isset($implemented_docblock_param_types[$offset])) { if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { \Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingClosureParamType('Parameter $' . $function_param->name . ' has no provided type', $function_param->location), $storage->suppressed_issues + $this->getSuppressedIssues()); } else { \Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingParamType('Parameter $' . $function_param->name . ' has no provided type', $function_param->location), $storage->suppressed_issues + $this->getSuppressedIssues()); } } } if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { $this->verifyReturnType($function_stmts, $statements_analyzer, $storage->return_type, $this->source->getFQCLN(), $storage->return_type_location, $context->has_returned, $global_context && $global_context->inside_call); $closure_yield_types = []; $closure_return_types = \Psalm\Internal\Analyzer\FunctionLike\ReturnTypeCollector::getReturnTypes($codebase, $type_provider, $function_stmts, $closure_yield_types, \true); $closure_return_type = $closure_return_types ? \Psalm\Type::combineUnionTypeArray($closure_return_types, $codebase) : null; $closure_yield_type = $closure_yield_types ? \Psalm\Type::combineUnionTypeArray($closure_yield_types, $codebase) : null; if ($closure_return_type || $closure_yield_type) { if ($closure_yield_type) { $closure_return_type = $closure_yield_type; } if ($function_type = $statements_analyzer->node_data->getType($this->function)) { /** * @var Type\Atomic\TClosure */ $closure_atomic = \array_values($function_type->getAtomicTypes())[0]; if ($storage->return_type === $storage->signature_return_type && (!$storage->return_type || $storage->return_type->hasMixed() || \Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $closure_return_type, $storage->return_type))) { $closure_atomic->return_type = $closure_return_type; } $closure_atomic->is_pure = !$this->inferred_impure; } } } if ($codebase->collect_references && !$context->collect_initializations && !$context->collect_mutations && $codebase->find_unused_variables && $context->check_variables) { $this->checkParamReferences($statements_analyzer, $storage, $appearing_class_storage, $context); } foreach ($storage->throws as $expected_exception => $_) { if (($expected_exception === 'self' || $expected_exception === 'static') && $context->self) { $expected_exception = $context->self; } if (isset($storage->throw_locations[$expected_exception])) { if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($statements_analyzer, $expected_exception, $storage->throw_locations[$expected_exception], $context->self, $context->calling_method_id, $statements_analyzer->getSuppressedIssues(), \false, \false, \true, \true)) { $input_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject($expected_exception)]); $container_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject('Exception'), new \Psalm\Type\Atomic\TNamedObject('Throwable')]); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $input_type, $container_type)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidThrow('Class supplied for @throws ' . $expected_exception . ' does not implement Throwable', $storage->throw_locations[$expected_exception], $expected_exception), $statements_analyzer->getSuppressedIssues())) { // fall through } } if ($codebase->alter_code) { $codebase->classlikes->handleDocblockTypeInMigration($codebase, $this, $input_type, $storage->throw_locations[$expected_exception], $context->calling_method_id); } } } } foreach ($statements_analyzer->getUncaughtThrows($context) as $possibly_thrown_exception => $codelocations) { $is_expected = \false; foreach ($storage->throws as $expected_exception => $_) { if ($expected_exception === $possibly_thrown_exception || $codebase->classExtendsOrImplements($possibly_thrown_exception, $expected_exception)) { $is_expected = \true; break; } } if (!$is_expected) { foreach ($codelocations as $codelocation) { // issues are suppressed in ThrowAnalyzer, CallAnalyzer, etc. if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingThrowsDocblock($possibly_thrown_exception . ' is thrown but not caught - please either catch' . ' or add a @throws annotation', $codelocation))) { // fall through } } } } if ($codebase->taint_flow_graph && $this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && $cased_method_id && $storage->specialize_call && isset($context->vars_in_scope['$this']) && $context->vars_in_scope['$this']->parent_nodes) { $method_source = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodReturn((string) $method_id, $cased_method_id, $storage->location); $codebase->taint_flow_graph->addNode($method_source); foreach ($context->vars_in_scope['$this']->parent_nodes as $parent_node) { $codebase->taint_flow_graph->addPath($parent_node, $method_source, '$this'); } } if ($add_mutations) { if ($this->return_vars_in_scope !== null) { $context->vars_in_scope = \Psalm\Internal\Analyzer\TypeAnalyzer::combineKeyedTypes($context->vars_in_scope, $this->return_vars_in_scope); } if ($this->return_vars_possibly_in_scope !== null) { $context->vars_possibly_in_scope = \array_merge($context->vars_possibly_in_scope, $this->return_vars_possibly_in_scope); } foreach ($context->vars_in_scope as $var => $_) { if (\strpos($var, '$this->') !== 0 && $var !== '$this') { unset($context->vars_in_scope[$var]); } } foreach ($context->vars_possibly_in_scope as $var => $_) { if (\strpos($var, '$this->') !== 0 && $var !== '$this') { unset($context->vars_possibly_in_scope[$var]); } } if ($hash && $real_method_id && $this instanceof \Psalm\Internal\Analyzer\MethodAnalyzer && !$context->collect_initializations) { $new_hash = \md5($real_method_id . '::' . $context->getScopeSummary()); if ($new_hash === $hash) { self::$no_effects_hashes[$hash] = \true; } } } $plugin_classes = $codebase->config->after_functionlike_checks; if ($plugin_classes) { $file_manipulations = []; foreach ($plugin_classes as $plugin_fq_class_name) { if ($plugin_fq_class_name::afterStatementAnalysis($this->function, $storage, $this, $codebase, $file_manipulations) === \false) { return \false; } } if ($file_manipulations) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($this->getFilePath(), $file_manipulations); } } return null; } private function checkParamReferences(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Storage\FunctionLikeStorage $storage, ?\Psalm\Storage\ClassLikeStorage $class_storage, \Psalm\Context $context) : void { $codebase = $statements_analyzer->getCodebase(); $unused_params = []; foreach ($statements_analyzer->getUnusedVarLocations() as [$var_name, $original_location]) { if (!\array_key_exists(\substr($var_name, 1), $storage->param_lookup)) { continue; } if (\strpos($var_name, '$_') === 0 || \strpos($var_name, '$unused') === 0 && $var_name !== '$unused') { continue; } $position = \array_search(\substr($var_name, 1), \array_keys($storage->param_lookup), \true); if ($position === \false) { throw new \UnexpectedValueException('$position should not be false here'); } if ($storage->params[$position]->by_ref) { continue; } $did_match_param = \false; foreach ($this->function->params as $param) { if ($param->var->getAttribute('endFilePos') === $original_location->raw_file_end) { $did_match_param = \true; break; } } if (!$did_match_param) { continue; } $assignment_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_name, $original_location); if ($statements_analyzer->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph && $statements_analyzer->data_flow_graph->isVariableUsed($assignment_node)) { continue; } if (!$storage instanceof \Psalm\Storage\MethodStorage || !$storage->cased_name || $storage->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnusedClosureParam('Param ' . $var_name . ' is never referenced in this method', $original_location), $this->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnusedParam('Param ' . $var_name . ' is never referenced in this method', $original_location), $this->getSuppressedIssues())) { // fall through } } } else { $fq_class_name = (string) $context->self; $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); $method_name_lc = \strtolower($storage->cased_name); if ($storage->abstract) { continue; } if (isset($class_storage->overridden_method_ids[$method_name_lc])) { $parent_method_id = \end($class_storage->overridden_method_ids[$method_name_lc]); if ($parent_method_id) { $parent_method_storage = $codebase->methods->getStorage($parent_method_id); // if the parent method has a param at that position and isn't abstract if (!$parent_method_storage->abstract && isset($parent_method_storage->params[$position])) { continue; } } } $unused_params[$position] = $original_location; } } if ($storage instanceof \Psalm\Storage\MethodStorage && $this instanceof \Psalm\Internal\Analyzer\MethodAnalyzer && $class_storage && $storage->cased_name && $storage->visibility !== \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE) { $method_id_lc = \strtolower((string) $this->getMethodId()); foreach ($storage->params as $i => $_) { if (!isset($unused_params[$i])) { $codebase->file_reference_provider->addMethodParamUse($method_id_lc, $i, $method_id_lc); $method_name_lc = \strtolower($storage->cased_name); if (!isset($class_storage->overridden_method_ids[$method_name_lc])) { continue; } foreach ($class_storage->overridden_method_ids[$method_name_lc] as $parent_method_id) { $codebase->file_reference_provider->addMethodParamUse(\strtolower((string) $parent_method_id), $i, $method_id_lc); } } } } } /** * @param array $params * @param array $implemented_docblock_param_types */ private function processParams(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Storage\FunctionLikeStorage $storage, ?string $cased_method_id, array $params, \Psalm\Context $context, array $implemented_docblock_param_types, bool $non_null_param_types, bool $has_template_types) : bool { $check_stmts = \true; $codebase = $statements_analyzer->getCodebase(); $project_analyzer = $statements_analyzer->getProjectAnalyzer(); foreach ($params as $offset => $function_param) { $signature_type = $function_param->signature_type; $signature_type_location = $function_param->signature_type_location; if ($signature_type && $signature_type_location && $signature_type->hasObjectType()) { $referenced_type = $signature_type; if ($referenced_type->isNullable()) { $referenced_type = clone $referenced_type; $referenced_type->removeType('null'); } [$start, $end] = $signature_type_location->getSelectionBounds(); $codebase->analyzer->addOffsetReference($this->getFilePath(), $start, $end, (string) $referenced_type); } if ($signature_type) { $signature_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $signature_type, $context->self, $context->self, $this->getParentFQCLN()); } if ($function_param->type) { $is_signature_type = $function_param->type === $function_param->signature_type; if ($is_signature_type && $storage instanceof \Psalm\Storage\MethodStorage && $storage->inheritdoc && isset($implemented_docblock_param_types[$offset])) { $param_type = clone $implemented_docblock_param_types[$offset]; } else { $param_type = clone $function_param->type; } $param_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $param_type, $context->self, $context->self, $this->getParentFQCLN()); if ($function_param->type_location) { if ($param_type->check($this, $function_param->type_location, $storage->suppressed_issues, [], \false, \false, $this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && \strtolower($this->function->name->name) !== '__construct') === \false) { $check_stmts = \false; } } } else { if (!$non_null_param_types && isset($implemented_docblock_param_types[$offset])) { $param_type = clone $implemented_docblock_param_types[$offset]; $param_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $param_type, $context->self, $context->self, $this->getParentFQCLN()); } else { $param_type = \Psalm\Type::getMixed(); } } if ($param_type->hasTemplate() && $param_type->isSingle()) { /** @var Type\Atomic\TTemplateParam */ $template_type = \array_values($param_type->getAtomicTypes())[0]; if ($template_type->as->getTemplateTypes()) { $param_type = $template_type->as; } } $var_type = $param_type; if ($function_param->is_variadic) { $var_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TList($param_type)]); } if ($statements_analyzer->data_flow_graph && $function_param->location) { $param_assignment = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment('$' . $function_param->name, $function_param->location); $statements_analyzer->data_flow_graph->addNode($param_assignment); if ($cased_method_id) { $type_source = \Psalm\Internal\DataFlow\DataFlowNode::getForMethodArgument($cased_method_id, $cased_method_id, $offset, $function_param->location, null); $statements_analyzer->data_flow_graph->addPath($type_source, $param_assignment, 'param'); } if ($function_param->by_ref && $codebase->find_unused_variables) { $statements_analyzer->data_flow_graph->addPath($param_assignment, new \Psalm\Internal\DataFlow\DataFlowNode('variable-use', 'variable use', null), 'variable-use'); } if ($storage->variadic) { $this->param_nodes += [$param_assignment->id => $param_assignment]; } $var_type->parent_nodes += [$param_assignment->id => $param_assignment]; } $context->vars_in_scope['$' . $function_param->name] = $var_type; $context->vars_possibly_in_scope['$' . $function_param->name] = \true; if ($function_param->by_ref) { $context->vars_in_scope['$' . $function_param->name]->by_ref = \true; } $parser_param = $this->function->getParams()[$offset]; if ($function_param->location) { $statements_analyzer->registerVariable('$' . $function_param->name, $function_param->location, null); } if (!$function_param->type_location || !$function_param->location) { if ($parser_param->default) { \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $parser_param->default, $context); } continue; } if ($signature_type) { $union_comparison_result = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $param_type, $signature_type, \false, \false, $union_comparison_result) && !$union_comparison_result->type_coerced_from_mixed) { if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['MismatchingDocblockParamType'])) { $this->addOrUpdateParamType($project_analyzer, $function_param->name, $signature_type, \true); continue; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MismatchingDocblockParamType('Parameter $' . $function_param->name . ' has wrong type \'' . $param_type . '\', should be \'' . $signature_type . '\'', $function_param->type_location), $storage->suppressed_issues, \true)) { // do nothing } if ($signature_type->check($this, $function_param->type_location, $storage->suppressed_issues, [], \false) === \false) { $check_stmts = \false; } continue; } } if ($parser_param->default) { \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $parser_param->default, $context); $default_type = $statements_analyzer->node_data->getType($parser_param->default); if ($default_type && !$default_type->hasMixed() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $default_type, $param_type, \false, \false, null, \true)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidParamDefault('Default value type ' . $default_type->getId() . ' for argument ' . ($offset + 1) . ' of method ' . $cased_method_id . ' does not match the given type ' . $param_type->getId(), $function_param->type_location))) { // fall through } } } if ($has_template_types) { $substituted_type = clone $param_type; if ($substituted_type->check($this->source, $function_param->type_location, $this->suppressed_issues, [], \false) === \false) { $check_stmts = \false; } } else { if ($param_type->isVoid()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ReservedWord('Parameter cannot be void', $function_param->type_location, 'void'), $this->suppressed_issues)) { // fall through } } if ($param_type->check($this->source, $function_param->type_location, $this->suppressed_issues, [], \false) === \false) { $check_stmts = \false; } } if ($codebase->collect_locations) { if ($function_param->type_location !== $function_param->signature_type_location && $function_param->signature_type_location && $function_param->signature_type) { if ($function_param->signature_type->check($this->source, $function_param->signature_type_location, $this->suppressed_issues, [], \false) === \false) { $check_stmts = \false; } } } if ($function_param->by_ref) { // register by ref params as having been used, to avoid false positives // @todo change the assignment analysis *just* for byref params // so that we don't have to do this $context->hasVariable('$' . $function_param->name); } } return $check_stmts; } /** * @param \Psalm\Storage\FunctionLikeParameter[] $params */ private function alterParams(\Psalm\Codebase $codebase, \Psalm\Storage\FunctionLikeStorage $storage, array $params, \Psalm\Context $context) : void { foreach ($this->function->params as $param) { $param_name_node = null; if ($param->type instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $param_name_node = $param->type; } elseif ($param->type instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType && $param->type->type instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $param_name_node = $param->type->type; } if ($param_name_node) { $resolved_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($param_name_node, $this->getAliases()); $parent_fqcln = $this->getParentFQCLN(); if ($resolved_name === 'self' && $context->self) { $resolved_name = (string) $context->self; } elseif ($resolved_name === 'parent' && $parent_fqcln) { $resolved_name = $parent_fqcln; } $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $this, $param_name_node, $resolved_name, $context->calling_method_id, \false, \true); } } if ($this->function->returnType) { $return_name_node = null; if ($this->function->returnType instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $return_name_node = $this->function->returnType; } elseif ($this->function->returnType instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType && $this->function->returnType->type instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $return_name_node = $this->function->returnType->type; } if ($return_name_node) { $resolved_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($return_name_node, $this->getAliases()); $parent_fqcln = $this->getParentFQCLN(); if ($resolved_name === 'self' && $context->self) { $resolved_name = (string) $context->self; } elseif ($resolved_name === 'parent' && $parent_fqcln) { $resolved_name = $parent_fqcln; } $codebase->classlikes->handleClassLikeReferenceInMigration($codebase, $this, $return_name_node, $resolved_name, $context->calling_method_id, \false, \true); } } if ($storage->return_type && $storage->return_type_location && $storage->return_type_location !== $storage->signature_return_type_location) { $replace_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $storage->return_type, $context->self, 'static', $this->getParentFQCLN(), \false); $codebase->classlikes->handleDocblockTypeInMigration($codebase, $this, $replace_type, $storage->return_type_location, $context->calling_method_id); } foreach ($params as $function_param) { if ($function_param->type && $function_param->type_location && $function_param->type_location !== $function_param->signature_type_location && $function_param->type_location->file_path === $this->getFilePath()) { $replace_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $function_param->type, $context->self, 'static', $this->getParentFQCLN(), \false); $codebase->classlikes->handleDocblockTypeInMigration($codebase, $this, $replace_type, $function_param->type_location, $context->calling_method_id); } } } /** * @param array $function_stmts */ public function verifyReturnType(array $function_stmts, \Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, ?\Psalm\Type\Union $return_type = null, ?string $fq_class_name = null, ?\Psalm\CodeLocation $return_type_location = null, bool $did_explicitly_return = \false, bool $closure_inside_call = \false) : void { \Psalm\Internal\Analyzer\FunctionLike\ReturnTypeAnalyzer::verifyReturnType($this->function, $function_stmts, $statements_analyzer, $statements_analyzer->node_data, $this, $return_type, $fq_class_name, $return_type_location, [], $did_explicitly_return, $closure_inside_call); } public function addOrUpdateParamType(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, string $param_name, \Psalm\Type\Union $inferred_return_type, bool $docblock_only = \false) : void { $manipulator = \Psalm\Internal\FileManipulation\FunctionDocblockManipulator::getForFunction($project_analyzer, $this->source->getFilePath(), $this->function); $codebase = $project_analyzer->getCodebase(); $is_final = \true; $fqcln = $this->source->getFQCLN(); if ($fqcln !== null && $this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $class_storage = $codebase->classlike_storage_provider->get($fqcln); $is_final = $this->function->isFinal() || $class_storage->final; } $allow_native_type = !$docblock_only && $codebase->php_major_version >= 7 && ($codebase->allow_backwards_incompatible_changes || $is_final || !$this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod); $manipulator->setParamType($param_name, $allow_native_type ? $inferred_return_type->toPhpString($this->source->getNamespace(), $this->source->getAliasedClassesFlipped(), $this->source->getFQCLN(), $project_analyzer->getCodebase()->php_major_version, $project_analyzer->getCodebase()->php_minor_version) : null, $inferred_return_type->toNamespacedString($this->source->getNamespace(), $this->source->getAliasedClassesFlipped(), $this->source->getFQCLN(), \false), $inferred_return_type->toNamespacedString($this->source->getNamespace(), $this->source->getAliasedClassesFlipped(), $this->source->getFQCLN(), \true)); } /** * Adds return types for the given function * * @param string $return_type * */ public function addReturnTypes(\Psalm\Context $context) : void { if ($this->return_vars_in_scope !== null) { $this->return_vars_in_scope = \Psalm\Internal\Analyzer\TypeAnalyzer::combineKeyedTypes($context->vars_in_scope, $this->return_vars_in_scope); } else { $this->return_vars_in_scope = $context->vars_in_scope; } if ($this->return_vars_possibly_in_scope !== null) { $this->return_vars_possibly_in_scope = \array_merge($context->vars_possibly_in_scope, $this->return_vars_possibly_in_scope); } else { $this->return_vars_possibly_in_scope = $context->vars_possibly_in_scope; } } public function examineParamTypes(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \Psalm\Context $context, \Psalm\Codebase $codebase, \_HumbugBoxd02f763d3c56\PhpParser\Node $stmt = null) : void { $storage = $this->getFunctionLikeStorage($statements_analyzer); foreach ($storage->params as $param) { if ($param->by_ref && isset($context->vars_in_scope['$' . $param->name]) && !$param->is_variadic) { $actual_type = $context->vars_in_scope['$' . $param->name]; $param_out_type = $param->out_type ?: $param->type; if ($param_out_type && !$actual_type->hasMixed() && $param->location) { if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $actual_type, $param_out_type, $actual_type->ignore_nullable_issues, $actual_type->ignore_falsable_issues)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ReferenceConstraintViolation('Variable ' . '$' . $param->name . ' is limited to values of type ' . $param_out_type->getId() . ' because it is passed by reference, ' . $actual_type->getId() . ' type found. Use @param-out to specify ' . 'a different output type', $stmt ? new \Psalm\CodeLocation($this, $stmt) : $param->location), $statements_analyzer->getSuppressedIssues())) { // fall through } } } } } } public function getMethodName() : ?string { if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { return (string) $this->function->name; } return null; } public function getCorrectlyCasedMethodId(?string $context_self = null) : string { if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $function_name = (string) $this->function->name; return ($context_self ?: $this->source->getFQCLN()) . '::' . $function_name; } if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_) { $namespace = $this->source->getNamespace(); return ($namespace ? $namespace . '\\' : '') . $this->function->name; } if (!$this instanceof \Psalm\Internal\Analyzer\ClosureAnalyzer) { throw new \UnexpectedValueException('This is weird'); } return $this->getClosureId(); } public function getFunctionLikeStorage(?\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer = null) : \Psalm\Storage\FunctionLikeStorage { $codebase = $this->codebase; if ($this->function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && $this instanceof \Psalm\Internal\Analyzer\MethodAnalyzer) { $method_id = $this->getMethodId(); $codebase_methods = $codebase->methods; try { return $codebase_methods->getStorage($method_id); } catch (\UnexpectedValueException $e) { $declaring_method_id = $codebase_methods->getDeclaringMethodId($method_id); if ($declaring_method_id === null) { throw new \UnexpectedValueException('Cannot get storage for function that doesn‘t exist'); } // happens for fake constructors return $codebase_methods->getStorage($declaring_method_id); } } if ($this instanceof \Psalm\Internal\Analyzer\FunctionAnalyzer) { $function_id = $this->getFunctionId(); } elseif ($this instanceof \Psalm\Internal\Analyzer\ClosureAnalyzer) { $function_id = $this->getClosureId(); } else { throw new \UnexpectedValueException('This is weird'); } return $codebase->functions->getStorage($statements_analyzer, $function_id); } /** @return non-empty-string */ public function getId() : string { if ($this instanceof \Psalm\Internal\Analyzer\MethodAnalyzer) { return (string) $this->getMethodId(); } if ($this instanceof \Psalm\Internal\Analyzer\FunctionAnalyzer) { return $this->getFunctionId(); } if ($this instanceof \Psalm\Internal\Analyzer\ClosureAnalyzer) { return $this->getClosureId(); } throw new \UnexpectedValueException('This is weird'); } /** * @return array */ public function getAliasedClassesFlipped() : array { if ($this->source instanceof \Psalm\Internal\Analyzer\NamespaceAnalyzer || $this->source instanceof \Psalm\Internal\Analyzer\FileAnalyzer || $this->source instanceof \Psalm\Internal\Analyzer\ClassLikeAnalyzer) { return $this->source->getAliasedClassesFlipped(); } return []; } /** * @return array */ public function getAliasedClassesFlippedReplaceable() : array { if ($this->source instanceof \Psalm\Internal\Analyzer\NamespaceAnalyzer || $this->source instanceof \Psalm\Internal\Analyzer\FileAnalyzer || $this->source instanceof \Psalm\Internal\Analyzer\ClassLikeAnalyzer) { return $this->source->getAliasedClassesFlippedReplaceable(); } return []; } public function getFQCLN() : ?string { return $this->source->getFQCLN(); } public function getClassName() : ?string { return $this->source->getClassName(); } /** * @return array>|null */ public function getTemplateTypeMap() : ?array { if ($this->source instanceof \Psalm\Internal\Analyzer\ClassLikeAnalyzer) { return ($this->source->getTemplateTypeMap() ?: []) + ($this->storage->template_types ?: []); } return $this->storage->template_types; } public function getParentFQCLN() : ?string { return $this->source->getParentFQCLN(); } public function getNodeTypeProvider() : \Psalm\NodeTypeProvider { return $this->source->getNodeTypeProvider(); } public function isStatic() : bool { return $this->is_static; } public function getSource() : \Psalm\StatementsSource { return $this->source; } public function getCodebase() : \Psalm\Codebase { return $this->codebase; } /** * Get a list of suppressed issues * * @return array */ public function getSuppressedIssues() : array { return $this->suppressed_issues; } /** * @param array $new_issues */ public function addSuppressedIssues(array $new_issues) : void { if (isset($new_issues[0])) { $new_issues = \array_combine($new_issues, $new_issues); } $this->suppressed_issues = $new_issues + $this->suppressed_issues; } /** * @param array $new_issues */ public function removeSuppressedIssues(array $new_issues) : void { if (isset($new_issues[0])) { $new_issues = \array_combine($new_issues, $new_issues); } $this->suppressed_issues = \array_diff_key($this->suppressed_issues, $new_issues); } /** * Adds a suppressed issue, useful when creating a method checker from scratch * */ public function addSuppressedIssue(string $issue_name) : void { $this->suppressed_issues[] = $issue_name; } public static function clearCache() : void { self::$no_effects_hashes = []; } public function getLocalReturnType(\Psalm\Type\Union $storage_return_type, bool $final = \false) : \Psalm\Type\Union { if ($this->local_return_type) { return $this->local_return_type; } $this->local_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($this->codebase, $storage_return_type, $this->getFQCLN(), $this->getFQCLN(), $this->getParentFQCLN(), \true, \true, $final); return $this->local_return_type; } } */ private $all_vars = []; /** * @var array */ private $var_branch_points = []; /** * Possibly undefined variables should be initialised if we're altering code * * @var array|null */ private $vars_to_initialize; /** * @var array */ private $function_analyzers = []; /** * @var array */ private $unused_var_locations = []; /** * @var ?array */ public $byref_uses; /** * @var ParsedDocblock|null */ private $parsed_docblock = null; /** * @var ?string */ private $fake_this_class = null; /** @var \Psalm\Internal\Provider\NodeDataProvider */ public $node_data; /** @var ?DataFlowGraph */ public $data_flow_graph; public function __construct(\Psalm\Internal\Analyzer\SourceAnalyzer $source, \Psalm\Internal\Provider\NodeDataProvider $node_data) { $this->source = $source; $this->file_analyzer = $source->getFileAnalyzer(); $this->codebase = $source->getCodebase(); $this->node_data = $node_data; if ($this->codebase->taint_flow_graph) { $this->data_flow_graph = new \Psalm\Internal\Codebase\TaintFlowGraph(); } elseif ($this->codebase->find_unused_variables) { $this->data_flow_graph = new \Psalm\Internal\Codebase\VariableUseGraph(); } } /** * Checks an array of statements for validity * * @param array $stmts * * @return null|false */ public function analyze(array $stmts, \Psalm\Context $context, ?\Psalm\Context $global_context = null, bool $root_scope = \false) : ?bool { if (!$stmts) { return null; } // hoist functions to the top $this->hoistFunctions($stmts, $context); $project_analyzer = $this->getFileAnalyzer()->project_analyzer; $codebase = $project_analyzer->getCodebase(); if ($codebase->config->hoist_constants) { self::hoistConstants($this, $stmts, $context); } foreach ($stmts as $stmt) { if (self::analyzeStatement($this, $stmt, $context, $global_context) === \false) { return \false; } } if ($root_scope && !$context->collect_initializations && $codebase->find_unused_variables && $context->check_variables) { //var_dump($this->data_flow_graph); $this->checkUnreferencedVars($stmts); } if ($codebase->alter_code && $root_scope && $this->vars_to_initialize) { $file_contents = $codebase->getFileContents($this->getFilePath()); foreach ($this->vars_to_initialize as $var_id => $branch_point) { $newline_pos = (int) \strrpos($file_contents, "\n", $branch_point - \strlen($file_contents)) + 1; $indentation = \substr($file_contents, $newline_pos, $branch_point - $newline_pos); \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($this->getFilePath(), [new \Psalm\FileManipulation($branch_point, $branch_point, $var_id . ' = null;' . "\n" . $indentation)]); } } if ($root_scope && $this->data_flow_graph instanceof \Psalm\Internal\Codebase\TaintFlowGraph && $this->codebase->taint_flow_graph && $codebase->config->trackTaintsInPath($this->getFilePath())) { $this->codebase->taint_flow_graph->addGraph($this->data_flow_graph); } return null; } /** * @param array $stmts */ private function hoistFunctions(array $stmts, \Psalm\Context $context) : void { foreach ($stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_) { $function_name = \strtolower($stmt->name->name); if ($ns = $this->getNamespace()) { $fq_function_name = \strtolower($ns) . '\\' . $function_name; } else { $fq_function_name = $function_name; } if ($this->data_flow_graph && $this->codebase->find_unused_variables) { foreach ($stmt->stmts as $function_stmt) { if ($function_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Global_) { foreach ($function_stmt->vars as $var) { if (!$var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable || !\is_string($var->name)) { continue; } $var_id = '$' . $var->name; if ($var_id !== '$argv' && $var_id !== '$argc') { $context->byref_constraints[$var_id] = new \Psalm\Internal\ReferenceConstraint(); } } } } } try { $function_analyzer = new \Psalm\Internal\Analyzer\FunctionAnalyzer($stmt, $this->source); $this->function_analyzers[$fq_function_name] = $function_analyzer; } catch (\UnexpectedValueException $e) { // do nothing } } } } /** * @param array $stmts */ private static function hoistConstants(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, array $stmts, \Psalm\Context $context) : void { $codebase = $statements_analyzer->getCodebase(); foreach ($stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_) { foreach ($stmt->consts as $const) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::setConstType($statements_analyzer, $const->name->name, \Psalm\Internal\Analyzer\Statements\Expression\SimpleTypeInferer::infer($codebase, $statements_analyzer->node_data, $const->value, $statements_analyzer->getAliases(), $statements_analyzer) ?: \Psalm\Type::getMixed(), $context); } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression && $stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $stmt->expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->expr->name->parts === ['define'] && isset($stmt->expr->args[1])) { $const_name = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::getConstName($stmt->expr->args[0]->value, $statements_analyzer->node_data, $codebase, $statements_analyzer->getAliases()); if ($const_name !== null) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::setConstType($statements_analyzer, $const_name, \Psalm\Internal\Analyzer\Statements\Expression\SimpleTypeInferer::infer($codebase, $statements_analyzer->node_data, $stmt->expr->args[1]->value, $statements_analyzer->getAliases(), $statements_analyzer) ?: \Psalm\Type::getMixed(), $context); } } } } /** * @return false|null */ private static function analyzeStatement(\Psalm\Internal\Analyzer\StatementsAnalyzer $statements_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt $stmt, \Psalm\Context $context, ?\Psalm\Context $global_context) : ?bool { $ignore_variable_property = \false; $ignore_variable_method = \false; $codebase = $statements_analyzer->getCodebase(); if ($context->has_returned && !$context->collect_initializations && !$context->collect_mutations && !$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop && !$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\InlineHTML) { if ($codebase->find_unused_variables) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnevaluatedCode('Expressions after return/throw/continue', new \Psalm\CodeLocation($statements_analyzer->source, $stmt)), $statements_analyzer->source->getSuppressedIssues())) { return \false; } } return null; } if ($statements_analyzer->getProjectAnalyzer()->debug_lines) { \fwrite(\STDERR, $statements_analyzer->getFilePath() . ':' . $stmt->getLine() . "\n"); } /* if (isset($context->vars_in_scope['$array']) && !$stmt instanceof PhpParser\Node\Stmt\Nop) { var_dump($stmt->getLine(), $context->vars_in_scope['$array']); } */ $new_issues = null; $traced_variables = []; if ($docblock = $stmt->getDocComment()) { $statements_analyzer->parseStatementDocblock($docblock, $stmt, $context); if (isset($statements_analyzer->parsed_docblock->tags['psalm-trace'])) { foreach ($statements_analyzer->parsed_docblock->tags['psalm-trace'] as $traced_variable_line) { $possible_traced_variable_names = \preg_split('/[\\s]+/', $traced_variable_line); if ($possible_traced_variable_names) { $traced_variables = \array_merge($traced_variables, \array_filter($possible_traced_variable_names)); } } } if (isset($statements_analyzer->parsed_docblock->tags['psalm-ignore-variable-method'])) { $context->ignore_variable_method = $ignore_variable_method = \true; } if (isset($statements_analyzer->parsed_docblock->tags['psalm-ignore-variable-property'])) { $context->ignore_variable_property = $ignore_variable_property = \true; } if (isset($statements_analyzer->parsed_docblock->tags['psalm-suppress'])) { $suppressed = $statements_analyzer->parsed_docblock->tags['psalm-suppress']; if ($suppressed) { $new_issues = []; foreach ($suppressed as $offset => $suppress_entry) { foreach (\Psalm\DocComment::parseSuppressList($suppress_entry) as $issue_offset => $issue_type) { $new_issues[$issue_offset + $offset + $docblock->getStartFilePos()] = $issue_type; if ($issue_type === 'InaccessibleMethod') { continue; } if ($codebase->track_unused_suppressions) { \Psalm\IssueBuffer::addUnusedSuppression($statements_analyzer->getFilePath(), $issue_offset + $offset + $docblock->getStartFilePos(), $issue_type); } } } $statements_analyzer->addSuppressedIssues($new_issues); } } if (isset($statements_analyzer->parsed_docblock->combined_tags['var']) && !($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression && $stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) && !$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_ && !$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_) { $file_path = $statements_analyzer->getRootFilePath(); $file_storage_provider = $codebase->file_storage_provider; $file_storage = $file_storage_provider->get($file_path); $template_type_map = $statements_analyzer->getTemplateTypeMap(); $var_comments = []; try { $var_comments = \Psalm\Internal\Analyzer\CommentAnalyzer::arrayToDocblocks($docblock, $statements_analyzer->parsed_docblock, $statements_analyzer->getSource(), $statements_analyzer->getAliases(), $template_type_map, $file_storage->type_aliases); } catch (\Psalm\Exception\IncorrectDocblockException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingDocblockType((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)))) { // fall through } } catch (\Psalm\Exception\DocblockParseException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($statements_analyzer->getSource(), $stmt)))) { // fall through } } foreach ($var_comments as $var_comment) { \Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::assignTypeFromVarDocblock($statements_analyzer, $stmt, $var_comment, $context); } } } else { $statements_analyzer->parsed_docblock = null; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_) { if (\Psalm\Internal\Analyzer\Statements\Block\IfAnalyzer::analyze($statements_analyzer, $stmt, $context) === \false) { return \false; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TryCatch) { if (\Psalm\Internal\Analyzer\Statements\Block\TryAnalyzer::analyze($statements_analyzer, $stmt, $context) === \false) { return \false; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\For_) { if (\Psalm\Internal\Analyzer\Statements\Block\ForAnalyzer::analyze($statements_analyzer, $stmt, $context) === \false) { return \false; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_) { if (\Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer::analyze($statements_analyzer, $stmt, $context) === \false) { return \false; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\While_) { if (\Psalm\Internal\Analyzer\Statements\Block\WhileAnalyzer::analyze($statements_analyzer, $stmt, $context) === \false) { return \false; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Do_) { \Psalm\Internal\Analyzer\Statements\Block\DoAnalyzer::analyze($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::analyzeConstAssignment($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Unset_) { \Psalm\Internal\Analyzer\Statements\UnsetAnalyzer::analyze($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_) { \Psalm\Internal\Analyzer\Statements\ReturnAnalyzer::analyze($statements_analyzer, $stmt, $context); $context->has_returned = \true; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Throw_) { \Psalm\Internal\Analyzer\Statements\ThrowAnalyzer::analyze($statements_analyzer, $stmt, $context); $context->has_returned = \true; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Switch_) { \Psalm\Internal\Analyzer\Statements\Block\SwitchAnalyzer::analyze($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Break_) { \Psalm\Internal\Analyzer\Statements\BreakAnalyzer::analyze($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Continue_) { \Psalm\Internal\Analyzer\Statements\ContinueAnalyzer::analyze($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Static_) { \Psalm\Internal\Analyzer\Statements\StaticAnalyzer::analyze($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Echo_) { if (\Psalm\Internal\Analyzer\Statements\EchoAnalyzer::analyze($statements_analyzer, $stmt, $context) === \false) { return \false; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_) { \Psalm\Internal\Analyzer\FunctionAnalyzer::analyzeStatement($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression) { if (\Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context, \false, $global_context, \true) === \false) { return \false; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\InlineHTML) { // do nothing } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Global_) { \Psalm\Internal\Analyzer\Statements\GlobalAnalyzer::analyze($statements_analyzer, $stmt, $context, $global_context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { \Psalm\Internal\Analyzer\Statements\Expression\Assignment\InstancePropertyAssignmentAnalyzer::analyzeStatement($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst) { \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ClassConstFetchAnalyzer::analyzeClassConstAssignment($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { try { $class_analyzer = new \Psalm\Internal\Analyzer\ClassAnalyzer($stmt, $statements_analyzer->source, $stmt->name ? $stmt->name->name : null); $class_analyzer->analyze(null, $global_context); } catch (\InvalidArgumentException $e) { // disregard this exception, we'll likely see it elsewhere in the form // of an issue } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Nop) { // do nothing } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Goto_) { // do nothing } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Label) { // do nothing } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Declare_) { foreach ($stmt->declares as $declaration) { if ((string) $declaration->key === 'strict_types' && $declaration->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber && $declaration->value->value === 1) { $context->strict_types = \true; } } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\HaltCompiler) { $context->has_returned = \true; } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UnrecognizedStatement('Psalm does not understand ' . \get_class($stmt), new \Psalm\CodeLocation($statements_analyzer->source, $stmt)), $statements_analyzer->getSuppressedIssues())) { return \false; } } $codebase = $statements_analyzer->getCodebase(); $plugin_classes = $codebase->config->after_statement_checks; if ($plugin_classes) { $file_manipulations = []; foreach ($plugin_classes as $plugin_fq_class_name) { if ($plugin_fq_class_name::afterStatementAnalysis($stmt, $context, $statements_analyzer, $codebase, $file_manipulations) === \false) { return \false; } } if ($file_manipulations) { \Psalm\Internal\FileManipulation\FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations); } } if ($new_issues) { $statements_analyzer->removeSuppressedIssues($new_issues); } if ($ignore_variable_property) { $context->ignore_variable_property = \false; } if ($ignore_variable_method) { $context->ignore_variable_method = \false; } foreach ($traced_variables as $traced_variable) { if (isset($context->vars_in_scope[$traced_variable])) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\Trace($traced_variable . ': ' . $context->vars_in_scope[$traced_variable]->getId(), new \Psalm\CodeLocation($statements_analyzer->source, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedTrace('Attempt to trace undefined variable ' . $traced_variable, new \Psalm\CodeLocation($statements_analyzer->source, $stmt)), $statements_analyzer->getSuppressedIssues())) { // fall through } } } return null; } private function parseStatementDocblock(\_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc $docblock, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt $stmt, \Psalm\Context $context) : void { $codebase = $this->getCodebase(); try { $this->parsed_docblock = \Psalm\DocComment::parsePreservingLength($docblock); } catch (\Psalm\Exception\DocblockParseException $e) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($this->getSource(), $stmt, null, \true)))) { // fall through } $this->parsed_docblock = null; } $comments = $this->parsed_docblock; if (isset($comments->tags['psalm-scope-this'])) { $trimmed = \trim(\reset($comments->tags['psalm-scope-this'])); if (!$codebase->classExists($trimmed)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedDocblockClass('Scope class ' . $trimmed . ' does not exist', new \Psalm\CodeLocation($this->getSource(), $stmt, null, \true), $trimmed))) { // fall through } } else { $this_type = \Psalm\Type::parseString($trimmed); $context->self = $trimmed; $context->vars_in_scope['$this'] = $this_type; $this->setFQCLN($trimmed); } } } /** * @param array $stmts */ public function checkUnreferencedVars(array $stmts) : void { $source = $this->getSource(); $codebase = $source->getCodebase(); $function_storage = $source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer ? $source->getFunctionLikeStorage($this) : null; $var_list = \array_column($this->unused_var_locations, 0); $loc_list = \array_column($this->unused_var_locations, 1); $project_analyzer = $this->getProjectAnalyzer(); $unused_var_remover = new \Psalm\Internal\Analyzer\Statements\UnusedAssignmentRemover(); foreach ($this->unused_var_locations as [$var_id, $original_location]) { if (\substr($var_id, 0, 2) === '$_') { continue; } if ($function_storage) { $param_index = \array_search(\substr($var_id, 1), \array_keys($function_storage->param_lookup)); if ($param_index !== \false) { $param = $function_storage->params[$param_index]; if ($param->location && ($original_location->raw_file_end === $param->location->raw_file_end || $param->by_ref)) { continue; } } } $assignment_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_id, $original_location); if (!isset($this->byref_uses[$var_id]) && !\Psalm\Internal\Analyzer\Statements\Expression\Fetch\VariableFetchAnalyzer::isSuperGlobal($var_id) && $this->data_flow_graph instanceof \Psalm\Internal\Codebase\VariableUseGraph && !$this->data_flow_graph->isVariableUsed($assignment_node)) { $issue = new \Psalm\Issue\UnusedVariable('Variable ' . $var_id . ' is never referenced', $original_location); if ($codebase->alter_code && !$unused_var_remover->checkIfVarRemoved($var_id, $original_location) && isset($project_analyzer->getIssuesToFix()['UnusedVariable']) && !\Psalm\IssueBuffer::isSuppressed($issue, $this->getSuppressedIssues())) { $unused_var_remover->findUnusedAssignment($this->getCodebase(), $stmts, \array_combine($var_list, $loc_list), $var_id, $original_location); } if (\Psalm\IssueBuffer::accepts($issue, $this->getSuppressedIssues(), \true)) { // fall through } } } } public function hasVariable(string $var_name) : bool { return isset($this->all_vars[$var_name]); } public function registerVariable(string $var_id, \Psalm\CodeLocation $location, ?int $branch_point) : void { $this->all_vars[$var_id] = $location; if ($branch_point) { $this->var_branch_points[$var_id] = $branch_point; } $this->registerVariableAssignment($var_id, $location); } public function registerVariableAssignment(string $var_id, \Psalm\CodeLocation $location) : void { $this->unused_var_locations[$location->getHash()] = [$var_id, $location]; } /** * @return array */ public function getUnusedVarLocations() : array { return $this->unused_var_locations; } public function registerPossiblyUndefinedVariable(string $undefined_var_id, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable $stmt) : void { if (!$this->data_flow_graph) { return; } $use_location = new \Psalm\CodeLocation($this->getSource(), $stmt); $use_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($undefined_var_id, $use_location); $stmt_type = $this->node_data->getType($stmt); if ($stmt_type) { $stmt_type->parent_nodes[$use_node->id] = $use_node; } foreach ($this->unused_var_locations as [$var_id, $original_location]) { if ($var_id === $undefined_var_id) { $parent_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_id, $original_location); $this->data_flow_graph->addPath($parent_node, $use_node, '='); } } } /** * @return array */ public function getParentNodesForPossiblyUndefinedVariable(string $undefined_var_id) : array { if (!$this->data_flow_graph) { return []; } $parent_nodes = []; foreach ($this->unused_var_locations as [$var_id, $original_location]) { if ($var_id === $undefined_var_id) { $assignment_node = \Psalm\Internal\DataFlow\DataFlowNode::getForAssignment($var_id, $original_location); $parent_nodes[$assignment_node->id] = $assignment_node; } } return $parent_nodes; } /** * The first appearance of the variable in this set of statements being evaluated */ public function getFirstAppearance(string $var_id) : ?\Psalm\CodeLocation { return isset($this->all_vars[$var_id]) ? $this->all_vars[$var_id] : null; } public function getBranchPoint(string $var_id) : ?int { return isset($this->var_branch_points[$var_id]) ? $this->var_branch_points[$var_id] : null; } public function addVariableInitialization(string $var_id, int $branch_point) : void { $this->vars_to_initialize[$var_id] = $branch_point; } public function getFileAnalyzer() : \Psalm\Internal\Analyzer\FileAnalyzer { return $this->file_analyzer; } public function getCodebase() : \Psalm\Codebase { return $this->codebase; } /** * @return array */ public function getFunctionAnalyzers() : array { return $this->function_analyzers; } /** * @param array $byref_uses */ public function setByRefUses(array $byref_uses) : void { $this->byref_uses = $byref_uses; } /** * @return array> */ public function getUncaughtThrows(\Psalm\Context $context) : array { $uncaught_throws = []; if ($context->collect_exceptions) { if ($context->possibly_thrown_exceptions) { $config = $this->codebase->config; $ignored_exceptions = \array_change_key_case($context->is_global ? $config->ignored_exceptions_in_global_scope : $config->ignored_exceptions); $ignored_exceptions_and_descendants = \array_change_key_case($context->is_global ? $config->ignored_exceptions_and_descendants_in_global_scope : $config->ignored_exceptions_and_descendants); foreach ($context->possibly_thrown_exceptions as $possibly_thrown_exception => $codelocations) { if (isset($ignored_exceptions[\strtolower($possibly_thrown_exception)])) { continue; } $is_expected = \false; foreach ($ignored_exceptions_and_descendants as $expected_exception => $_) { try { if ($expected_exception === \strtolower($possibly_thrown_exception) || $this->codebase->classExtends($possibly_thrown_exception, $expected_exception)) { $is_expected = \true; break; } } catch (\InvalidArgumentException $e) { $is_expected = \true; break; } } if (!$is_expected) { $uncaught_throws[$possibly_thrown_exception] = $codelocations; } } } } return $uncaught_throws; } public function getFunctionAnalyzer(string $function_id) : ?\Psalm\Internal\Analyzer\FunctionAnalyzer { return $this->function_analyzers[$function_id] ?? null; } public function getParsedDocblock() : ?\Psalm\Internal\Scanner\ParsedDocblock { return $this->parsed_docblock; } public function getFQCLN() : ?string { if ($this->fake_this_class) { return $this->fake_this_class; } return parent::getFQCLN(); } public function setFQCLN(string $fake_this_class) : void { $this->fake_this_class = $fake_this_class; } /** * @return \Psalm\Internal\Provider\NodeDataProvider */ public function getNodeTypeProvider() : \Psalm\NodeTypeProvider { return $this->node_data; } } $stmts * @param list $yield_types * * @return list a list of return types */ public static function getReturnTypes(\Psalm\Codebase $codebase, \Psalm\Internal\Provider\NodeDataProvider $nodes, array $stmts, array &$yield_types, bool $collapse_types = \false) : array { $return_types = []; foreach ($stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_) { if (!$stmt->expr) { $return_types[] = \Psalm\Type::getVoid(); } elseif ($stmt_type = $nodes->getType($stmt)) { $return_types[] = $stmt_type; $yield_types = \array_merge($yield_types, self::getYieldTypeFromExpression($stmt->expr, $nodes)); } else { $return_types[] = \Psalm\Type::getMixed(); } break; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Throw_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Break_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Continue_) { break; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression) { if ($stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, [$stmt->expr->expr], $yield_types)); } $yield_types = \array_merge($yield_types, self::getYieldTypeFromExpression($stmt->expr, $nodes)); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $stmt->stmts, $yield_types)); foreach ($stmt->elseifs as $elseif) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $elseif->stmts, $yield_types)); } if ($stmt->else) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $stmt->else->stmts, $yield_types)); } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TryCatch) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $stmt->stmts, $yield_types)); foreach ($stmt->catches as $catch) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $catch->stmts, $yield_types)); } if ($stmt->finally) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $stmt->finally->stmts, $yield_types)); } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\For_) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $stmt->stmts, $yield_types)); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $stmt->stmts, $yield_types)); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\While_) { $yield_types = \array_merge($yield_types, self::getYieldTypeFromExpression($stmt->cond, $nodes)); $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $stmt->stmts, $yield_types)); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Do_) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $stmt->stmts, $yield_types)); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Switch_) { foreach ($stmt->cases as $case) { $return_types = \array_merge($return_types, self::getReturnTypes($codebase, $nodes, $case->stmts, $yield_types)); } } } // if we're at the top level and we're not ending in a return, make sure to add possible null if ($collapse_types) { // if it's a generator, boil everything down to a single generator return type if ($yield_types) { $key_type = null; $value_type = null; $yield_type = \Psalm\Type::combineUnionTypeArray($yield_types, null); foreach ($yield_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TKeyedArray) { $type = $type->getGenericArrayType(); } if ($type instanceof \Psalm\Type\Atomic\TList) { $type = new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $type->type_param]); } if ($type instanceof \Psalm\Type\Atomic\TArray) { [$key_type_param, $value_type_param] = $type->type_params; if (!$key_type) { $key_type = clone $key_type_param; } else { $key_type = \Psalm\Type::combineUnionTypes($key_type_param, $key_type); } if (!$value_type) { $value_type = clone $value_type_param; } else { $value_type = \Psalm\Type::combineUnionTypes($value_type_param, $value_type); } } elseif ($type instanceof \Psalm\Type\Atomic\TIterable || $type instanceof \Psalm\Type\Atomic\TNamedObject) { \Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer::getKeyValueParamsForTraversableObject($type, $codebase, $key_type, $value_type); } } $yield_types = [new \Psalm\Type\Union([new \Psalm\Type\Atomic\TGenericObject('Generator', [$key_type ?: \Psalm\Type::getMixed(), $value_type ?: \Psalm\Type::getMixed(), \Psalm\Type::getMixed(), $return_types ? \Psalm\Type::combineUnionTypeArray($return_types, null) : \Psalm\Type::getVoid()])])]; } } return $return_types; } /** * @return list */ protected static function getYieldTypeFromExpression(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, \Psalm\Internal\Provider\NodeDataProvider $nodes) : array { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_) { $key_type = null; if ($stmt->key && ($stmt_key_type = $nodes->getType($stmt->key))) { $key_type = $stmt_key_type; } if ($stmt->value && ($value_type = $nodes->getType($stmt->value))) { $generator_type = new \Psalm\Type\Atomic\TGenericObject('Generator', [$key_type ? clone $key_type : \Psalm\Type::getInt(), clone $value_type, \Psalm\Type::getMixed(), \Psalm\Type::getMixed()]); return [new \Psalm\Type\Union([$generator_type])]; } return [\Psalm\Type::getMixed()]; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom) { if ($stmt_expr_type = $nodes->getType($stmt->expr)) { return [$stmt_expr_type]; } return [\Psalm\Type::getMixed()]; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp) { return \array_merge(self::getYieldTypeFromExpression($stmt->left, $nodes), self::getYieldTypeFromExpression($stmt->right, $nodes)); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { return self::getYieldTypeFromExpression($stmt->expr, $nodes); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall) { $yield_types = []; foreach ($stmt->args as $arg) { $yield_types = \array_merge($yield_types, self::getYieldTypeFromExpression($arg->value, $nodes)); } return $yield_types; } return []; } } getSuppressedIssues(); $codebase = $source->getCodebase(); $project_analyzer = $source->getProjectAnalyzer(); $function_like_storage = null; if ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { $function_like_storage = $function_like_analyzer->getFunctionLikeStorage($source); } elseif ($source instanceof \Psalm\Internal\Analyzer\ClassAnalyzer || $source instanceof \Psalm\Internal\Analyzer\TraitAnalyzer) { $function_like_storage = $function_like_analyzer->getFunctionLikeStorage(); } $cased_method_id = $function_like_analyzer->getCorrectlyCasedMethodId(); if (!$function->getStmts() && ($function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && ($source instanceof \Psalm\Internal\Analyzer\InterfaceAnalyzer || $function->isAbstract()))) { if (!$return_type) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingReturnType('Method ' . $cased_method_id . ' does not have a return type', new \Psalm\CodeLocation($function_like_analyzer, $function->name, null, \true)), $suppressed_issues)) { // fall through } } return null; } $is_to_string = $function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && \strtolower($function->name->name) === '__tostring'; if ($function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && \substr($function->name->name, 0, 2) === '__' && !$is_to_string && !$return_type) { // do not check __construct, __set, __get, __call etc. return null; } if (!$return_type_location) { $return_type_location = new \Psalm\CodeLocation($function_like_analyzer, $function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction ? $function : $function->name); } $inferred_yield_types = []; $inferred_return_type_parts = \Psalm\Internal\Analyzer\FunctionLike\ReturnTypeCollector::getReturnTypes($codebase, $type_provider, $function_stmts, $inferred_yield_types, \true); if (!$inferred_return_type_parts) { $did_explicitly_return = \true; } if ((!$return_type || $return_type->from_docblock) && \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($function_stmts, $type_provider, $codebase->config->exit_functions) !== [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END] && !$inferred_yield_types && \count($inferred_return_type_parts) && !$did_explicitly_return) { // only add null if we have a return statement elsewhere and it wasn't void foreach ($inferred_return_type_parts as $inferred_return_type_part) { if (!$inferred_return_type_part->isVoid()) { $atomic_null = new \Psalm\Type\Atomic\TNull(); $atomic_null->from_docblock = \true; $inferred_return_type_parts[] = new \Psalm\Type\Union([$atomic_null]); break; } } } /** @psalm-suppress PossiblyUndefinedStringArrayOffset */ if ($return_type && (!$return_type->from_docblock || $return_type->isNullable() && !$return_type->hasTemplate() && !$return_type->getAtomicTypes()['null']->from_docblock) && !$return_type->isVoid() && !$inferred_yield_types && (!$function_like_storage || !$function_like_storage->has_yield) && \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($function_stmts, $type_provider, $codebase->config->exit_functions) !== [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END]) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidReturnType('Not all code paths of ' . $cased_method_id . ' end in a return statement, return type ' . $return_type . ' expected', $return_type_location), $suppressed_issues)) { return \false; } return null; } if ($return_type && $return_type->isNever() && !$inferred_yield_types && \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($function_stmts, $type_provider, $codebase->config->exit_functions, [], \false) !== [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END]) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidReturnType($cased_method_id . ' is not expected to return any values but it does, ' . 'either implicitly or explicitly', $return_type_location), $suppressed_issues)) { return \false; } return null; } $inferred_return_type = $inferred_return_type_parts ? \Psalm\Type::combineUnionTypeArray($inferred_return_type_parts, $codebase) : \Psalm\Type::getVoid(); $inferred_yield_type = $inferred_yield_types ? \Psalm\Type::combineUnionTypeArray($inferred_yield_types, $codebase) : null; if ($inferred_yield_type) { $inferred_return_type = $inferred_yield_type; } $unsafe_return_type = \false; // prevent any return types that do not return a value from being used in PHP typehints if ($codebase->alter_code && $inferred_return_type->isNullable() && !$inferred_yield_types) { foreach ($inferred_return_type_parts as $inferred_return_type_part) { if ($inferred_return_type_part->isVoid()) { $unsafe_return_type = \true; break; } } } $inferred_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $inferred_return_type, $source->getFQCLN(), $source->getFQCLN(), $source->getParentFQCLN()); // hack until we have proper yield type collection if ($function_like_storage && $function_like_storage->has_yield && !$inferred_yield_type && !$inferred_return_type->isVoid()) { $inferred_return_type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TNamedObject('Generator')]); } if ($is_to_string) { if (!$inferred_return_type->hasMixed() && !\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $inferred_return_type, \Psalm\Type::getString(), $inferred_return_type->ignore_nullable_issues, $inferred_return_type->ignore_falsable_issues)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidToString('__toString methods must return a string, ' . $inferred_return_type . ' returned', $return_type_location), $suppressed_issues)) { return \false; } } return null; } if (!$return_type) { if ($function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { if (!$closure_inside_call || $inferred_return_type->isMixed()) { if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['MissingClosureReturnType']) && !\in_array('MissingClosureReturnType', $suppressed_issues)) { if ($inferred_return_type->hasMixed() || $inferred_return_type->isNull()) { return null; } self::addOrUpdateReturnType($function, $project_analyzer, $inferred_return_type, $source, ($project_analyzer->only_replace_php_types_with_non_docblock_types || $unsafe_return_type) && $inferred_return_type->from_docblock, $function_like_storage); return null; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingClosureReturnType('Closure does not have a return type, expecting ' . $inferred_return_type->getId(), new \Psalm\CodeLocation($function_like_analyzer, $function, null, \true)), $suppressed_issues, !$inferred_return_type->hasMixed() && !$inferred_return_type->isNull())) { // fall through } } return null; } if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['MissingReturnType']) && !\in_array('MissingReturnType', $suppressed_issues)) { if ($inferred_return_type->hasMixed() || $inferred_return_type->isNull()) { return null; } self::addOrUpdateReturnType($function, $project_analyzer, $inferred_return_type, $source, $compatible_method_ids || !$did_explicitly_return || ($project_analyzer->only_replace_php_types_with_non_docblock_types || $unsafe_return_type) && $inferred_return_type->from_docblock, $function_like_storage); return null; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingReturnType('Method ' . $cased_method_id . ' does not have a return type' . (!$inferred_return_type->hasMixed() ? ', expecting ' . $inferred_return_type->getId() : ''), new \Psalm\CodeLocation($function_like_analyzer, $function->name, null, \true)), $suppressed_issues, !$inferred_return_type->hasMixed() && !$inferred_return_type->isNull())) { // fall through } return null; } $self_fq_class_name = $fq_class_name ?: $source->getFQCLN(); $parent_class = null; if ($self_fq_class_name) { $classlike_storage = $codebase->classlike_storage_provider->get($self_fq_class_name); $parent_class = $classlike_storage->parent_class; } // passing it through fleshOutTypes eradicates errant $ vars $declared_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $return_type, $self_fq_class_name, $self_fq_class_name, $parent_class, \true, \true, $function_like_storage instanceof \Psalm\Storage\MethodStorage && $function_like_storage->final); if (!$inferred_return_type_parts && !$inferred_yield_types && (!$function_like_storage || !$function_like_storage->has_yield)) { if ($declared_return_type->isVoid() || $declared_return_type->isNever()) { return null; } if (\Psalm\Internal\Analyzer\ScopeAnalyzer::onlyThrowsOrExits($type_provider, $function_stmts)) { // if there's a single throw statement, it's presumably an exception saying this method is not to be // used return null; } if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['InvalidReturnType']) && !\in_array('InvalidReturnType', $suppressed_issues)) { self::addOrUpdateReturnType($function, $project_analyzer, \Psalm\Type::getVoid(), $source, $compatible_method_ids || ($project_analyzer->only_replace_php_types_with_non_docblock_types || $unsafe_return_type) && $inferred_return_type->from_docblock); return null; } if (!$declared_return_type->from_docblock || !$declared_return_type->isNullable()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidReturnType('No return statements were found for method ' . $cased_method_id . ' but return type \'' . $declared_return_type . '\' was expected', $return_type_location), $suppressed_issues, \true)) { return \false; } } return null; } if (!$declared_return_type->hasMixed()) { if ($inferred_return_type->isVoid() && ($declared_return_type->isVoid() || $function_like_storage && $function_like_storage->has_yield)) { return null; } if ($inferred_return_type->hasMixed() || $inferred_return_type->isEmpty()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedInferredReturnType('Could not verify return type \'' . $declared_return_type . '\' for ' . $cased_method_id, $return_type_location), $suppressed_issues)) { return \false; } return null; } $union_comparison_results = new \Psalm\Internal\Type\Comparator\TypeComparisonResult(); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $inferred_return_type, $declared_return_type, \true, \true, $union_comparison_results)) { // is the declared return type more specific than the inferred one? if ($union_comparison_results->type_coerced) { if ($union_comparison_results->type_coerced_from_mixed) { if (!$union_comparison_results->type_coerced_from_as_mixed) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MixedReturnTypeCoercion('The declared return type \'' . $declared_return_type->getId() . '\' for ' . $cased_method_id . ' is more specific than the inferred return type ' . '\'' . $inferred_return_type->getId() . '\'', $return_type_location), $suppressed_issues)) { return \false; } } } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MoreSpecificReturnType('The declared return type \'' . $declared_return_type->getId() . '\' for ' . $cased_method_id . ' is more specific than the inferred return type ' . '\'' . $inferred_return_type->getId() . '\'', $return_type_location), $suppressed_issues)) { return \false; } } } else { if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['InvalidReturnType']) && !\in_array('InvalidReturnType', $suppressed_issues)) { self::addOrUpdateReturnType($function, $project_analyzer, $inferred_return_type, $source, ($project_analyzer->only_replace_php_types_with_non_docblock_types || $unsafe_return_type) && $inferred_return_type->from_docblock, $function_like_storage); return null; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidReturnType('The declared return type \'' . $declared_return_type->getId() . '\' for ' . $cased_method_id . ' is incorrect, got \'' . $inferred_return_type->getId() . '\'', $return_type_location), $suppressed_issues, \true)) { return \false; } } } elseif ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['LessSpecificReturnType']) && !\in_array('LessSpecificReturnType', $suppressed_issues) && !($function_like_storage instanceof \Psalm\Storage\MethodStorage && $function_like_storage->inheritdoc)) { if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $declared_return_type, $inferred_return_type, \false, \false)) { self::addOrUpdateReturnType($function, $project_analyzer, $inferred_return_type, $source, $compatible_method_ids || ($project_analyzer->only_replace_php_types_with_non_docblock_types || $unsafe_return_type) && $inferred_return_type->from_docblock, $function_like_storage); return null; } } elseif (!$inferred_return_type->hasMixed() && (!$inferred_return_type->isNullable() && $declared_return_type->isNullable() || !$inferred_return_type->isFalsable() && $declared_return_type->isFalsable())) { if ($function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ || $function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction || $function->isPrivate()) { $check_for_less_specific_type = \true; } elseif ($source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) { if ($function_like_storage instanceof \Psalm\Storage\MethodStorage) { $check_for_less_specific_type = !$function_like_storage->overridden_somewhere; } else { $check_for_less_specific_type = \false; } } else { $check_for_less_specific_type = \false; } if ($check_for_less_specific_type) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\LessSpecificReturnType('The inferred return type \'' . $inferred_return_type . '\' for ' . $cased_method_id . ' is more specific than the declared return type \'' . $declared_return_type . '\'', $return_type_location), $suppressed_issues, !($function_like_storage instanceof \Psalm\Storage\MethodStorage && $function_like_storage->inheritdoc))) { return \false; } } } if (!$inferred_return_type->ignore_nullable_issues && $inferred_return_type->isNullable() && !$declared_return_type->isNullable() && !$declared_return_type->hasTemplate() && !$declared_return_type->isVoid()) { if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['InvalidNullableReturnType']) && !\in_array('InvalidNullableReturnType', $suppressed_issues) && !$inferred_return_type->isNull()) { self::addOrUpdateReturnType($function, $project_analyzer, $inferred_return_type, $source, ($project_analyzer->only_replace_php_types_with_non_docblock_types || $unsafe_return_type) && $inferred_return_type->from_docblock, $function_like_storage); return null; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidNullableReturnType('The declared return type \'' . $declared_return_type . '\' for ' . $cased_method_id . ' is not nullable, but \'' . $inferred_return_type . '\' contains null', $return_type_location), $suppressed_issues, !$inferred_return_type->isNull())) { return \false; } } if (!$inferred_return_type->ignore_falsable_issues && $inferred_return_type->isFalsable() && !$declared_return_type->isFalsable() && !$declared_return_type->hasBool() && !$declared_return_type->hasScalar()) { if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['InvalidFalsableReturnType'])) { self::addOrUpdateReturnType($function, $project_analyzer, $inferred_return_type, $source, ($project_analyzer->only_replace_php_types_with_non_docblock_types || $unsafe_return_type) && $inferred_return_type->from_docblock, $function_like_storage); return null; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidFalsableReturnType('The declared return type \'' . $declared_return_type . '\' for ' . $cased_method_id . ' does not allow false, but \'' . $inferred_return_type . '\' contains false', $return_type_location), $suppressed_issues, \true)) { return \false; } } } return null; } /** * @param Closure|Function_|ClassMethod|ArrowFunction $function * * @return false|null */ public static function checkReturnType(\_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $function, \Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, \Psalm\Internal\Analyzer\FunctionLikeAnalyzer $function_like_analyzer, \Psalm\Storage\FunctionLikeStorage $storage, \Psalm\Context $context) : ?bool { $codebase = $project_analyzer->getCodebase(); if (!$storage->return_type || !$storage->return_type_location) { return null; } $parent_class = null; $classlike_storage = null; if ($context->self) { $classlike_storage = $codebase->classlike_storage_provider->get($context->self); $parent_class = $classlike_storage->parent_class; } if (!$storage->signature_return_type || $storage->signature_return_type === $storage->return_type) { foreach ($storage->return_type->getAtomicTypes() as $type) { if ($type instanceof \Psalm\Type\Atomic\TNamedObject && 'parent' === $type->value && null === $parent_class) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidParent('Cannot use parent as a return type when class has no parent', $storage->return_type_location), $storage->suppressed_issues)) { return \false; } return null; } } $fleshed_out_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $storage->return_type, $classlike_storage ? $classlike_storage->name : null, $classlike_storage ? $classlike_storage->name : null, $parent_class); $fleshed_out_return_type->check($function_like_analyzer, $storage->return_type_location, $storage->suppressed_issues, [], \false); return null; } $fleshed_out_signature_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $storage->signature_return_type, $classlike_storage ? $classlike_storage->name : null, $classlike_storage ? $classlike_storage->name : null, $parent_class); if ($fleshed_out_signature_type->check($function_like_analyzer, $storage->signature_return_type_location ?: $storage->return_type_location, $storage->suppressed_issues, [], \false) === \false) { return \false; } if ($function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { return null; } $fleshed_out_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $storage->return_type, $classlike_storage ? $classlike_storage->name : null, $classlike_storage ? $classlike_storage->name : null, $parent_class, \true, \true); if ($fleshed_out_return_type->check($function_like_analyzer, $storage->return_type_location, $storage->suppressed_issues, [], \false, $storage instanceof \Psalm\Storage\MethodStorage && $storage->inherited_return_type) === \false) { return \false; } if ($classlike_storage && $context->self) { $class_template_params = \Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector::collect($codebase, $classlike_storage, $codebase->classlike_storage_provider->get($context->self), \strtolower($function->name->name), new \Psalm\Type\Atomic\TNamedObject($context->self), '$this'); $class_template_params = $class_template_params ?: []; if ($class_template_params) { $template_result = new \Psalm\Internal\Type\TemplateResult($class_template_params, []); $fleshed_out_return_type = \Psalm\Internal\Type\UnionTemplateHandler::replaceTemplateTypesWithStandins($fleshed_out_return_type, $template_result, $codebase, null, null, null); } } if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $fleshed_out_return_type, $fleshed_out_signature_type)) { if ($codebase->alter_code && isset($project_analyzer->getIssuesToFix()['MismatchingDocblockReturnType'])) { self::addOrUpdateReturnType($function, $project_analyzer, $storage->signature_return_type, $function_like_analyzer->getSource()); return null; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MismatchingDocblockReturnType('Docblock has incorrect return type \'' . $storage->return_type->getId() . '\', should be \'' . $storage->signature_return_type->getId() . '\'', $storage->return_type_location), $storage->suppressed_issues, \true)) { return \false; } } return null; } /** * @param Closure|Function_|ClassMethod|ArrowFunction $function * */ private static function addOrUpdateReturnType(\_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $function, \Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, \Psalm\Type\Union $inferred_return_type, \Psalm\StatementsSource $source, bool $docblock_only = \false, ?\Psalm\Storage\FunctionLikeStorage $function_like_storage = null) : void { $manipulator = \Psalm\Internal\FileManipulation\FunctionDocblockManipulator::getForFunction($project_analyzer, $source->getFilePath(), $function); $codebase = $project_analyzer->getCodebase(); $is_final = \true; $fqcln = $source->getFQCLN(); if ($fqcln !== null && $function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $class_storage = $codebase->classlike_storage_provider->get($fqcln); $is_final = $function->isFinal() || $class_storage->final; } $allow_native_type = !$docblock_only && $codebase->php_major_version >= 7 && ($codebase->allow_backwards_incompatible_changes || $is_final || !$function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod); $manipulator->setReturnType($allow_native_type ? (string) $inferred_return_type->toPhpString($source->getNamespace(), $source->getAliasedClassesFlipped(), $source->getFQCLN(), $codebase->php_major_version, $codebase->php_minor_version) : null, $inferred_return_type->toNamespacedString($source->getNamespace(), $source->getAliasedClassesFlipped(), $source->getFQCLN(), \false), $inferred_return_type->toNamespacedString($source->getNamespace(), $source->getAliasedClassesFlipped(), $source->getFQCLN(), \true), $inferred_return_type->canBeFullyExpressedInPhp(), $function_like_storage ? $function_like_storage->return_type_description : null); } } */ class GitInfoCollector { /** * Git command. * * @var SystemCommandExecutor */ protected $executor; /** * Constructor. */ public function __construct() { $this->executor = new \Psalm\Internal\ExecutionEnvironment\SystemCommandExecutor(); } // API /** * Collect git repository info. */ public function collect() : \Psalm\SourceControl\Git\GitInfo { $branch = $this->collectBranch(); $commit = $this->collectCommit(); $remotes = $this->collectRemotes(); return new \Psalm\SourceControl\Git\GitInfo($branch, $commit, $remotes); } /** * Collect branch name. * * @throws \RuntimeException */ protected function collectBranch() : string { $branchesResult = $this->executor->execute('git branch'); foreach ($branchesResult as $result) { if (\strpos($result, '* ') === 0) { $exploded = \explode('* ', $result, 2); return $exploded[1]; } } throw new \RuntimeException(); } /** * Collect commit info. * * @throws \RuntimeException */ protected function collectCommit() : \Psalm\SourceControl\Git\CommitInfo { $commitResult = $this->executor->execute('git log -1 --pretty=format:%H%n%aN%n%ae%n%cN%n%ce%n%s%n%at'); if (\count($commitResult) !== 7 || \array_keys($commitResult) !== \range(0, 6)) { throw new \RuntimeException(); } $commit = new \Psalm\SourceControl\Git\CommitInfo(); return $commit->setId(\trim($commitResult[0]))->setAuthorName(\trim($commitResult[1]))->setAuthorEmail(\trim($commitResult[2]))->setCommitterName(\trim($commitResult[3]))->setCommitterEmail(\trim($commitResult[4]))->setMessage($commitResult[5])->setDate((int) $commitResult[6]); } /** * Collect remotes info. * * @throws \RuntimeException * * @return list */ protected function collectRemotes() : array { $remotesResult = $this->executor->execute('git remote -v'); if (\count($remotesResult) === 0) { throw new \RuntimeException(); } // parse command result $results = []; foreach ($remotesResult as $result) { if (\strpos($result, ' ') !== \false) { [$remote] = \explode(' ', $result, 2); $results[] = $remote; } } // filter $results = \array_unique($results); // create Remote instances $remotes = []; foreach ($results as $result) { if (\strpos($result, "\t") !== \false) { [$name, $url] = \explode("\t", $result, 2); $remote = new \Psalm\SourceControl\Git\RemoteInfo(); $remotes[] = $remote->setName(\trim($name))->setUrl(\trim($url)); } } return $remotes; } } */ class BuildInfoCollector { /** * Environment variables. * * Overwritten through collection process. * * @var array */ protected $env; /** * Read environment variables. * * @var array */ protected $readEnv = []; public function __construct(array $env) { $this->env = $env; } // API /** * Collect environment variables. */ public function collect() : array { $this->readEnv = []; $this->fillTravisCi()->fillCircleCi()->fillAppVeyor()->fillJenkins()->fillScrutinizer()->fillGithubActions(); return $this->readEnv; } // internal method /** * Fill Travis CI environment variables. * * "TRAVIS", "TRAVIS_JOB_ID" must be set. * * @return $this * * @psalm-suppress PossiblyUndefinedStringArrayOffset */ protected function fillTravisCi() : self { if (isset($this->env['TRAVIS']) && $this->env['TRAVIS'] && isset($this->env['TRAVIS_JOB_ID'])) { $this->readEnv['CI_JOB_ID'] = $this->env['TRAVIS_JOB_ID']; $this->env['CI_NAME'] = 'travis-ci'; // backup $this->readEnv['TRAVIS'] = $this->env['TRAVIS']; $this->readEnv['TRAVIS_JOB_ID'] = $this->env['TRAVIS_JOB_ID']; $this->readEnv['CI_NAME'] = $this->env['CI_NAME']; $this->readEnv['TRAVIS_TAG'] = $this->env['TRAVIS_TAG'] ?? ''; $repo_slug = (string) $this->env['TRAVIS_REPO_SLUG']; if ($repo_slug) { $slug_parts = \explode('/', $repo_slug); $this->readEnv['CI_REPO_OWNER'] = $slug_parts[0]; $this->readEnv['CI_REPO_NAME'] = $slug_parts[1]; } $pr_slug = (string) ($this->env['TRAVIS_PULL_REQUEST_SLUG'] ?? ''); if ($pr_slug) { $slug_parts = \explode('/', $pr_slug); $this->readEnv['CI_PR_REPO_OWNER'] = $slug_parts[0]; $this->readEnv['CI_PR_REPO_NAME'] = $slug_parts[1]; } $this->readEnv['CI_PR_NUMBER'] = $this->env['TRAVIS_PULL_REQUEST']; $this->readEnv['CI_BRANCH'] = $this->env['TRAVIS_BRANCH']; } return $this; } /** * Fill CircleCI environment variables. * * "CIRCLECI", "CIRCLE_BUILD_NUM" must be set. * * @return $this */ protected function fillCircleCi() : self { if (isset($this->env['CIRCLECI']) && $this->env['CIRCLECI'] && isset($this->env['CIRCLE_BUILD_NUM'])) { $this->env['CI_BUILD_NUMBER'] = $this->env['CIRCLE_BUILD_NUM']; $this->env['CI_NAME'] = 'circleci'; // backup $this->readEnv['CIRCLECI'] = $this->env['CIRCLECI']; $this->readEnv['CIRCLE_BUILD_NUM'] = $this->env['CIRCLE_BUILD_NUM']; $this->readEnv['CI_NAME'] = $this->env['CI_NAME']; $this->readEnv['CI_PR_REPO_OWNER'] = $this->env['CIRCLE_PR_USERNAME'] ?? null; $this->readEnv['CI_PR_REPO_NAME'] = $this->env['CIRCLE_PR_REPONAME'] ?? null; $this->readEnv['CI_REPO_OWNER'] = $this->env['CIRCLE_PROJECT_USERNAME'] ?? null; $this->readEnv['CI_REPO_NAME'] = $this->env['CIRCLE_PROJECT_REPONAME'] ?? null; $this->readEnv['CI_PR_NUMBER'] = $this->env['CIRCLE_PR_NUMBER'] ?? null; $this->readEnv['CI_BRANCH'] = $this->env['CIRCLE_BRANCH'] ?? null; } return $this; } /** * Fill AppVeyor environment variables. * * "APPVEYOR", "APPVEYOR_BUILD_NUMBER" must be set. * * @psalm-suppress PossiblyUndefinedStringArrayOffset * * @return $this */ protected function fillAppVeyor() : self { if (isset($this->env['APPVEYOR']) && $this->env['APPVEYOR'] && isset($this->env['APPVEYOR_BUILD_NUMBER'])) { $this->readEnv['CI_BUILD_NUMBER'] = $this->env['APPVEYOR_BUILD_NUMBER']; $this->readEnv['CI_JOB_ID'] = $this->env['APPVEYOR_JOB_NUMBER']; $this->readEnv['CI_BRANCH'] = $this->env['APPVEYOR_REPO_BRANCH']; $this->readEnv['CI_PR_NUMBER'] = $this->env['APPVEYOR_PULL_REQUEST_NUMBER'] ?? ''; $this->env['CI_NAME'] = 'AppVeyor'; // backup $this->readEnv['APPVEYOR'] = $this->env['APPVEYOR']; $this->readEnv['APPVEYOR_BUILD_NUMBER'] = $this->env['APPVEYOR_BUILD_NUMBER']; $this->readEnv['APPVEYOR_JOB_NUMBER'] = $this->env['APPVEYOR_JOB_NUMBER']; $this->readEnv['APPVEYOR_REPO_BRANCH'] = $this->env['APPVEYOR_REPO_BRANCH']; $this->readEnv['CI_NAME'] = $this->env['CI_NAME']; $repo_slug = (string) ($this->env['APPVEYOR_REPO_NAME'] ?? ''); if ($repo_slug) { $slug_parts = \explode('/', $repo_slug); $this->readEnv['CI_REPO_OWNER'] = $slug_parts[0]; $this->readEnv['CI_REPO_NAME'] = $slug_parts[1]; } $pr_slug = (string) ($this->env['APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME'] ?? ''); if ($pr_slug) { $slug_parts = \explode('/', $pr_slug); $this->readEnv['CI_PR_REPO_OWNER'] = $slug_parts[0]; $this->readEnv['CI_PR_REPO_NAME'] = $slug_parts[1]; } $this->readEnv['CI_BRANCH'] = $this->env['APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH'] ?? $this->env['APPVEYOR_REPO_BRANCH']; } return $this; } /** * Fill Jenkins environment variables. * * "JENKINS_URL", "BUILD_NUMBER" must be set. * * @return $this */ protected function fillJenkins() : self { if (isset($this->env['JENKINS_URL']) && isset($this->env['BUILD_NUMBER'])) { $this->readEnv['CI_BUILD_NUMBER'] = $this->env['BUILD_NUMBER']; $this->readEnv['CI_BUILD_URL'] = $this->env['JENKINS_URL']; $this->env['CI_NAME'] = 'jenkins'; // backup $this->readEnv['BUILD_NUMBER'] = $this->env['BUILD_NUMBER']; $this->readEnv['JENKINS_URL'] = $this->env['JENKINS_URL']; $this->readEnv['CI_NAME'] = $this->env['CI_NAME']; } return $this; } /** * Fill Scrutinizer environment variables. * * "JENKINS_URL", "BUILD_NUMBER" must be set. * * @psalm-suppress PossiblyUndefinedStringArrayOffset * * @return $this */ protected function fillScrutinizer() : self { if (isset($this->env['SCRUTINIZER']) && $this->env['SCRUTINIZER']) { $this->readEnv['CI_JOB_ID'] = $this->env['SCRUTINIZER_INSPECTION_UUID']; $this->readEnv['CI_BRANCH'] = $this->env['SCRUTINIZER_BRANCH']; $this->readEnv['CI_PR_NUMBER'] = $this->env['SCRUTINIZER_PR_NUMBER'] ?? ''; // backup $this->readEnv['CI_NAME'] = 'Scrutinizer'; $repo_slug = (string) ($this->env['SCRUTINIZER_PROJECT'] ?? ''); if ($repo_slug) { $slug_parts = \explode('/', $repo_slug); if ($this->readEnv['CI_PR_NUMBER']) { $this->readEnv['CI_PR_REPO_OWNER'] = $slug_parts[1]; $this->readEnv['CI_PR_REPO_NAME'] = $slug_parts[2]; } else { $this->readEnv['CI_REPO_OWNER'] = $slug_parts[1]; $this->readEnv['CI_REPO_NAME'] = $slug_parts[2]; } } } return $this; } /** * Fill Github Actions environment variables. * * @return $this * @psalm-suppress PossiblyUndefinedStringArrayOffset */ protected function fillGithubActions() : \Psalm\Internal\ExecutionEnvironment\BuildInfoCollector { if (isset($this->env['GITHUB_ACTIONS'])) { $this->env['CI_NAME'] = 'github-actions'; $this->env['CI_JOB_ID'] = $this->env['GITHUB_ACTIONS']; $githubRef = (string) $this->env['GITHUB_REF']; if (\strpos($githubRef, 'refs/heads/') !== \false) { $githubRef = \str_replace('refs/heads/', '', $githubRef); } elseif (\strpos($githubRef, 'refs/tags/') !== \false) { $githubRef = \str_replace('refs/tags/', '', $githubRef); } $this->env['CI_BRANCH'] = $githubRef; $this->readEnv['GITHUB_ACTIONS'] = $this->env['GITHUB_ACTIONS']; $this->readEnv['GITHUB_REF'] = $this->env['GITHUB_REF']; $this->readEnv['CI_NAME'] = $this->env['CI_NAME']; $this->readEnv['CI_BRANCH'] = $this->env['CI_BRANCH']; $slug_parts = \explode('/', (string) $this->env['GITHUB_REPOSITORY']); $this->readEnv['CI_REPO_OWNER'] = $slug_parts[0]; $this->readEnv['CI_REPO_NAME'] = $slug_parts[1]; if (isset($this->env['GITHUB_EVENT_PATH'])) { $event_json = \file_get_contents((string) $this->env['GITHUB_EVENT_PATH']); /** @var array */ $event_data = \json_decode($event_json, \true); if (isset($event_data['head_commit'])) { /** * @var array{ * id: string, * author: array{name: string, email: string}, * committer: array{name: string, email: string}, * message: string, * timestamp: string * } */ $head_commit_data = $event_data['head_commit']; $gitinfo = new \Psalm\SourceControl\Git\GitInfo($githubRef, (new \Psalm\SourceControl\Git\CommitInfo())->setId($head_commit_data['id'])->setAuthorName($head_commit_data['author']['name'])->setAuthorEmail($head_commit_data['author']['email'])->setCommitterName($head_commit_data['committer']['name'])->setCommitterEmail($head_commit_data['committer']['email'])->setMessage($head_commit_data['message'])->setDate(\strtotime($head_commit_data['timestamp'])), []); $this->readEnv['git'] = $gitinfo->toArray(); } if ($this->env['GITHUB_EVENT_PATH'] === 'pull_request') { $this->readEnv['CI_PR_NUMBER'] = $event_data['number']; } } } return $this; } } * @author Dariusz Rumiński * * @internal */ final class SystemCommandExecutor { /** * Execute command. * * * @throws \RuntimeException * * @return string[] */ public function execute(string $command) : array { \exec($command, $result, $returnValue); if ($returnValue === 0) { /** @var string[] */ return $result; } throw new \RuntimeException(\sprintf('Failed to execute command: %s', $command), $returnValue); } } [pluginClass => packageName] */ private $all_plugins = null; /** @var ?array [pluginClass => ?packageName] */ private $enabled_plugins = null; public function __construct(\Psalm\Internal\PluginManager\ConfigFile $config_file, \Psalm\Internal\PluginManager\ComposerLock $composer_lock) { $this->config_file = $config_file; $this->composer_lock = $composer_lock; } /** * @return array [pluginClass => ?packageName, ...] */ public function getEnabled() : array { if (!$this->enabled_plugins) { $this->enabled_plugins = []; foreach ($this->config_file->getConfig()->getPluginClasses() as $plugin_entry) { $plugin_class = $plugin_entry['class']; $this->enabled_plugins[$plugin_class] = $this->findPluginPackage($plugin_class); } } return $this->enabled_plugins; } /** * @return array [pluginCLass => ?packageName] */ public function getAvailable() : array { return \array_diff_key($this->getAll(), $this->getEnabled()); } /** * @return array [pluginClass => packageName] */ public function getAll() : array { if (null === $this->all_plugins) { $this->all_plugins = \array_flip($this->composer_lock->getPlugins()); } return $this->all_plugins; } public function resolvePluginClass(string $class_or_package) : string { if (\false === \strpos($class_or_package, '/')) { return $class_or_package; // must be a class then } // pluginClass => ?pluginPackage $plugin_classes = $this->getAll(); $class = \array_search($class_or_package, $plugin_classes, \true); if (\false === $class) { throw new \InvalidArgumentException('Unknown plugin: ' . $class_or_package); } return $class; } public function findPluginPackage(string $class) : ?string { // pluginClass => ?pluginPackage $plugin_classes = $this->getAll(); return $plugin_classes[$class] ?? null; } public function isEnabled(string $class) : bool { return \array_key_exists($class, $this->getEnabled()); } public function enable(string $class) : void { $this->config_file->addPlugin($class); } public function disable(string $class) : void { $this->config_file->removePlugin($class); } } current_dir = $current_dir; if ($explicit_path) { $this->path = $explicit_path; } else { $path = \Psalm\Config::locateConfigFile($current_dir); if (!$path) { throw new \RuntimeException('Cannot find Psalm config'); } $this->path = $path; } } public function getConfig() : \Psalm\Config { return \Psalm\Config::loadFromXMLFile($this->path, $this->current_dir); } public function removePlugin(string $plugin_class) : void { $config_xml = $this->readXml(); /** @var \DomElement */ $psalm_root = $config_xml->getElementsByTagName('psalm')[0]; $plugins_elements = $psalm_root->getElementsByTagName('plugins'); if (!$plugins_elements->length) { // no plugins, nothing to remove return; } /** @var \DomElement */ $plugins_element = $plugins_elements->item(0); $plugin_elements = $plugins_element->getElementsByTagName('pluginClass'); foreach ($plugin_elements as $plugin_element) { if ($plugin_element->getAttribute('class') === $plugin_class) { $plugins_element->removeChild($plugin_element); break; } } if (!$plugin_elements->length) { // avoid breaking old psalm binaries, whose schema did not allow empty plugins $psalm_root->removeChild($plugins_element); } $this->saveXml($config_xml); } public function addPlugin(string $plugin_class) : void { $config_xml = $this->readXml(); /** @var \DomElement */ $psalm_root = $config_xml->getElementsByTagName('psalm')->item(0); $plugins_elements = $psalm_root->getElementsByTagName('plugins'); if (!$plugins_elements->length) { $plugins_element = $config_xml->createElement('plugins'); if ($plugins_element) { $psalm_root->appendChild($plugins_element); } } else { /** @var \DomElement */ $plugins_element = $plugins_elements->item(0); } $plugin_class_element = $config_xml->createElement('pluginClass'); if ($plugin_class_element) { $plugin_class_element->setAttribute('xmlns', self::NS); $plugin_class_element->setAttribute('class', $plugin_class); if ($plugins_element) { $plugins_element->appendChild($plugin_class_element); } } $this->saveXml($config_xml); } private function readXml() : \DOMDocument { $doc = new \DOMDocument(); $file_contents = \file_get_contents($this->path); if (($tag_start = \strpos($file_contents, '', $tag_start + 1); if ($tag_end !== \false) { $this->psalm_tag_end_pos = $tag_end; $this->psalm_header = \substr($file_contents, 0, $tag_end); } } $doc->loadXML($file_contents); return $doc; } private function saveXml(\DOMDocument $config_xml) : void { $new_file_contents = $config_xml->saveXML($config_xml); if (($tag_start = \strpos($new_file_contents, '', $tag_start + 1); if ($tag_end !== \false && $new_file_contents[$tag_end - 1] !== '/' && $this->psalm_tag_end_pos && $this->psalm_header) { $new_file_contents = $this->psalm_header . \substr($new_file_contents, $tag_end); } } \file_put_contents($this->path, $new_file_contents); } } file_names = $file_names; } /** * @param mixed $package * * @psalm-assert-if-true array $package * * @psalm-pure */ public function isPlugin($package) : bool { return \is_array($package) && isset($package['name']) && \is_string($package['name']) && isset($package['type']) && $package['type'] === 'psalm-plugin' && isset($package['extra']['psalm']['pluginClass']) && \is_array($package['extra']) && \is_array($package['extra']['psalm']) && \is_string($package['extra']['psalm']['pluginClass']); } /** * @return array [packageName => pluginClass, ...] */ public function getPlugins() : array { $pluginPackages = $this->getAllPluginPackages(); $ret = []; foreach ($pluginPackages as $package) { $ret[$package['name']] = $package['extra']['psalm']['pluginClass']; } return $ret; } private function read(string $file_name) : array { /** @psalm-suppress MixedAssignment */ $contents = \json_decode(\file_get_contents($file_name), \true); if ($error = \json_last_error()) { throw new \RuntimeException(\json_last_error_msg(), $error); } if (!\is_array($contents)) { throw new \RuntimeException('Malformed ' . $file_name . ', expecting JSON-encoded object'); } return $contents; } /** * @return list */ private function getAllPluginPackages() : array { $packages = $this->getAllPackages(); $ret = []; /** @psalm-suppress MixedAssignment */ foreach ($packages as $package) { if ($this->isPlugin($package)) { /** @var array{type:'psalm-plugin',name:string,extra:array{psalm:array{pluginClass:string}}} */ $ret[] = $package; } } return $ret; } private function getAllPackages() : array { $packages = []; foreach ($this->file_names as $file_name) { $composer_lock_contents = $this->read($file_name); if (!isset($composer_lock_contents['packages']) || !\is_array($composer_lock_contents['packages'])) { throw new \RuntimeException('packages section is missing or not an array'); } if (!isset($composer_lock_contents['packages-dev']) || !\is_array($composer_lock_contents['packages-dev'])) { throw new \RuntimeException('packages-dev section is missing or not an array'); } $packages = \array_merge($packages, \array_merge($composer_lock_contents['packages'], $composer_lock_contents['packages-dev'])); } return $packages; } } plugin_list_factory = $plugin_list_factory; parent::__construct(); } protected function configure() : void { $this->setName('enable')->setDescription('Enables a named plugin')->addArgument('pluginName', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument::REQUIRED, 'Plugin name (fully qualified class name or composer package name)')->addUsage('vendor/plugin-package-name [-c path/to/psalm.xml]'); $this->addUsage('\'Plugin\\Class\\Name\' [-c path/to/psalm.xml]'); } protected function execute(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) : int { $io = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Style\SymfonyStyle($input, $output); $current_dir = (string) \getcwd() . \DIRECTORY_SEPARATOR; $config_file_path = $input->getOption('config'); if ($config_file_path !== null && !\is_string($config_file_path)) { throw new \UnexpectedValueException('Config file path should be a string'); } $plugin_list = ($this->plugin_list_factory)($current_dir, $config_file_path); $plugin_name = $input->getArgument('pluginName'); \assert(\is_string($plugin_name)); try { $plugin_class = $plugin_list->resolvePluginClass($plugin_name); } catch (\InvalidArgumentException $e) { $io->error('Unknown plugin class ' . $plugin_name); return 2; } if ($plugin_list->isEnabled($plugin_class)) { $io->note('Plugin already enabled'); return 3; } $plugin_list->enable($plugin_class); $io->success('Plugin enabled'); return 0; } } plugin_list_factory = $plugin_list_factory; parent::__construct(); } protected function configure() : void { $this->setName('disable')->setDescription('Disables a named plugin')->addArgument('pluginName', \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputArgument::REQUIRED, 'Plugin name (fully qualified class name or composer package name)')->addUsage('vendor/plugin-package-name [-c path/to/psalm.xml]'); $this->addUsage('\'Plugin\\Class\\Name\' [-c path/to/psalm.xml]'); } protected function execute(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) : int { $io = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Style\SymfonyStyle($input, $output); $current_dir = (string) \getcwd() . \DIRECTORY_SEPARATOR; $config_file_path = $input->getOption('config'); if ($config_file_path !== null && !\is_string($config_file_path)) { throw new \UnexpectedValueException('Config file path should be a string'); } $plugin_list = ($this->plugin_list_factory)($current_dir, $config_file_path); $plugin_name = $input->getArgument('pluginName'); \assert(\is_string($plugin_name)); try { $plugin_class = $plugin_list->resolvePluginClass($plugin_name); } catch (\InvalidArgumentException $e) { $io->error('Unknown plugin class ' . $plugin_name); return 2; } if (!$plugin_list->isEnabled($plugin_class)) { $io->note('Plugin already disabled'); return 3; } $plugin_list->disable($plugin_class); $io->success('Plugin disabled'); return 0; } } plugin_list_factory = $plugin_list_factory; parent::__construct(); } protected function configure() : void { $this->setName('show')->setDescription('Lists enabled and available plugins')->addUsage('[-c path/to/psalm.xml]'); } protected function execute(\_HumbugBoxd02f763d3c56\Symfony\Component\Console\Input\InputInterface $input, \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Output\OutputInterface $output) : int { $io = new \_HumbugBoxd02f763d3c56\Symfony\Component\Console\Style\SymfonyStyle($input, $output); $current_dir = (string) \getcwd() . \DIRECTORY_SEPARATOR; $config_file_path = $input->getOption('config'); if ($config_file_path !== null && !\is_string($config_file_path)) { throw new \UnexpectedValueException('Config file path should be a string'); } $plugin_list = ($this->plugin_list_factory)($current_dir, $config_file_path); $enabled = $plugin_list->getEnabled(); $available = $plugin_list->getAvailable(); $formatRow = function (string $class, ?string $package) : array { return [$package, $class]; }; $io->section('Enabled'); if (\count($enabled)) { $io->table(['Package', 'Class'], \array_map($formatRow, \array_keys($enabled), \array_values($enabled))); } else { $io->note('No plugins enabled'); } $io->section('Available'); if (\count($available)) { $io->table(['Package', 'Class'], \array_map($formatRow, \array_keys($available), \array_values($available))); } else { $io->note('No plugins available'); } return 0; } } project_root = $project_root; $this->psalm_root = $psalm_root; } public function __invoke(string $current_dir, ?string $config_file_path = null) : \Psalm\Internal\PluginManager\PluginList { $config_file = new \Psalm\Internal\PluginManager\ConfigFile($current_dir, $config_file_path); $composer_lock = new \Psalm\Internal\PluginManager\ComposerLock($this->findLockFiles()); return new \Psalm\Internal\PluginManager\PluginList($config_file, $composer_lock); } /** @return non-empty-array */ private function findLockFiles() : array { // use cases // 1. plugins are installed into project vendors - composer.lock is PROJECT_ROOT/composer.lock // 2. plugins are installed into separate composer environment (either global or bamarni-bin) // - composer.lock is PSALM_ROOT/../../../composer.lock // 3. plugins are installed into psalm vendors - composer.lock is PSALM_ROOT/composer.lock // 4. none of the above - use stub (empty virtual composer.lock) if ($this->psalm_root === $this->project_root) { // managing plugins for psalm itself $composer_lock_filenames = [\Psalm\Internal\Composer::getLockFilePath(\rtrim($this->psalm_root, \DIRECTORY_SEPARATOR))]; } else { $composer_lock_filenames = [\Psalm\Internal\Composer::getLockFilePath(\rtrim($this->project_root, \DIRECTORY_SEPARATOR)), \Psalm\Internal\Composer::getLockFilePath(\rtrim($this->psalm_root, \DIRECTORY_SEPARATOR) . '/../../..'), \Psalm\Internal\Composer::getLockFilePath(\rtrim($this->psalm_root, \DIRECTORY_SEPARATOR))]; } $composer_lock_filenames = \array_filter($composer_lock_filenames, 'is_readable'); if (empty($composer_lock_filenames)) { $stub_composer_lock = (object) ['packages' => [], 'packages-dev' => []]; $composer_lock_filenames[] = 'data:application/json,' . \urlencode(\json_encode($stub_composer_lock)); } return $composer_lock_filenames; } } file_offset = $offset; $this->line_offset = $line_offset; } /** * @return null|int */ public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { /** @var array{startFilePos: int, endFilePos: int, startLine: int} */ $attrs = $node->getAttributes(); if ($cs = $node->getComments()) { $new_comments = []; foreach ($cs as $c) { if ($c instanceof \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc) { $new_comments[] = new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc($c->getText(), $c->getStartLine() + $this->line_offset, $c->getStartFilePos() + $this->file_offset); } else { $new_comments[] = new \_HumbugBoxd02f763d3c56\PhpParser\Comment($c->getText(), $c->getStartLine() + $this->line_offset, $c->getStartFilePos() + $this->file_offset); } } $node->setAttribute('comments', $new_comments); } /** * @psalm-suppress MixedOperand */ $node->setAttribute('startFilePos', $attrs['startFilePos'] + $this->file_offset); /** @psalm-suppress MixedOperand */ $node->setAttribute('endFilePos', $attrs['endFilePos'] + $this->file_offset); /** @psalm-suppress MixedOperand */ $node->setAttribute('startLine', $attrs['startLine'] + $this->line_offset); } } type_provider = $old_type_provider; } /** * @return Node\Expr */ public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : \_HumbugBoxd02f763d3c56\PhpParser\Node { /** @var \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node */ $origNode = $node; $node = clone $node; $node_type = $this->type_provider->getType($origNode); if ($node_type) { $this->type_provider->setType($node, clone $node_type); } return $node; } } */ private $replacements = []; /** @var bool */ private $new_name_replaced = \false; /** @var bool */ private $new_new_name_used = \false; public function __construct(string $old_name, string $new_name) { $this->old_name = $old_name; $this->new_name = $new_name; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : ?int { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { if ($node->name === $this->old_name) { $this->replacements[] = new \Psalm\FileManipulation((int) $node->getAttribute('startFilePos') + 1, (int) $node->getAttribute('endFilePos') + 1, $this->new_name); } elseif ($node->name === $this->new_name) { if ($this->new_new_name_used) { $this->replacements = []; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } $this->replacements[] = new \Psalm\FileManipulation((int) $node->getAttribute('startFilePos') + 1, (int) $node->getAttribute('endFilePos') + 1, $this->new_name . '_new'); $this->new_name_replaced = \true; } elseif ($node->name === $this->new_name . '_new') { if ($this->new_name_replaced) { $this->replacements = []; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } $this->new_new_name_used = \true; } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && ($docblock = $node->getDocComment())) { $parsed_docblock = \Psalm\Internal\Scanner\DocblockParser::parse($docblock->getText()); $replaced = \false; foreach ($parsed_docblock->tags as $tag_name => $tags) { foreach ($tags as $i => $tag) { if ($tag_name === 'param' || $tag_name === 'psalm-param' || $tag_name === 'phpstan-param' || $tag_name === 'phan-param') { $parts = \Psalm\Internal\Analyzer\CommentAnalyzer::splitDocLine($tag); if (($parts[1] ?? '') === '$' . $this->old_name) { $parsed_docblock->tags[$tag_name][$i] = \str_replace('$' . $this->old_name, '$' . $this->new_name, $tag); $replaced = \true; } } } } if ($replaced) { $this->replacements[] = new \Psalm\FileManipulation($docblock->getStartFilePos(), $docblock->getStartFilePos() + \strlen($docblock->getText()), \rtrim($parsed_docblock->render($parsed_docblock->first_line_padding)), \false, \false); } } return null; } /** * @return list */ public function getReplacements() : array { return $this->replacements; } } */ protected $non_trivial_expr = []; private function checkNonTrivialExpr(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $node) : bool { /** * @psalm-suppress UndefinedClass * @psalm-suppress TypeDoesNotContainType */ if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClosureUse || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Eval_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Exit_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ShellExec || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\String_) { if (($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\MethodCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall) && isset($node->pure)) { return \false; } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ && isset($node->external_mutation_free)) { return \false; } return \true; } else { return \false; } } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : ?int { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { // Check for Non-Trivial Expression first if ($this->checkNonTrivialExpr($node)) { $this->non_trivial_expr[] = $node; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch) { return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } } return null; } /** * @return array */ public function getNonTrivialExpr() : array { return $this->non_trivial_expr; } } */ protected $used_variables = []; public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : ?int { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($node->name)) { $this->used_variables['$' . $node->name] = \true; } return null; } /** * @return array */ public function getUsedVariables() : array { return $this->used_variables; } } type_provider = $type_provider; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : ?int { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr) { $this->type_provider->clearNodeOfTypeAndAssertions($node); } return null; } } count++; } } $offset_map */ public function __construct(\_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler $errorHandler, ?array $offset_map = null) { if ($offset_map) { foreach ($offset_map as [, , $b_s, $b_e]) { if ($this->start_change === null) { $this->start_change = $b_s; } $this->end_change = $b_e; } } $this->nameContext = new \_HumbugBoxd02f763d3c56\PhpParser\NameContext($errorHandler); } public function beforeTraverse(array $nodes) : ?array { $this->nameContext->startNamespace(); return null; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : ?int { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { $this->nameContext->startNamespace($node->name); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type, null); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type, $node->prefix); } } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && $this->start_change && $this->end_change) { /** @var array{startFilePos: int, endFilePos: int} */ $attrs = $node->getAttributes(); if ($cs = $node->getComments()) { $attrs['startFilePos'] = $cs[0]->getStartFilePos(); } if ($attrs['endFilePos'] < $this->start_change || $attrs['startFilePos'] > $this->end_change) { return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN; } } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure) { $this->resolveSignature($node); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_) { if ($node->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $node->class = $this->resolveClassName($node->class); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Catch_) { foreach ($node->types as &$type) { $type = $this->resolveClassName($type); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { if ($node->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $node->name = $this->resolveName($node->name, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { $node->name = $this->resolveName($node->name, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_) { $this->resolveTrait($node); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { foreach ($node->traits as &$trait) { $trait = $this->resolveClassName($trait); } foreach ($node->adaptations as $adaptation) { if (null !== $adaptation->trait) { $adaptation->trait = $this->resolveClassName($adaptation->trait); } if ($adaptation instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Precedence) { foreach ($adaptation->insteadof as &$insteadof) { $insteadof = $this->resolveClassName($insteadof); } } } } return null; } private function addAlias(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\UseUse $use, int $type, ?\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $prefix = null) : void { // Add prefix for group uses /** @var Name $name */ $name = $prefix ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Name::concat($prefix, $use->name) : $use->name; // Type is determined either by individual element or whole use declaration $type |= $use->type; $this->nameContext->addAlias($name, (string) $use->getAlias(), $type, $use->getAttributes()); } /** * @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ private function resolveSignature(\_HumbugBoxd02f763d3c56\PhpParser\NodeAbstract $node) : void { foreach ($node->params as $param) { $param->type = $this->resolveType($param->type); } $node->returnType = $this->resolveType($node->returnType); } /** * @param PhpParser\Node|string|null $node * * @return null|PhpParser\Node\Identifier|PhpParser\Node\Name|PhpParser\Node\NullableType * @psalm-suppress InvalidReturnType * @psalm-suppress InvalidReturnStatement */ private function resolveType($node) : ?\_HumbugBoxd02f763d3c56\PhpParser\Node { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType) { /** @psalm-suppress PossiblyInvalidPropertyAssignmentValue */ $node->type = $this->resolveType($node->type); return $node; } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { return $this->resolveClassName($node); } return $node; } /** * Resolve name, according to name resolver options. * * @param Name $name Function or constant name to resolve * @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_* * * @return Name Resolved name, or original name with attribute */ protected function resolveName(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $name, int $type) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Name { $resolvedName = $this->nameContext->getResolvedName($name, $type); if (null !== $resolvedName) { $name->setAttribute('resolvedName', $resolvedName->toString()); } return $name; } protected function resolveClassName(\_HumbugBoxd02f763d3c56\PhpParser\Node\Name $name) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Name { return $this->resolveName($name, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL); } protected function resolveTrait(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_ $node) : void { $resolvedName = \_HumbugBoxd02f763d3c56\PhpParser\Node\Name::concat($this->nameContext->getNamespace(), (string) $node->name); if (null !== $resolvedName) { $node->setAttribute('resolvedName', $resolvedName->toString()); } } } > */ private $class_template_types = []; /** @var array> */ private $function_template_types = []; /** @var FunctionLikeStorage[] */ private $functionlike_storages = []; /** @var FileStorage */ private $file_storage; /** @var ClassLikeStorage[] */ private $classlike_storages = []; /** @var class-string<\Psalm\Plugin\Hook\AfterClassLikeVisitInterface>[] */ private $after_classlike_check_plugins; /** @var int */ private $php_major_version; /** @var int */ private $php_minor_version; /** @var PhpParser\Node\Name|null */ private $namespace_name; /** @var PhpParser\Node\Expr|null */ private $exists_cond_expr; /** * @var ?int */ private $skip_if_descendants = null; /** * @var array */ private $type_aliases = []; /** * @var array */ private $classlike_type_aliases = []; /** * @var array */ private $bad_classes = []; public function __construct(\Psalm\Codebase $codebase, \Psalm\Storage\FileStorage $file_storage, \Psalm\Internal\Scanner\FileScanner $file_scanner) { $this->codebase = $codebase; $this->file_scanner = $file_scanner; $this->file_path = $file_scanner->file_path; $this->scan_deep = $file_scanner->will_analyze; $this->config = $codebase->config; $this->file_storage = $file_storage; $this->aliases = $this->file_storage->aliases = new \Psalm\Aliases(); $this->after_classlike_check_plugins = $this->config->after_visit_classlikes; $this->php_major_version = $codebase->php_major_version; $this->php_minor_version = $codebase->php_minor_version; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : ?int { foreach ($node->getComments() as $comment) { if ($comment instanceof \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc && !$node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike) { $self_fqcln = $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike && $node->name !== null ? ($this->aliases->namespace ? $this->aliases->namespace . '\\' : '') . $node->name->name : null; try { $type_aliases = \Psalm\Internal\Analyzer\CommentAnalyzer::getTypeAliasesFromComment($comment, $this->aliases, $this->type_aliases, $self_fqcln); foreach ($type_aliases as $type_alias) { // finds issues, if there are any \Psalm\Internal\Type\TypeParser::parseTokens($type_alias->replacement_tokens); } $this->type_aliases += $type_aliases; } catch (\Psalm\Exception\DocblockParseException $e) { $this->file_storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); } catch (\Psalm\Exception\TypeParseTreeException $e) { $this->file_storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); } } } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { $this->file_storage->aliases = $this->aliases; $this->namespace_name = $node->name; $this->aliases = new \Psalm\Aliases($node->name ? \implode('\\', $node->name->parts) : '', $this->aliases->uses, $this->aliases->functions, $this->aliases->constants, $this->aliases->uses_flipped, $this->aliases->functions_flipped, $this->aliases->constants_flipped); $this->file_storage->namespace_aliases[(int) $node->getAttribute('startFilePos')] = $this->aliases; if ($node->stmts) { $this->aliases->namespace_first_stmt_start = (int) $node->stmts[0]->getAttribute('startFilePos'); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_) { foreach ($node->uses as $use) { $use_path = \implode('\\', $use->name->parts); $use_alias = $use->alias ? $use->alias->name : $use->name->getLast(); switch ($use->type !== \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $node->type) { case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION: $this->aliases->functions[\strtolower($use_alias)] = $use_path; $this->aliases->functions_flipped[\strtolower($use_path)] = $use_alias; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT: $this->aliases->constants[$use_alias] = $use_path; $this->aliases->constants_flipped[$use_path] = $use_alias; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL: $this->aliases->uses[\strtolower($use_alias)] = $use_path; $this->aliases->uses_flipped[\strtolower($use_path)] = $use_alias; break; } } if (!$this->aliases->uses_start) { $this->aliases->uses_start = (int) $node->getAttribute('startFilePos'); } $this->aliases->uses_end = (int) $node->getAttribute('endFilePos') + 1; } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\GroupUse) { $use_prefix = \implode('\\', $node->prefix->parts); foreach ($node->uses as $use) { $use_path = $use_prefix . '\\' . \implode('\\', $use->name->parts); $use_alias = $use->alias ? $use->alias->name : $use->name->getLast(); switch ($use->type !== \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $node->type) { case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_FUNCTION: $this->aliases->functions[\strtolower($use_alias)] = $use_path; $this->aliases->functions_flipped[\strtolower($use_path)] = $use_alias; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_CONSTANT: $this->aliases->constants[$use_alias] = $use_path; $this->aliases->constants_flipped[$use_path] = $use_alias; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Use_::TYPE_NORMAL: $this->aliases->uses[\strtolower($use_alias)] = $use_path; $this->aliases->uses_flipped[\strtolower($use_path)] = $use_alias; break; } } if (!$this->aliases->uses_start) { $this->aliases->uses_start = (int) $node->getAttribute('startFilePos'); } $this->aliases->uses_end = (int) $node->getAttribute('endFilePos') + 1; } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike) { if ($this->skip_if_descendants) { return null; } if ($this->registerClassLike($node) === \false) { $this->bad_classes[\spl_object_id($node)] = \true; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN; } } elseif (($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\New_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Instanceof_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticPropertyFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\StaticCall) && $node->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $fq_classlike_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($node->class, $this->aliases); if (!\in_array(\strtolower($fq_classlike_name), ['self', 'static', 'parent'], \true)) { $this->codebase->scanner->queueClassLikeForScanning($fq_classlike_name, \false, !$node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch || !$node->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier || \strtolower($node->name->name) !== 'class'); $this->file_storage->referenced_classlikes[\strtolower($fq_classlike_name)] = $fq_classlike_name; } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TryCatch) { foreach ($node->catches as $catch) { foreach ($catch->types as $catch_type) { $catch_fqcln = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($catch_type, $this->aliases); if (!\in_array(\strtolower($catch_fqcln), ['self', 'static', 'parent'], \true)) { $this->codebase->scanner->queueClassLikeForScanning($catch_fqcln); $this->file_storage->referenced_classlikes[\strtolower($catch_fqcln)] = $catch_fqcln; } } } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { if ($this->skip_if_descendants) { return null; } } $this->registerFunctionLike($node); if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { $this->codebase->scanner->queueClassLikeForScanning('Closure'); } if (!$this->scan_deep) { return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN; } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Global_) { $function_like_storage = \end($this->functionlike_storages); if ($function_like_storage) { foreach ($node->vars as $var) { if ($var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { if (\is_string($var->name) && $var->name !== 'argv' && $var->name !== 'argc') { $var_id = '$' . $var->name; $function_like_storage->global_variables[$var_id] = \true; } } } } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $node->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $function_id = \implode('\\', $node->name->parts); if (\Psalm\Internal\Codebase\InternalCallMapHandler::inCallMap($function_id)) { $this->registerClassMapFunctionCall($function_id, $node); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse) { if ($this->skip_if_descendants) { return null; } if (!$this->classlike_storages) { throw new \LogicException('$this->classlike_storages should not be empty'); } $storage = $this->classlike_storages[\count($this->classlike_storages) - 1]; $method_map = $storage->trait_alias_map ?: []; $visibility_map = $storage->trait_visibility_map ?: []; $final_map = $storage->trait_final_map ?: []; foreach ($node->adaptations as $adaptation) { if ($adaptation instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUseAdaptation\Alias) { $old_name = \strtolower($adaptation->method->name); $new_name = $old_name; if ($adaptation->newName) { $new_name = \strtolower($adaptation->newName->name); if ($new_name !== $old_name) { $method_map[$new_name] = $old_name; } } if ($adaptation->newModifier) { switch ($adaptation->newModifier) { case 1: $visibility_map[$new_name] = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; break; case 2: $visibility_map[$new_name] = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED; break; case 4: $visibility_map[$new_name] = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE; break; case 32: $final_map[$new_name] = \true; break; } } } } $storage->trait_alias_map = $method_map; $storage->trait_visibility_map = $visibility_map; $storage->trait_final_map = $final_map; foreach ($node->traits as $trait) { $trait_fqcln = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($trait, $this->aliases); $this->codebase->scanner->queueClassLikeForScanning($trait_fqcln, $this->scan_deep); $storage->used_traits[\strtolower($trait_fqcln)] = $trait_fqcln; $this->file_storage->required_classes[\strtolower($trait_fqcln)] = $trait_fqcln; } if ($node_comment = $node->getDocComment()) { $comments = \Psalm\DocComment::parsePreservingLength($node_comment); if (isset($comments->combined_tags['use'])) { foreach ($comments->combined_tags['use'] as $template_line) { $this->useTemplatedType($storage, $node, \trim(\preg_replace('@^[ \\t]*\\*@m', '', $template_line))); } } if (isset($comments->tags['template-extends']) || isset($comments->tags['extends']) || isset($comments->tags['template-implements']) || isset($comments->tags['implements'])) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('You must use @use or @template-use to parameterize traits', new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); } } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_) { $this->visitInclude($node); } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\For_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Foreach_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\While_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Do_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Echo_) { if ($doc_comment = $node->getDocComment()) { $var_comments = []; try { $var_comments = \Psalm\Internal\Analyzer\CommentAnalyzer::getTypeFromComment($doc_comment, $this->file_scanner, $this->aliases, null, $this->type_aliases); } catch (\Psalm\Exception\DocblockParseException $e) { // do nothing } foreach ($var_comments as $var_comment) { if (!$var_comment->type) { continue; } $var_type = $var_comment->type; $var_type->queueClassLikesForScanning($this->codebase, $this->file_storage); } } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignRef) { if ($node->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && $node->var->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $node->var->var->name === 'this' && $node->var->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $functionlike_storage = \end($this->functionlike_storages); if ($functionlike_storage instanceof \Psalm\Storage\MethodStorage) { $functionlike_storage->this_property_mutations[$node->var->name->name] = \true; } } } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_) { foreach ($node->consts as $const) { $const_type = \Psalm\Internal\Analyzer\Statements\Expression\SimpleTypeInferer::infer($this->codebase, new \Psalm\Internal\Provider\NodeDataProvider(), $const->value, $this->aliases) ?: \Psalm\Type::getMixed(); $fq_const_name = \Psalm\Type::getFQCLNFromString($const->name->name, $this->aliases); if ($this->codebase->register_stub_files || $this->codebase->register_autoload_files) { $this->codebase->addGlobalConstantType($fq_const_name, $const_type); } $this->file_storage->constants[$fq_const_name] = $const_type; $this->file_storage->declaring_constants[$fq_const_name] = $this->file_path; } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_ && !$this->skip_if_descendants) { if (!$this->fq_classlike_names && !$this->functionlike_storages) { $this->exists_cond_expr = $node->cond; if ($this->enterConditional($this->exists_cond_expr) === \false) { // the else node should terminate the agreement $this->skip_if_descendants = $node->else ? $node->else->getLine() : $node->getLine(); } } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Else_) { if ($this->skip_if_descendants === $node->getLine()) { $this->skip_if_descendants = null; $this->exists_cond_expr = null; } elseif (!$this->skip_if_descendants) { if ($this->exists_cond_expr && $this->enterConditional($this->exists_cond_expr) === \true) { $this->skip_if_descendants = $node->getLine(); } } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Yield_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\YieldFrom) { $function_like_storage = \end($this->functionlike_storages); if ($function_like_storage) { $function_like_storage->has_yield = \true; } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Cast\Object_) { $this->codebase->scanner->queueClassLikeForScanning('stdClass', \false, \false); $this->file_storage->referenced_classlikes['stdclass'] = 'stdClass'; } return null; } /** * @return null */ public function leaveNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_) { if (!$this->file_storage->aliases) { throw new \UnexpectedValueException('File storage liases should not be null'); } $this->aliases = $this->file_storage->aliases; if ($this->codebase->register_stub_files && $node->name && $node->name->parts === ['PHPSTORM_META']) { foreach ($node->stmts as $meta_stmt) { if ($meta_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression && $meta_stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $meta_stmt->expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $meta_stmt->expr->name->parts === ['override'] && \count($meta_stmt->expr->args) > 1) { \Psalm\Internal\Scanner\PhpStormMetaScanner::handleOverride($meta_stmt->expr->args, $this->codebase); } } } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike) { if ($this->skip_if_descendants) { return null; } if (isset($this->bad_classes[\spl_object_id($node)])) { return null; } if (!$this->fq_classlike_names) { throw new \LogicException('$this->fq_classlike_names should not be empty'); } $fq_classlike_name = \array_pop($this->fq_classlike_names); if (!$this->classlike_storages) { throw new \UnexpectedValueException('$this->classlike_storages cannot be empty'); } $classlike_storage = \array_pop($this->classlike_storages); if (\Psalm\Internal\Codebase\PropertyMap::inPropertyMap($fq_classlike_name)) { $mapped_properties = \Psalm\Internal\Codebase\PropertyMap::getPropertyMap()[\strtolower($fq_classlike_name)]; foreach ($mapped_properties as $property_name => $public_mapped_property) { $property_type = \Psalm\Type::parseString($public_mapped_property); $property_type->queueClassLikesForScanning($this->codebase, $this->file_storage); if (!isset($classlike_storage->properties[$property_name])) { $classlike_storage->properties[$property_name] = new \Psalm\Storage\PropertyStorage(); } $classlike_storage->properties[$property_name]->type = $property_type; $property_id = $fq_classlike_name . '::$' . $property_name; $classlike_storage->declaring_property_ids[$property_name] = $fq_classlike_name; $classlike_storage->appearing_property_ids[$property_name] = $property_id; } } $converted_aliases = \array_map(function (\Psalm\Internal\Type\TypeAlias\InlineTypeAlias $t) : ?TypeAlias\ClassTypeAlias { try { $union = \Psalm\Internal\Type\TypeParser::parseTokens($t->replacement_tokens, null, [], $this->type_aliases); $union->setFromDocblock(); return new \Psalm\Internal\Type\TypeAlias\ClassTypeAlias(\array_values($union->getAtomicTypes())); } catch (\Exception $e) { return null; } }, $this->classlike_type_aliases); foreach ($converted_aliases as $key => $type) { if (!$type) { $classlike_storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@psalm-type ' . $key . ' contains invalid references', new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); } } $classlike_storage->type_aliases = \array_filter($converted_aliases); $this->classlike_type_aliases = []; if ($classlike_storage->has_visitor_issues) { $this->file_storage->has_visitor_issues = \true; } if ($node->name) { $this->class_template_types = []; } if ($this->after_classlike_check_plugins) { $file_manipulations = []; foreach ($this->after_classlike_check_plugins as $plugin_fq_class_name) { $plugin_fq_class_name::afterClassLikeVisit($node, $classlike_storage, $this, $this->codebase, $file_manipulations); } } if (!$this->file_storage->has_visitor_issues) { $this->codebase->cacheClassLikeStorage($classlike_storage, $this->file_path); } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $this->function_template_types = []; } if ($this->skip_if_descendants) { return null; } if (!$this->functionlike_storages) { if ($this->file_storage->has_visitor_issues) { return null; } throw new \UnexpectedValueException('There should be function storages for line ' . $this->file_path . ':' . $node->getLine()); } $functionlike_storage = \array_pop($this->functionlike_storages); if ($functionlike_storage->docblock_issues && (\strpos($this->file_path, 'CoreGenericFunctions.phpstub') || \strpos($this->file_path, 'CoreGenericClasses.phpstub'))) { throw new \UnexpectedValueException('Error with core stub file docblocks'); } if ($functionlike_storage->has_visitor_issues) { $this->file_storage->has_visitor_issues = \true; } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_ && $node->getLine() === $this->skip_if_descendants) { $this->exists_cond_expr = null; $this->skip_if_descendants = null; } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Else_ && $node->getLine() === $this->skip_if_descendants) { $this->exists_cond_expr = null; $this->skip_if_descendants = null; } return null; } private function enterConditional(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $expr) : ?bool { if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BooleanNot) { $enter_negated = $this->enterConditional($expr->expr); return $enter_negated === null ? null : !$enter_negated; } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanAnd) { $enter_conditional_left = $this->enterConditional($expr->left); $enter_conditional_right = $this->enterConditional($expr->right); return $enter_conditional_left !== \false && $enter_conditional_right !== \false; } if ($expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BooleanOr) { $enter_conditional_left = $this->enterConditional($expr->left); $enter_conditional_right = $this->enterConditional($expr->right); return $enter_conditional_left !== \false || $enter_conditional_right !== \false; } if (!$expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { return null; } return $this->functionEvaluatesToTrue($expr); } private function functionEvaluatesToTrue(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $function) : ?bool { if (!$function->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { return null; } if ($function->name->parts === ['function_exists'] && isset($function->args[0]) && $function->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ && \function_exists($function->args[0]->value->value)) { $reflection_function = new \ReflectionFunction($function->args[0]->value->value); if ($reflection_function->isInternal()) { return \true; } return \false; } if ($function->name->parts === ['class_exists'] && isset($function->args[0])) { $string_value = null; if ($function->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $string_value = $function->args[0]->value->value; } elseif ($function->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $function->args[0]->value->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $function->args[0]->value->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($function->args[0]->value->name->name) === 'class') { $string_value = (string) $function->args[0]->value->class->getAttribute('resolvedName'); } if ($string_value && \class_exists($string_value)) { $reflection_class = new \ReflectionClass($string_value); if ($reflection_class->getFileName() !== $this->file_path) { $this->codebase->scanner->queueClassLikeForScanning($string_value); return \true; } } return \false; } if ($function->name->parts === ['interface_exists'] && isset($function->args[0])) { $string_value = null; if ($function->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $string_value = $function->args[0]->value->value; } elseif ($function->args[0]->value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $function->args[0]->value->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $function->args[0]->value->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($function->args[0]->value->name->name) === 'class') { $string_value = (string) $function->args[0]->value->class->getAttribute('resolvedName'); } if ($string_value && \interface_exists($string_value)) { $reflection_class = new \ReflectionClass($string_value); if ($reflection_class->getFileName() !== $this->file_path) { $this->codebase->scanner->queueClassLikeForScanning($string_value); return \true; } } return \false; } return null; } private function registerClassMapFunctionCall(string $function_id, \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall $node) : void { $callables = \Psalm\Internal\Codebase\InternalCallMapHandler::getCallablesFromCallMap($function_id); if ($callables) { foreach ($callables as $callable) { \assert($callable->params !== null); foreach ($callable->params as $function_param) { if ($function_param->type) { $function_param->type->queueClassLikesForScanning($this->codebase, $this->file_storage); } } if ($callable->return_type && !$callable->return_type->hasMixed()) { $callable->return_type->queueClassLikesForScanning($this->codebase, $this->file_storage); } } } if ($function_id === 'define') { $first_arg_value = isset($node->args[0]) ? $node->args[0]->value : null; $second_arg_value = isset($node->args[1]) ? $node->args[1]->value : null; if ($first_arg_value && $second_arg_value) { $type_provider = new \Psalm\Internal\Provider\NodeDataProvider(); $const_name = \Psalm\Internal\Analyzer\Statements\Expression\Fetch\ConstFetchAnalyzer::getConstName($first_arg_value, $type_provider, $this->codebase, $this->aliases); if ($const_name !== null) { $const_type = \Psalm\Internal\Analyzer\Statements\Expression\SimpleTypeInferer::infer($this->codebase, $type_provider, $second_arg_value, $this->aliases) ?: \Psalm\Type::getMixed(); if ($this->functionlike_storages && !$this->config->hoist_constants) { $functionlike_storage = $this->functionlike_storages[\count($this->functionlike_storages) - 1]; $functionlike_storage->defined_constants[$const_name] = $const_type; } else { $this->file_storage->constants[$const_name] = $const_type; $this->file_storage->declaring_constants[$const_name] = $this->file_path; } if (($this->codebase->register_stub_files || $this->codebase->register_autoload_files) && !\defined($const_name)) { $this->codebase->addGlobalConstantType($const_name, $const_type); } } } } $mapping_function_ids = []; if ($function_id === 'array_map' && isset($node->args[0]) || $function_id === 'array_filter' && isset($node->args[1])) { $node_arg_value = $function_id === 'array_map' ? $node->args[0]->value : $node->args[1]->value; if ($node_arg_value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $node_arg_value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_ || $node_arg_value instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { $mapping_function_ids = \Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer::getFunctionIdsFromCallableArg($this->file_scanner, $node_arg_value); } foreach ($mapping_function_ids as $potential_method_id) { if (\strpos($potential_method_id, '::') === \false) { continue; } [$callable_fqcln] = \explode('::', $potential_method_id); if (!\in_array(\strtolower($callable_fqcln), ['self', 'parent', 'static'], \true)) { $this->codebase->scanner->queueClassLikeForScanning($callable_fqcln); } } } if ($function_id === 'func_get_arg' || $function_id === 'func_get_args' || $function_id === 'func_num_args') { $function_like_storage = \end($this->functionlike_storages); if ($function_like_storage) { $function_like_storage->variadic = \true; } } if ($function_id === 'is_a' || $function_id === 'is_subclass_of') { $second_arg = $node->args[1]->value ?? null; if ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $this->codebase->scanner->queueClassLikeForScanning($second_arg->value); } } if ($function_id === 'class_alias' && !$this->skip_if_descendants) { $first_arg = $node->args[0]->value ?? null; $second_arg = $node->args[1]->value ?? null; if ($first_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $first_arg_value = $first_arg->value; } elseif ($first_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $first_arg->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $first_arg->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($first_arg->name->name) === 'class') { /** @var string */ $first_arg_value = $first_arg->class->getAttribute('resolvedName'); } else { $first_arg_value = null; } if ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $second_arg_value = $second_arg->value; } elseif ($second_arg instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch && $second_arg->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $second_arg->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && \strtolower($second_arg->name->name) === 'class') { /** @var string */ $second_arg_value = $second_arg->class->getAttribute('resolvedName'); } else { $second_arg_value = null; } if ($first_arg_value !== null && $second_arg_value !== null) { if ($first_arg_value[0] === '\\') { $first_arg_value = \substr($first_arg_value, 1); } if ($second_arg_value[0] === '\\') { $second_arg_value = \substr($second_arg_value, 1); } $second_arg_value = \strtolower($second_arg_value); $this->codebase->classlikes->addClassAlias($first_arg_value, $second_arg_value); $this->file_storage->classlike_aliases[$second_arg_value] = $first_arg_value; } } } /** * @return false|null */ private function registerClassLike(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike $node) : ?bool { $class_location = new \Psalm\CodeLocation($this->file_scanner, $node); $name_location = null; $storage = null; $class_name = null; $is_classlike_overridden = \false; if ($node->name === null) { if (!$node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { throw new \LogicException('Anonymous classes are always classes'); } $fq_classlike_name = \Psalm\Internal\Analyzer\ClassAnalyzer::getAnonymousClassName($node, $this->file_path); } else { $name_location = new \Psalm\CodeLocation($this->file_scanner, $node->name); $fq_classlike_name = ($this->aliases->namespace ? $this->aliases->namespace . '\\' : '') . $node->name->name; $fq_classlike_name_lc = \strtolower($fq_classlike_name); $class_name = $node->name->name; if ($this->codebase->classlike_storage_provider->has($fq_classlike_name_lc)) { $duplicate_storage = $this->codebase->classlike_storage_provider->get($fq_classlike_name_lc); if (!$this->codebase->register_stub_files) { if (!$duplicate_storage->stmt_location || $duplicate_storage->stmt_location->file_path !== $this->file_path || $class_location->getHash() !== $duplicate_storage->stmt_location->getHash()) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DuplicateClass('Class ' . $fq_classlike_name . ' has already been defined' . ($duplicate_storage->location ? ' in ' . $duplicate_storage->location->file_path : ''), $name_location))) { } $this->file_storage->has_visitor_issues = \true; $duplicate_storage->has_visitor_issues = \true; return \false; } } elseif (!$duplicate_storage->location || $duplicate_storage->location->file_path !== $this->file_path || $class_location->getHash() !== $duplicate_storage->location->getHash()) { $is_classlike_overridden = \true; // we're overwriting some methods $storage = $duplicate_storage; $this->codebase->classlike_storage_provider->makeNew(\strtolower($fq_classlike_name)); $storage->populated = \false; $storage->class_implements = []; // we do this because reflection reports $storage->parent_interfaces = []; $storage->stubbed = \true; $storage->aliases = $this->aliases; foreach ($storage->dependent_classlikes as $dependent_name_lc => $_) { $dependent_storage = $this->codebase->classlike_storage_provider->get($dependent_name_lc); $dependent_storage->populated = \false; $this->codebase->classlike_storage_provider->makeNew($dependent_name_lc); } } } } $fq_classlike_name_lc = \strtolower($fq_classlike_name); $this->file_storage->classlikes_in_file[$fq_classlike_name_lc] = $fq_classlike_name; $this->fq_classlike_names[] = $fq_classlike_name; if (!$storage) { $storage = $this->codebase->classlike_storage_provider->create($fq_classlike_name); } if ($class_name && isset($this->aliases->uses[\strtolower($class_name)]) && $this->aliases->uses[\strtolower($class_name)] !== $fq_classlike_name) { \Psalm\IssueBuffer::add(new \Psalm\Issue\ParseError('Class name ' . $class_name . ' clashes with a use statement alias', $name_location ?: $class_location)); $storage->has_visitor_issues = \true; $this->file_storage->has_visitor_issues = \true; } $storage->stmt_location = $class_location; $storage->location = $name_location; if ($this->namespace_name) { $storage->namespace_name_location = new \Psalm\CodeLocation($this->file_scanner, $this->namespace_name); } $storage->user_defined = !$this->codebase->register_stub_files; $storage->stubbed = $this->codebase->register_stub_files; $storage->aliases = $this->aliases; $this->classlike_storages[] = $storage; if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_) { $storage->abstract = $node->isAbstract(); $storage->final = $node->isFinal(); $this->codebase->classlikes->addFullyQualifiedClassName($fq_classlike_name, $this->file_path); if ($node->extends) { $parent_fqcln = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($node->extends, $this->aliases); $parent_fqcln = $this->codebase->classlikes->getUnAliasedName($parent_fqcln); $this->codebase->scanner->queueClassLikeForScanning($parent_fqcln, $this->scan_deep); $parent_fqcln_lc = \strtolower($parent_fqcln); $storage->parent_class = $parent_fqcln; $storage->parent_classes[$parent_fqcln_lc] = $parent_fqcln; $this->file_storage->required_classes[\strtolower($parent_fqcln)] = $parent_fqcln; } foreach ($node->implements as $interface) { $interface_fqcln = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($interface, $this->aliases); $this->codebase->scanner->queueClassLikeForScanning($interface_fqcln); $storage->class_implements[\strtolower($interface_fqcln)] = $interface_fqcln; $storage->direct_class_interfaces[\strtolower($interface_fqcln)] = $interface_fqcln; $this->file_storage->required_interfaces[\strtolower($interface_fqcln)] = $interface_fqcln; } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_) { $storage->is_interface = \true; $this->codebase->classlikes->addFullyQualifiedInterfaceName($fq_classlike_name, $this->file_path); foreach ($node->extends as $interface) { $interface_fqcln = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($interface, $this->aliases); $interface_fqcln = $this->codebase->classlikes->getUnAliasedName($interface_fqcln); $this->codebase->scanner->queueClassLikeForScanning($interface_fqcln); $storage->parent_interfaces[\strtolower($interface_fqcln)] = $interface_fqcln; $storage->direct_interface_parents[\strtolower($interface_fqcln)] = $interface_fqcln; $this->file_storage->required_interfaces[\strtolower($interface_fqcln)] = $interface_fqcln; } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_) { $storage->is_trait = \true; $this->file_storage->has_trait = \true; $this->codebase->classlikes->addFullyQualifiedTraitName($fq_classlike_name, $this->file_path); } $doc_comment = $node->getDocComment(); if ($doc_comment) { $docblock_info = null; try { $docblock_info = \Psalm\Internal\Analyzer\CommentAnalyzer::extractClassLikeDocblockInfo($node, $doc_comment, $this->aliases); } catch (\Psalm\Exception\DocblockParseException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . \implode('.', $this->fq_classlike_names), $name_location ?: $class_location); } if ($docblock_info) { if ($docblock_info->stub_override && !$is_classlike_overridden) { throw new \Psalm\Exception\InvalidClasslikeOverrideException('Class/interface/trait ' . $fq_classlike_name . ' is marked as stub override,' . ' but no original counterpart found'); } if ($docblock_info->templates) { $storage->template_types = []; \usort($docblock_info->templates, function (array $l, array $r) : int { return $l[4] > $r[4] ? 1 : -1; }); foreach ($docblock_info->templates as $i => $template_map) { $template_name = $template_map[0]; if ($template_map[1] !== null && $template_map[2] !== null) { if (\trim($template_map[2])) { try { $template_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($template_map[2], $this->aliases, $storage->template_types, $this->type_aliases), null, $storage->template_types, $this->type_aliases); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . \implode('.', $this->fq_classlike_names), $name_location ?: $class_location); continue; } $storage->template_types[$template_name] = [$fq_classlike_name => [$template_type]]; } else { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Template missing as type', $name_location ?: $class_location); } } else { /** @psalm-suppress PropertyTypeCoercion due to a Psalm bug */ $storage->template_types[$template_name][$fq_classlike_name] = [\Psalm\Type::getMixed()]; } $storage->template_covariants[$i] = $template_map[3]; } $this->class_template_types = $storage->template_types; } foreach ($docblock_info->template_extends as $extended_class_name) { $this->extendTemplatedType($storage, $node, $extended_class_name); } foreach ($docblock_info->template_implements as $implemented_class_name) { $this->implementTemplatedType($storage, $node, $implemented_class_name); } if ($docblock_info->yield) { try { $yield_type_tokens = \Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($docblock_info->yield, $this->aliases, $storage->template_types, $this->type_aliases); $yield_type = \Psalm\Internal\Type\TypeParser::parseTokens($yield_type_tokens, null, $storage->template_types ?: [], $this->type_aliases); $yield_type->setFromDocblock(); $yield_type->queueClassLikesForScanning($this->codebase, $this->file_storage, $storage->template_types ?: []); $storage->yield = $yield_type; } catch (\Psalm\Exception\TypeParseTreeException $e) { // do nothing } } if ($docblock_info->extension_requirement !== null) { $storage->extension_requirement = (string) \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($docblock_info->extension_requirement, $this->aliases, $this->class_template_types, $this->type_aliases), null, $this->class_template_types, $this->type_aliases); } foreach ($docblock_info->implementation_requirements as $implementation_requirement) { $storage->implementation_requirements[] = (string) \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($implementation_requirement, $this->aliases, $this->class_template_types, $this->type_aliases), null, $this->class_template_types, $this->type_aliases); } $storage->sealed_properties = $docblock_info->sealed_properties; $storage->sealed_methods = $docblock_info->sealed_methods; if ($docblock_info->properties) { foreach ($docblock_info->properties as $property) { $pseudo_property_type_tokens = \Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($property['type'], $this->aliases, $this->class_template_types, $this->type_aliases); try { $pseudo_property_type = \Psalm\Internal\Type\TypeParser::parseTokens($pseudo_property_type_tokens, null, $this->class_template_types, $this->type_aliases); $pseudo_property_type->setFromDocblock(); $pseudo_property_type->queueClassLikesForScanning($this->codebase, $this->file_storage, $storage->template_types ?: []); if ($property['tag'] !== 'property-read' && $property['tag'] !== 'psalm-property-read') { $storage->pseudo_property_set_types[$property['name']] = $pseudo_property_type; } if ($property['tag'] !== 'property-write' && $property['tag'] !== 'psalm-property-write') { $storage->pseudo_property_get_types[$property['name']] = $pseudo_property_type; } } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . \implode('.', $this->fq_classlike_names), $name_location ?: $class_location); } } $storage->sealed_properties = \true; } foreach ($docblock_info->methods as $method) { /** @var MethodStorage */ $pseudo_method_storage = $this->registerFunctionLike($method, \true); if ($pseudo_method_storage->is_static) { $storage->pseudo_static_methods[\strtolower($method->name->name)] = $pseudo_method_storage; } else { $storage->pseudo_methods[\strtolower($method->name->name)] = $pseudo_method_storage; } $storage->sealed_methods = \true; } foreach ($docblock_info->imported_types as $import_type_entry) { $imported_type_data = $import_type_entry['parts']; $location = new \Psalm\CodeLocation\DocblockTypeLocation($this->file_scanner, $import_type_entry['start_offset'], $import_type_entry['end_offset'], $import_type_entry['line_number']); // There are two valid forms: // @psalm-import Thing from Something // @psalm-import Thing from Something as Alias // but there could be leftovers after that if (\count($imported_type_data) < 3) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidTypeImport('Invalid import in docblock for ' . \implode('.', $this->fq_classlike_names) . ', expecting " from ",' . ' got "' . \implode(' ', $imported_type_data) . '" instead.', $location); continue; } if ($imported_type_data[1] === 'from' && !empty($imported_type_data[0]) && !empty($imported_type_data[2])) { $type_alias_name = $as_alias_name = $imported_type_data[0]; $declaring_classlike_name = $imported_type_data[2]; } else { $storage->docblock_issues[] = new \Psalm\Issue\InvalidTypeImport('Invalid import in docblock for ' . \implode('.', $this->fq_classlike_names) . ', expecting " from ", got "' . \implode(' ', [$imported_type_data[0], $imported_type_data[1], $imported_type_data[2]]) . '" instead.', $location); continue; } if (\count($imported_type_data) >= 4 && $imported_type_data[3] === 'as') { // long form if (empty($imported_type_data[4])) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidTypeImport('Invalid import in docblock for ' . \implode('.', $this->fq_classlike_names) . ', expecting "as ", got "' . $imported_type_data[3] . ' ' . ($imported_type_data[4] ?? '') . '" instead.', $location); continue; } $as_alias_name = $imported_type_data[4]; } $declaring_fq_classlike_name = \Psalm\Type::getFQCLNFromString($declaring_classlike_name, $this->aliases); $this->codebase->scanner->queueClassLikeForScanning($declaring_fq_classlike_name); $this->file_storage->referenced_classlikes[\strtolower($declaring_fq_classlike_name)] = $declaring_fq_classlike_name; $this->type_aliases[$as_alias_name] = new \Psalm\Internal\Type\TypeAlias\LinkableTypeAlias($declaring_fq_classlike_name, $type_alias_name, $import_type_entry['line_number'], $import_type_entry['start_offset'], $import_type_entry['end_offset']); } $storage->deprecated = $docblock_info->deprecated; if ($docblock_info->internal && !$docblock_info->psalm_internal && $this->aliases->namespace) { $storage->internal = \explode('\\', $this->aliases->namespace)[0]; } else { $storage->internal = $docblock_info->psalm_internal ?? ''; } $storage->final = $storage->final || $docblock_info->final; $storage->preserve_constructor_signature = $docblock_info->consistent_constructor; if ($storage->preserve_constructor_signature) { $has_constructor = \false; foreach ($node->stmts as $stmt) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && $stmt->name->name === '__construct') { $has_constructor = \true; break; } } if (!$has_constructor) { self::registerEmptyConstructor($storage); } } foreach ($docblock_info->mixins as $key => $mixin) { $mixin_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($mixin, $this->aliases, $this->class_template_types, $this->type_aliases, $fq_classlike_name), null, $this->class_template_types, $this->type_aliases); $mixin_type->queueClassLikesForScanning($this->codebase, $this->file_storage, $storage->template_types ?: []); $mixin_type->setFromDocblock(); if ($mixin_type->isSingle()) { $mixin_type = \array_values($mixin_type->getAtomicTypes())[0]; if ($mixin_type instanceof \Psalm\Type\Atomic\TNamedObject) { $storage->namedMixins[] = $mixin_type; } if ($mixin_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $storage->templatedMixins[] = $mixin_type; } } if ($key === 0) { $storage->mixin_declaring_fqcln = $storage->name; // backwards compatibility if ($mixin_type instanceof \Psalm\Type\Atomic\TNamedObject || $mixin_type instanceof \Psalm\Type\Atomic\TTemplateParam) { /** @psalm-suppress DeprecatedProperty **/ $storage->mixin = $mixin_type; } } } $storage->mutation_free = $docblock_info->mutation_free; $storage->external_mutation_free = $docblock_info->external_mutation_free; $storage->specialize_instance = $docblock_info->taint_specialize; $storage->override_property_visibility = $docblock_info->override_property_visibility; $storage->override_method_visibility = $docblock_info->override_method_visibility; $storage->suppressed_issues = $docblock_info->suppressed_issues; } } foreach ($node->getComments() as $comment) { if (!$comment instanceof \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc) { continue; } try { $type_aliases = \Psalm\Internal\Analyzer\CommentAnalyzer::getTypeAliasesFromComment($comment, $this->aliases, $this->type_aliases, $fq_classlike_name); foreach ($type_aliases as $type_alias) { // finds issues, if there are any \Psalm\Internal\Type\TypeParser::parseTokens($type_alias->replacement_tokens); } $this->type_aliases += $type_aliases; if ($type_aliases) { $this->classlike_type_aliases = $type_aliases; } } catch (\Psalm\Exception\DocblockParseException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock((string) $e->getMessage(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); } } foreach ($node->stmts as $node_stmt) { if ($node_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst) { $this->visitClassConstDeclaration($node_stmt, $storage, $fq_classlike_name); } } foreach ($node->stmts as $node_stmt) { if ($node_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property) { $this->visitPropertyDeclaration($node_stmt, $this->config, $storage, $fq_classlike_name); } } return null; } private function extendTemplatedType(\Psalm\Storage\ClassLikeStorage $storage, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike $node, string $extended_class_name) : void { if (\trim($extended_class_name) === '') { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Extended class cannot be empty in docblock for ' . \implode('.', $this->fq_classlike_names), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } try { $extended_union_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($extended_class_name, $this->aliases, $this->class_template_types, $this->type_aliases), null, $this->class_template_types, $this->type_aliases); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . \implode('.', $this->fq_classlike_names), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } if (!$extended_union_type->isSingle()) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@template-extends cannot be a union type', new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); } $extended_union_type->setFromDocblock(); $extended_union_type->queueClassLikesForScanning($this->codebase, $this->file_storage, $storage->template_types ?: []); foreach ($extended_union_type->getAtomicTypes() as $atomic_type) { if (!$atomic_type instanceof \Psalm\Type\Atomic\TGenericObject) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@template-extends has invalid class ' . $atomic_type->getId(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } $generic_class_lc = \strtolower($atomic_type->value); if (!isset($storage->parent_classes[$generic_class_lc]) && !isset($storage->parent_interfaces[$generic_class_lc])) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@template-extends must include the name of an extended class,' . ' got ' . $atomic_type->getId(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); } $extended_type_parameters = []; $storage->template_type_extends_count = \count($atomic_type->type_params); foreach ($atomic_type->type_params as $type_param) { $extended_type_parameters[] = $type_param; } $storage->template_type_extends[$atomic_type->value] = $extended_type_parameters; } } private function implementTemplatedType(\Psalm\Storage\ClassLikeStorage $storage, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike $node, string $implemented_class_name) : void { if (\trim($implemented_class_name) === '') { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Extended class cannot be empty in docblock for ' . \implode('.', $this->fq_classlike_names), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } try { $implemented_union_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($implemented_class_name, $this->aliases, $this->class_template_types, $this->type_aliases), null, $this->class_template_types, $this->type_aliases); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . \implode('.', $this->fq_classlike_names), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } if (!$implemented_union_type->isSingle()) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@template-implements cannot be a union type', new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } $implemented_union_type->setFromDocblock(); $implemented_union_type->queueClassLikesForScanning($this->codebase, $this->file_storage, $storage->template_types ?: []); foreach ($implemented_union_type->getAtomicTypes() as $atomic_type) { if (!$atomic_type instanceof \Psalm\Type\Atomic\TGenericObject) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@template-implements has invalid class ' . $atomic_type->getId(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } $generic_class_lc = \strtolower($atomic_type->value); if (!isset($storage->class_implements[$generic_class_lc])) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@template-implements must include the name of an implemented class,' . ' got ' . $atomic_type->getId(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } $implemented_type_parameters = []; $storage->template_type_implements_count[$generic_class_lc] = \count($atomic_type->type_params); foreach ($atomic_type->type_params as $type_param) { $implemented_type_parameters[] = $type_param; } $storage->template_type_extends[$atomic_type->value] = $implemented_type_parameters; } } private function useTemplatedType(\Psalm\Storage\ClassLikeStorage $storage, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\TraitUse $node, string $used_class_name) : void { if (\trim($used_class_name) === '') { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Extended class cannot be empty in docblock for ' . \implode('.', $this->fq_classlike_names), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } try { $used_union_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($used_class_name, $this->aliases, $this->class_template_types, $this->type_aliases), null, $this->class_template_types, $this->type_aliases); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . \implode('.', $this->fq_classlike_names), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } if (!$used_union_type->isSingle()) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@template-use cannot be a union type', new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } $used_union_type->setFromDocblock(); $used_union_type->queueClassLikesForScanning($this->codebase, $this->file_storage, $storage->template_types ?: []); foreach ($used_union_type->getAtomicTypes() as $atomic_type) { if (!$atomic_type instanceof \Psalm\Type\Atomic\TGenericObject) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@template-use has invalid class ' . $atomic_type->getId(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } $generic_class_lc = \strtolower($atomic_type->value); if (!isset($storage->used_traits[$generic_class_lc])) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('@template-use must include the name of an used class,' . ' got ' . $atomic_type->getId(), new \Psalm\CodeLocation($this->file_scanner, $node, null, \true)); return; } $used_type_parameters = []; $storage->template_type_uses_count[$generic_class_lc] = \count($atomic_type->type_params); foreach ($atomic_type->type_params as $type_param) { $used_type_parameters[] = $type_param; } $storage->template_type_extends[$atomic_type->value] = $used_type_parameters; } } private static function registerEmptyConstructor(\Psalm\Storage\ClassLikeStorage $class_storage) : void { $method_name_lc = '__construct'; if (isset($class_storage->methods[$method_name_lc])) { return; } $storage = $class_storage->methods['__construct'] = new \Psalm\Storage\MethodStorage(); $storage->cased_name = '__construct'; $storage->defining_fqcln = $class_storage->name; $storage->mutation_free = $storage->external_mutation_free = \true; $storage->mutation_free_inferred = \true; $class_storage->declaring_method_ids['__construct'] = new \Psalm\Internal\MethodIdentifier($class_storage->name, '__construct'); $class_storage->inheritable_method_ids['__construct'] = $class_storage->declaring_method_ids['__construct']; $class_storage->appearing_method_ids['__construct'] = $class_storage->declaring_method_ids['__construct']; $class_storage->overridden_method_ids['__construct'] = []; $storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; } /** * @param bool $fake_method in the case of @method annotations we do something a little strange * * @return FunctionStorage|MethodStorage|false */ private function registerFunctionLike(\_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $stmt, bool $fake_method = \false) { $class_storage = null; $fq_classlike_name = null; $is_functionlike_override = \false; $method_name_lc = null; if ($fake_method && $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $cased_function_id = '@method ' . $stmt->name->name; $storage = new \Psalm\Storage\MethodStorage(); $storage->defining_fqcln = ''; $storage->is_static = $stmt->isStatic(); $class_storage = $this->classlike_storages[\count($this->classlike_storages) - 1]; $storage->final = $class_storage->final; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_) { $cased_function_id = ($this->aliases->namespace ? $this->aliases->namespace . '\\' : '') . $stmt->name->name; $function_id = \strtolower($cased_function_id); $storage = new \Psalm\Storage\FunctionStorage(); if ($this->codebase->register_stub_files || $this->codebase->register_autoload_files) { if (isset($this->file_storage->functions[$function_id]) && ($this->codebase->register_stub_files || !$this->codebase->functions->hasStubbedFunction($function_id))) { $this->codebase->functions->addGlobalFunction($function_id, $this->file_storage->functions[$function_id]); $storage = $this->file_storage->functions[$function_id]; $this->functionlike_storages[] = $storage; return $storage; } } else { if (isset($this->file_storage->functions[$function_id])) { $duplicate_function_storage = $this->file_storage->functions[$function_id]; if ($duplicate_function_storage->location && $duplicate_function_storage->location->getLineNumber() === $stmt->getLine()) { $storage = $this->file_storage->functions[$function_id]; $this->functionlike_storages[] = $storage; return $storage; } if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DuplicateFunction('Method ' . $function_id . ' has already been defined' . ($duplicate_function_storage->location ? ' in ' . $duplicate_function_storage->location->file_path : ''), new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)))) { // fall through } $this->file_storage->has_visitor_issues = \true; $duplicate_function_storage->has_visitor_issues = \true; $storage = $this->file_storage->functions[$function_id]; $this->functionlike_storages[] = $storage; return $storage; } if (isset($this->config->getPredefinedFunctions()[$function_id])) { /** @psalm-suppress ArgumentTypeCoercion */ $reflection_function = new \ReflectionFunction($function_id); if ($reflection_function->getFileName() !== $this->file_path) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DuplicateFunction('Method ' . $function_id . ' has already been defined as a core function', new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)))) { // fall through } } } } if ($this->codebase->register_stub_files || $this->codebase->register_autoload_files && !$this->codebase->functions->hasStubbedFunction($function_id)) { $this->codebase->functions->addGlobalFunction($function_id, $storage); } $this->file_storage->functions[$function_id] = $storage; $this->file_storage->declaring_function_ids[$function_id] = \strtolower($this->file_path); } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { if (!$this->fq_classlike_names) { throw new \LogicException('$this->fq_classlike_names should not be null'); } $fq_classlike_name = $this->fq_classlike_names[\count($this->fq_classlike_names) - 1]; $method_name_lc = \strtolower($stmt->name->name); $function_id = $fq_classlike_name . '::' . $method_name_lc; $cased_function_id = $fq_classlike_name . '::' . $stmt->name->name; if (!$this->classlike_storages) { throw new \UnexpectedValueException('$class_storages cannot be empty for ' . $function_id); } $class_storage = $this->classlike_storages[\count($this->classlike_storages) - 1]; $storage = null; if (isset($class_storage->methods[$method_name_lc])) { if (!$this->codebase->register_stub_files) { $duplicate_method_storage = $class_storage->methods[$method_name_lc]; if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DuplicateMethod('Method ' . $function_id . ' has already been defined' . ($duplicate_method_storage->location ? ' in ' . $duplicate_method_storage->location->file_path : ''), new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)))) { // fall through } $this->file_storage->has_visitor_issues = \true; $duplicate_method_storage->has_visitor_issues = \true; return \false; } else { $is_functionlike_override = \true; } $storage = $class_storage->methods[$method_name_lc]; } if (!$storage) { $storage = $class_storage->methods[$method_name_lc] = new \Psalm\Storage\MethodStorage(); } $storage->defining_fqcln = $fq_classlike_name; $class_name_parts = \explode('\\', $fq_classlike_name); $class_name = \array_pop($class_name_parts); if ($method_name_lc === \strtolower($class_name) && !isset($class_storage->methods['__construct']) && \strpos($fq_classlike_name, '\\') === \false && $this->codebase->php_major_version < 8) { $this->codebase->methods->setDeclaringMethodId($fq_classlike_name, '__construct', $fq_classlike_name, $method_name_lc); $this->codebase->methods->setAppearingMethodId($fq_classlike_name, '__construct', $fq_classlike_name, $method_name_lc); } $method_id = new \Psalm\Internal\MethodIdentifier($fq_classlike_name, $method_name_lc); $class_storage->declaring_method_ids[$method_name_lc] = $class_storage->appearing_method_ids[$method_name_lc] = $method_id; if (!$stmt->isPrivate() || $method_name_lc === '__construct' || $class_storage->is_trait) { $class_storage->inheritable_method_ids[$method_name_lc] = $method_id; } if (!isset($class_storage->overridden_method_ids[$method_name_lc])) { $class_storage->overridden_method_ids[$method_name_lc] = []; } $storage->is_static = $stmt->isStatic(); $storage->abstract = $stmt->isAbstract(); $storage->final = $class_storage->final || $stmt->isFinal(); if ($storage->final && $method_name_lc === '__construct') { // a bit of a hack, but makes sure that `new static` works for these classes $class_storage->preserve_constructor_signature = \true; } if ($stmt->isPrivate()) { $storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE; } elseif ($stmt->isProtected()) { $storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED; } else { $storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; } } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrowFunction) { $function_id = $cased_function_id = \strtolower($this->file_path) . ':' . $stmt->getLine() . ':' . (int) $stmt->getAttribute('startFilePos') . ':-:closure'; $storage = $this->file_storage->functions[$function_id] = new \Psalm\Storage\FunctionStorage(); if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure) { foreach ($stmt->uses as $closure_use) { if ($closure_use->byRef && \is_string($closure_use->var->name)) { $storage->byref_uses[$closure_use->var->name] = \true; } } } } else { throw new \UnexpectedValueException('Unrecognized functionlike'); } $this->functionlike_storages[] = $storage; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { $storage->cased_name = $stmt->name->name; } elseif ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_) { $storage->cased_name = ($this->aliases->namespace ? $this->aliases->namespace . '\\' : '') . $stmt->name->name; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_) { $storage->location = new \Psalm\CodeLocation($this->file_scanner, $stmt->name, null, \true); } else { $storage->location = new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true); } $storage->stmt_location = new \Psalm\CodeLocation($this->file_scanner, $stmt); $required_param_count = 0; $i = 0; $has_optional_param = \false; $existing_params = []; $storage->params = []; foreach ($stmt->getParams() as $param) { if ($param->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Param' . ($i + 1) . ' of ' . $cased_function_id . ' has invalid syntax', new \Psalm\CodeLocation($this->file_scanner, $param, null, \true)); ++$i; continue; } $param_storage = $this->getTranslatedFunctionParam($param, $stmt, $fake_method, $fq_classlike_name); if ($param_storage->name === 'haystack' && (\strpos($this->file_path, 'CoreGenericFunctions.phpstub') || \strpos($this->file_path, 'CoreGenericClasses.phpstub'))) { $param_storage->expect_variable = \true; } if (isset($existing_params['$' . $param_storage->name])) { $storage->docblock_issues[] = new \Psalm\Issue\DuplicateParam('Duplicate param $' . $param_storage->name . ' in docblock for ' . $cased_function_id, new \Psalm\CodeLocation($this->file_scanner, $param, null, \true)); ++$i; continue; } $existing_params['$' . $param_storage->name] = $i; $storage->param_lookup[$param_storage->name] = !!$param->type; $storage->params[] = $param_storage; if (!$param_storage->is_optional && !$param_storage->is_variadic) { $required_param_count = $i + 1; if (!$param->variadic && $has_optional_param) { foreach ($storage->params as $param) { $param->is_optional = \false; } } } else { $has_optional_param = \true; } ++$i; } $storage->required_param_count = $required_param_count; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && $storage instanceof \Psalm\Storage\MethodStorage && $class_storage && !$class_storage->mutation_free && $stmt->stmts && \count($stmt->stmts) === 1 && !\count($stmt->params) && $stmt->stmts[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Return_ && $stmt->stmts[0]->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && $stmt->stmts[0]->expr->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $stmt->stmts[0]->expr->var->name === 'this' && $stmt->stmts[0]->expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $property_name = $stmt->stmts[0]->expr->name->name; if (isset($class_storage->properties[$property_name]) && $class_storage->properties[$property_name]->type) { $storage->mutation_free = \true; $storage->external_mutation_free = \true; $storage->mutation_free_inferred = !$stmt->isFinal() && !$class_storage->final; $class_storage->properties[$property_name]->getter_method = \strtolower($stmt->name->name); } } elseif (\strpos($stmt->name->name, 'assert') === 0 && $stmt->stmts) { $var_assertions = []; foreach ($stmt->stmts as $function_stmt) { if ($function_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_) { $final_actions = \Psalm\Internal\Analyzer\ScopeAnalyzer::getControlActions($function_stmt->stmts, null, $this->config->exit_functions, [], \false); if ($final_actions !== [\Psalm\Internal\Analyzer\ScopeAnalyzer::ACTION_END]) { $var_assertions = []; break; } $cond_id = \spl_object_id($function_stmt->cond); $if_clauses = \Psalm\Type\Algebra::getFormula($cond_id, $cond_id, $function_stmt->cond, $this->fq_classlike_names ? $this->fq_classlike_names[\count($this->fq_classlike_names) - 1] : null, $this->file_scanner, null); $negated_formula = \Psalm\Type\Algebra::negateFormula($if_clauses); $rules = \Psalm\Type\Algebra::getTruthsFromFormula($negated_formula); if (!$rules) { $var_assertions = []; break; } foreach ($rules as $var_id => $rule) { foreach ($rule as $rule_part) { if (\count($rule_part) > 1) { continue 2; } } if (isset($existing_params[$var_id])) { $param_offset = $existing_params[$var_id]; $var_assertions[] = new \Psalm\Storage\Assertion($param_offset, $rule); } elseif (\strpos($var_id, '$this->') === 0) { $var_assertions[] = new \Psalm\Storage\Assertion($var_id, $rule); } } } else { $var_assertions = []; break; } } $storage->assertions = $var_assertions; } } if (!$this->scan_deep && ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure) && $stmt->stmts) { // pick up func_get_args that would otherwise be missed foreach ($stmt->stmts as $function_stmt) { if ($function_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression && $function_stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign && $function_stmt->expr->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $function_stmt->expr->expr->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $function_id = \implode('\\', $function_stmt->expr->expr->name->parts); if ($function_id === 'func_get_arg' || $function_id === 'func_get_args' || $function_id === 'func_num_args') { $storage->variadic = \true; } } elseif ($function_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\If_ && $function_stmt->cond instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp && $function_stmt->cond->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Equal && $function_stmt->cond->left->left instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall && $function_stmt->cond->left->left->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name) { $function_id = \implode('\\', $function_stmt->cond->left->left->name->parts); if ($function_id === 'func_get_arg' || $function_id === 'func_get_args' || $function_id === 'func_num_args') { $storage->variadic = \true; } } } } $parser_return_type = $stmt->getReturnType(); if ($parser_return_type) { $original_type = $parser_return_type; $storage->return_type = $this->getTypeFromTypeHint($parser_return_type); $storage->return_type_location = new \Psalm\CodeLocation($this->file_scanner, $original_type); if ($stmt->returnsByRef()) { $storage->return_type->by_ref = \true; } $storage->signature_return_type = $storage->return_type; $storage->signature_return_type_location = $storage->return_type_location; } if ($stmt->returnsByRef()) { $storage->returns_by_ref = \true; } $doc_comment = $stmt->getDocComment(); if ($class_storage && !$class_storage->is_trait && \strlen($class_storage->internal) > \strlen($storage->internal)) { $storage->internal = $class_storage->internal; } if ($doc_comment) { try { $docblock_info = \Psalm\Internal\Analyzer\CommentAnalyzer::extractFunctionDocblockInfo($doc_comment); } catch (\Psalm\Exception\IncorrectDocblockException $e) { $storage->docblock_issues[] = new \Psalm\Issue\MissingDocblockType($e->getMessage() . ' in docblock for ' . $cased_function_id, new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); $docblock_info = null; } catch (\Psalm\Exception\DocblockParseException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . $cased_function_id, new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); $docblock_info = null; } if ($docblock_info) { $this->handleFunctionLikeDocblock($stmt, $storage, $docblock_info, $class_storage, $is_functionlike_override, $fake_method, $cased_function_id); } } if ($class_storage && $method_name_lc === '__construct') { foreach ($stmt->getParams() as $param) { if (!$param->flags || !$param->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable) { continue; } $param_storage = null; foreach ($storage->params as $param_storage) { if ($param_storage->name === $param->var->name) { break; } } if (!$param_storage) { continue; } $property_storage = $class_storage->properties[$param_storage->name] = new \Psalm\Storage\PropertyStorage(); $property_storage->is_static = \false; $property_storage->type = $param_storage->type; $property_storage->signature_type = $param_storage->signature_type; $property_storage->signature_type_location = $param_storage->signature_type_location; $property_storage->type_location = $param_storage->type_location; $property_storage->location = $param_storage->location; $property_storage->stmt_location = new \Psalm\CodeLocation($this->file_scanner, $param); $property_storage->has_default = $param->default ? \true : \false; $property_id = $fq_classlike_name . '::$' . $param_storage->name; switch ($param->flags) { case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC: $property_storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; $class_storage->inheritable_property_ids[$param_storage->name] = $property_id; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED: $property_storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED; $class_storage->inheritable_property_ids[$param_storage->name] = $property_id; break; case \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE: $property_storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE; break; } $fq_classlike_name = $this->fq_classlike_names[\count($this->fq_classlike_names) - 1]; $property_id = $fq_classlike_name . '::$' . $param_storage->name; $class_storage->declaring_property_ids[$param_storage->name] = $fq_classlike_name; $class_storage->appearing_property_ids[$param_storage->name] = $property_id; $class_storage->initialized_properties[$param_storage->name] = \true; } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod && $stmt->name->name === '__construct' && $class_storage && $storage instanceof \Psalm\Storage\MethodStorage && $storage->params && $this->config->infer_property_types_from_constructor) { $this->inferPropertyTypeFromConstructor($stmt, $storage, $class_storage); } return $storage; } private function handleFunctionLikeDocblock(\_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $stmt, \Psalm\Storage\FunctionLikeStorage $storage, \Psalm\Internal\Scanner\FunctionDocblockComment $docblock_info, ?\Psalm\Storage\ClassLikeStorage $class_storage, bool $is_functionlike_override, bool $fake_method, string $cased_function_id) : void { if ($docblock_info->mutation_free) { $storage->mutation_free = \true; if ($storage instanceof \Psalm\Storage\MethodStorage) { $storage->external_mutation_free = \true; $storage->mutation_free_inferred = \false; } } if ($storage instanceof \Psalm\Storage\MethodStorage && $docblock_info->external_mutation_free) { $storage->external_mutation_free = \true; } if ($docblock_info->deprecated) { $storage->deprecated = \true; } if ($docblock_info->internal && !$docblock_info->psalm_internal && $this->aliases->namespace) { $storage->internal = \explode('\\', $this->aliases->namespace)[0]; } elseif (!$class_storage || $docblock_info->psalm_internal && \strlen($docblock_info->psalm_internal) > \strlen($class_storage->internal)) { $storage->internal = $docblock_info->psalm_internal ?? ''; } if (($storage->internal || $class_storage && $class_storage->internal) && !$this->config->allow_internal_named_arg_calls) { $storage->allow_named_arg_calls = \false; } elseif ($docblock_info->no_named_args) { $storage->allow_named_arg_calls = \false; } if ($docblock_info->variadic) { $storage->variadic = \true; } if ($docblock_info->pure) { $storage->pure = \true; $storage->specialize_call = \true; $storage->mutation_free = \true; if ($storage instanceof \Psalm\Storage\MethodStorage) { $storage->external_mutation_free = \true; } } if ($docblock_info->specialize_call) { $storage->specialize_call = \true; } if ($docblock_info->ignore_nullable_return && $storage->return_type) { $storage->return_type->ignore_nullable_issues = \true; } if ($docblock_info->ignore_falsable_return && $storage->return_type) { $storage->return_type->ignore_falsable_issues = \true; } if ($docblock_info->stub_override && !$is_functionlike_override) { throw new \Psalm\Exception\InvalidMethodOverrideException('Method ' . $cased_function_id . ' is marked as stub override,' . ' but no original counterpart found'); } $storage->suppressed_issues = $docblock_info->suppressed_issues; foreach ($docblock_info->throws as [$throw, $offset, $line]) { $throw_location = new \Psalm\CodeLocation\DocblockTypeLocation($this->file_scanner, $offset, $offset + \strlen($throw), $line); $class_names = \array_filter(\array_map('trim', \explode('|', $throw))); foreach ($class_names as $throw_class) { if ($throw_class !== 'self' && $throw_class !== 'static' && $throw_class !== 'parent') { $exception_fqcln = \Psalm\Type::getFQCLNFromString($throw_class, $this->aliases); } else { $exception_fqcln = $throw_class; } $this->codebase->scanner->queueClassLikeForScanning($exception_fqcln); $this->file_storage->referenced_classlikes[\strtolower($exception_fqcln)] = $exception_fqcln; $storage->throws[$exception_fqcln] = \true; $storage->throw_locations[$exception_fqcln] = $throw_location; } } if (!$this->config->use_docblock_types) { return; } if ($storage instanceof \Psalm\Storage\MethodStorage && $docblock_info->inheritdoc) { $storage->inheritdoc = \true; } $template_types = $class_storage && $class_storage->template_types ? $class_storage->template_types : null; if ($docblock_info->templates) { $storage->template_types = []; foreach ($docblock_info->templates as $i => $template_map) { $template_name = $template_map[0]; if ($template_map[1] !== null && $template_map[2] !== null) { if (\trim($template_map[2])) { try { $template_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($template_map[2], $this->aliases, $storage->template_types + ($template_types ?: []), $this->type_aliases), null, $storage->template_types + ($template_types ?: []), $this->type_aliases); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Template ' . $template_name . ' has invalid as type - ' . $e->getMessage(), new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); $template_type = \Psalm\Type::getMixed(); } } else { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Template ' . $template_name . ' missing as type', new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); $template_type = \Psalm\Type::getMixed(); } } else { $template_type = \Psalm\Type::getMixed(); } if (isset($template_types[$template_name])) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Duplicate template param ' . $template_name . ' in docblock for ' . $cased_function_id, new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); } else { $storage->template_types[$template_name] = ['fn-' . \strtolower($cased_function_id) => [$template_type]]; } $storage->template_covariants[$i] = $template_map[3]; } $template_types = \array_merge($template_types ?: [], $storage->template_types); $this->function_template_types = $template_types; } if ($docblock_info->assertions) { $storage->assertions = []; foreach ($docblock_info->assertions as $assertion) { $assertion_type_parts = $this->getAssertionParts($storage, $assertion['type'], $stmt, $class_storage && !$class_storage->is_trait ? $class_storage->name : null); if (!$assertion_type_parts) { continue; } foreach ($storage->params as $i => $param) { if ($param->name === $assertion['param_name']) { $storage->assertions[] = new \Psalm\Storage\Assertion($i, [$assertion_type_parts]); continue 2; } } $storage->assertions[] = new \Psalm\Storage\Assertion('$' . $assertion['param_name'], [$assertion_type_parts]); } } if ($docblock_info->if_true_assertions) { $storage->if_true_assertions = []; foreach ($docblock_info->if_true_assertions as $assertion) { $assertion_type_parts = $this->getAssertionParts($storage, $assertion['type'], $stmt, $class_storage && !$class_storage->is_trait ? $class_storage->name : null); if (!$assertion_type_parts) { continue; } foreach ($storage->params as $i => $param) { if ($param->name === $assertion['param_name']) { $storage->if_true_assertions[] = new \Psalm\Storage\Assertion($i, [$assertion_type_parts]); continue 2; } } $storage->if_true_assertions[] = new \Psalm\Storage\Assertion('$' . $assertion['param_name'], [$assertion_type_parts]); } } if ($docblock_info->if_false_assertions) { $storage->if_false_assertions = []; foreach ($docblock_info->if_false_assertions as $assertion) { $assertion_type_parts = $this->getAssertionParts($storage, $assertion['type'], $stmt, $class_storage && !$class_storage->is_trait ? $class_storage->name : null); if (!$assertion_type_parts) { continue; } foreach ($storage->params as $i => $param) { if ($param->name === $assertion['param_name']) { $storage->if_false_assertions[] = new \Psalm\Storage\Assertion($i, [$assertion_type_parts]); continue 2; } } $storage->if_false_assertions[] = new \Psalm\Storage\Assertion('$' . $assertion['param_name'], [$assertion_type_parts]); } } foreach ($docblock_info->globals as $global) { try { $storage->global_types[$global['name']] = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($global['type'], $this->aliases, null, $this->type_aliases), null); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . $cased_function_id, new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); continue; } } if ($docblock_info->params) { $this->improveParamsFromDocblock($storage, $docblock_info->params, $stmt, $fake_method, $class_storage && !$class_storage->is_trait ? $class_storage->name : null); } if ($storage instanceof \Psalm\Storage\MethodStorage) { $storage->has_docblock_param_types = (bool) \array_filter($storage->params, function (\Psalm\Storage\FunctionLikeParameter $p) : bool { return $p->type !== null && $p->has_docblock_type; }); } $class_template_types = $this->class_template_types; foreach ($docblock_info->params_out as $docblock_param_out) { $param_name = \substr($docblock_param_out['name'], 1); try { $out_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($docblock_param_out['type'], $this->aliases, $this->function_template_types + $class_template_types, $this->type_aliases), null, $this->function_template_types + $class_template_types, $this->type_aliases); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . $cased_function_id, new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); continue; } $out_type->queueClassLikesForScanning($this->codebase, $this->file_storage, $storage->template_types ?: []); foreach ($storage->params as $param_storage) { if ($param_storage->name === $param_name) { $param_storage->out_type = $out_type; } } } if ($docblock_info->self_out && $storage instanceof \Psalm\Storage\MethodStorage) { $out_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($docblock_info->self_out['type'], $this->aliases, $this->function_template_types + $class_template_types, $this->type_aliases), null, $this->function_template_types + $class_template_types, $this->type_aliases); $storage->self_out_type = $out_type; } foreach ($docblock_info->taint_sink_params as $taint_sink_param) { $param_name = \substr($taint_sink_param['name'], 1); foreach ($storage->params as $param_storage) { if ($param_storage->name === $param_name) { $param_storage->sinks[] = $taint_sink_param['taint']; } } } foreach ($docblock_info->taint_source_types as $taint_source_type) { if ($taint_source_type === 'input') { $storage->taint_source_types = \array_merge($storage->taint_source_types, \Psalm\Type\TaintKindGroup::ALL_INPUT); } else { $storage->taint_source_types[] = $taint_source_type; } } $storage->added_taints = $docblock_info->added_taints; $storage->removed_taints = $docblock_info->removed_taints; if ($docblock_info->flows) { foreach ($docblock_info->flows as $flow) { $path_type = 'arg'; $fancy_path_regex = '/-\\(([a-z\\-]+)\\)->/'; if (\preg_match($fancy_path_regex, $flow, $matches)) { if (isset($matches[1])) { $path_type = $matches[1]; } $flow = \preg_replace($fancy_path_regex, '->', $flow); } $flow_parts = \explode('->', $flow); if (isset($flow_parts[1]) && \trim($flow_parts[1]) === 'return') { $source_param_string = \trim($flow_parts[0]); if ($source_param_string[0] === '(' && \substr($source_param_string, -1) === ')') { $source_params = \preg_split('/, ?/', \substr($source_param_string, 1, -1)); foreach ($source_params as $source_param) { $source_param = \substr($source_param, 1); foreach ($storage->params as $i => $param_storage) { if ($param_storage->name === $source_param) { $storage->return_source_params[$i] = $path_type; } } } } } } } foreach ($docblock_info->assert_untainted_params as $untainted_assert_param) { $param_name = \substr($untainted_assert_param['name'], 1); foreach ($storage->params as $param_storage) { if ($param_storage->name === $param_name) { $param_storage->assert_untainted = \true; } } } if ($docblock_info->template_typeofs) { foreach ($docblock_info->template_typeofs as $template_typeof) { foreach ($storage->params as $param) { if ($param->name === $template_typeof['param_name']) { $param_type_nullable = $param->type && $param->type->isNullable(); $template_type = null; $template_class = null; if (isset($template_types[$template_typeof['template_type']])) { foreach ($template_types[$template_typeof['template_type']] as $class => $map) { $template_type = $map[0]; $template_class = $class; } } $template_atomic_type = null; if ($template_type) { foreach ($template_type->getAtomicTypes() as $tat) { if ($tat instanceof \Psalm\Type\Atomic\TNamedObject) { $template_atomic_type = $tat; } } } $param->type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParamClass($template_typeof['template_type'], $template_type && !$template_type->isMixed() ? (string) $template_type : 'object', $template_atomic_type, $template_class ?: 'fn-' . \strtolower($cased_function_id))]); if ($param_type_nullable) { $param->type->addType(new \Psalm\Type\Atomic\TNull()); } break; } } } } if ($docblock_info->return_type) { $docblock_return_type = $docblock_info->return_type; if (!$fake_method && $docblock_info->return_type_line_number && $docblock_info->return_type_start && $docblock_info->return_type_end) { $storage->return_type_location = new \Psalm\CodeLocation\DocblockTypeLocation($this->file_scanner, $docblock_info->return_type_start, $docblock_info->return_type_end, $docblock_info->return_type_line_number); } else { $storage->return_type_location = new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \false, !$fake_method ? \Psalm\CodeLocation::FUNCTION_PHPDOC_RETURN_TYPE : \Psalm\CodeLocation::FUNCTION_PHPDOC_METHOD, $docblock_info->return_type); } try { $fixed_type_tokens = \Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($docblock_return_type, $this->aliases, $this->function_template_types + $class_template_types, $this->type_aliases, $class_storage && !$class_storage->is_trait ? $class_storage->name : null); $param_type_mapping = []; // This checks for param references in the return type tokens // If found, the param is replaced with a generated template param foreach ($fixed_type_tokens as $i => $type_token) { $token_body = $type_token[0]; $template_function_id = 'fn-' . \strtolower($cased_function_id); if ($token_body[0] === '$') { foreach ($storage->params as $j => $param_storage) { if ('$' . $param_storage->name === $token_body) { if (!isset($param_type_mapping[$token_body])) { $template_name = 'TGeneratedFromParam' . $j; $template_as_type = $param_storage->type ? clone $param_storage->type : \Psalm\Type::getMixed(); $storage->template_types[$template_name] = [$template_function_id => [$template_as_type]]; $this->function_template_types[$template_name] = $storage->template_types[$template_name]; $param_type_mapping[$token_body] = $template_name; $param_storage->type = new \Psalm\Type\Union([new \Psalm\Type\Atomic\TTemplateParam($template_name, $template_as_type, $template_function_id)]); } // spaces are allowed before $foo in get(string $foo) magic method // definitions, but we want to remove them in this instance if (isset($fixed_type_tokens[$i - 1]) && $fixed_type_tokens[$i - 1][0][0] === ' ') { unset($fixed_type_tokens[$i - 1]); } $fixed_type_tokens[$i][0] = $param_type_mapping[$token_body]; continue 2; } } } if ($token_body === 'func_num_args()') { $template_name = 'TFunctionArgCount'; $storage->template_types[$template_name] = [$template_function_id => [\Psalm\Type::getInt()]]; $this->function_template_types[$template_name] = $storage->template_types[$template_name]; $fixed_type_tokens[$i][0] = $template_name; } } $storage->return_type = \Psalm\Internal\Type\TypeParser::parseTokens(\array_values($fixed_type_tokens), null, $this->function_template_types + $class_template_types, $this->type_aliases); $storage->return_type->setFromDocblock(); if ($storage->signature_return_type) { $all_typehint_types_match = \true; $signature_return_atomic_types = $storage->signature_return_type->getAtomicTypes(); foreach ($storage->return_type->getAtomicTypes() as $key => $type) { if (isset($signature_return_atomic_types[$key])) { $type->from_docblock = \false; } else { $all_typehint_types_match = \false; } } if ($all_typehint_types_match) { $storage->return_type->from_docblock = \false; } if ($storage->signature_return_type->isNullable() && !$storage->return_type->isNullable() && !$storage->return_type->hasTemplate() && !$storage->return_type->hasConditional()) { $storage->return_type->addType(new \Psalm\Type\Atomic\TNull()); } } $storage->return_type->queueClassLikesForScanning($this->codebase, $this->file_storage); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . $cased_function_id, new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); } if ($storage->return_type && $docblock_info->ignore_nullable_return) { $storage->return_type->ignore_nullable_issues = \true; } if ($storage->return_type && $docblock_info->ignore_falsable_return) { $storage->return_type->ignore_falsable_issues = \true; } if ($stmt->returnsByRef() && $storage->return_type) { $storage->return_type->by_ref = \true; } if ($docblock_info->return_type_line_number && !$fake_method) { $storage->return_type_location->setCommentLine($docblock_info->return_type_line_number); } $storage->return_type_description = $docblock_info->return_type_description; } } private function inferPropertyTypeFromConstructor(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod $stmt, \Psalm\Storage\MethodStorage $storage, \Psalm\Storage\ClassLikeStorage $class_storage) : void { if (!$stmt->stmts) { return; } $assigned_properties = []; foreach ($stmt->stmts as $function_stmt) { if ($function_stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Expression && $function_stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign && $function_stmt->expr->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PropertyFetch && $function_stmt->expr->var->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && $function_stmt->expr->var->var->name === 'this' && $function_stmt->expr->var->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && ($property_name = $function_stmt->expr->var->name->name) && isset($class_storage->properties[$property_name]) && $function_stmt->expr->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($function_stmt->expr->expr->name) && ($param_name = $function_stmt->expr->expr->name) && isset($storage->param_lookup[$param_name])) { if ($class_storage->properties[$property_name]->type || !$storage->param_lookup[$param_name]) { continue; } $param_index = \array_search($param_name, \array_keys($storage->param_lookup), \true); if ($param_index === \false || !isset($storage->params[$param_index]->type)) { continue; } $param_type = $storage->params[$param_index]->type; $assigned_properties[$property_name] = $storage->params[$param_index]->is_variadic ? new \Psalm\Type\Union([new \Psalm\Type\Atomic\TArray([\Psalm\Type::getInt(), $param_type])]) : $param_type; } else { $assigned_properties = []; break; } } if (!$assigned_properties) { return; } $storage->external_mutation_free = \true; foreach ($assigned_properties as $property_name => $property_type) { $class_storage->properties[$property_name]->type = clone $property_type; } } /** * @return non-empty-list|null */ private function getAssertionParts(\Psalm\Storage\FunctionLikeStorage $storage, string $assertion_type, \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $stmt, ?string $self_fqcln) : ?array { $prefix = ''; if ($assertion_type[0] === '!') { $prefix = '!'; $assertion_type = \substr($assertion_type, 1); } if ($assertion_type[0] === '~') { $prefix .= '~'; $assertion_type = \substr($assertion_type, 1); } if ($assertion_type[0] === '=') { $prefix .= '='; $assertion_type = \substr($assertion_type, 1); } $class_template_types = !$stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod || !$stmt->isStatic() ? $this->class_template_types : []; try { $namespaced_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($assertion_type, $this->aliases, $this->function_template_types + $class_template_types, $this->type_aliases, $self_fqcln, null, \true)); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Invalid @psalm-assert union type ' . $e, new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); return null; } if ($prefix && \count($namespaced_type->getAtomicTypes()) > 1) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock('Docblock assertions cannot contain | characters together with ' . $prefix, new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); return null; } $namespaced_type->queueClassLikesForScanning($this->codebase, $this->file_storage, $this->function_template_types + $class_template_types); $assertion_type_parts = []; foreach ($namespaced_type->getAtomicTypes() as $namespaced_type_part) { if ($namespaced_type_part instanceof \Psalm\Type\Atomic\TAssertionFalsy || $namespaced_type_part instanceof \Psalm\Type\Atomic\TList && $namespaced_type_part->type_param->isMixed() || $namespaced_type_part instanceof \Psalm\Type\Atomic\TArray && $namespaced_type_part->type_params[0]->isArrayKey() && $namespaced_type_part->type_params[1]->isMixed() || $namespaced_type_part instanceof \Psalm\Type\Atomic\TIterable && $namespaced_type_part->type_params[0]->isMixed() && $namespaced_type_part->type_params[1]->isMixed()) { $assertion_type_parts[] = $prefix . $namespaced_type_part->getAssertionString(); } else { $assertion_type_parts[] = $prefix . $namespaced_type_part->getId(); } } return $assertion_type_parts; } public function getTranslatedFunctionParam(\_HumbugBoxd02f763d3c56\PhpParser\Node\Param $param, \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $stmt, bool $fake_method, ?string $fq_classlike_name) : \Psalm\Storage\FunctionLikeParameter { $param_type = null; $is_nullable = $param->default !== null && $param->default instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch && \strtolower($param->default->name->parts[0]) === 'null'; $param_typehint = $param->type; if ($param_typehint) { $param_type = $this->getTypeFromTypeHint($param_typehint); if ($is_nullable) { $param_type->addType(new \Psalm\Type\Atomic\TNull()); } else { $is_nullable = $param_type->isNullable(); } } $is_optional = $param->default !== null; if ($param->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Error || !\is_string($param->var->name)) { throw new \UnexpectedValueException('Not expecting param name to be non-string'); } return new \Psalm\Storage\FunctionLikeParameter($param->var->name, $param->byRef, $param_type, new \Psalm\CodeLocation($this->file_scanner, $fake_method ? $stmt : $param->var, null, \false, !$fake_method ? \Psalm\CodeLocation::FUNCTION_PARAM_VAR : \Psalm\CodeLocation::FUNCTION_PHPDOC_METHOD), $param_typehint ? new \Psalm\CodeLocation($this->file_scanner, $fake_method ? $stmt : $param, null, \false, \Psalm\CodeLocation::FUNCTION_PARAM_TYPE) : null, $is_optional, $is_nullable, $param->variadic, $param->default ? \Psalm\Internal\Analyzer\Statements\Expression\SimpleTypeInferer::infer($this->codebase, new \Psalm\Internal\Provider\NodeDataProvider(), $param->default, $this->aliases, null, null, $fq_classlike_name) : null); } /** * @param PhpParser\Node\Identifier|PhpParser\Node\Name|PhpParser\Node\NullableType|PhpParser\Node\UnionType $hint */ private function getTypeFromTypeHint(\_HumbugBoxd02f763d3c56\PhpParser\NodeAbstract $hint) : \Psalm\Type\Union { if ($hint instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\UnionType) { $type = null; if (!$hint->types) { throw new \UnexpectedValueException('bad'); } foreach ($hint->types as $atomic_typehint) { $resolved_type = $this->getTypeFromTypeHint($atomic_typehint); if (!$type) { $type = $resolved_type; } else { $type = \Psalm\Type::combineUnionTypes($resolved_type, $type); } } return $type; } $is_nullable = \false; if ($hint instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType) { $is_nullable = \true; $hint = $hint->type; } if ($hint instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier) { $type_string = $hint->name; } elseif ($hint instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified) { $type_string = (string) $hint; $this->codebase->scanner->queueClassLikeForScanning($type_string); $this->file_storage->referenced_classlikes[\strtolower($type_string)] = $type_string; } else { $lower_hint = \strtolower($hint->parts[0]); if ($this->classlike_storages && ($lower_hint === 'self' || $lower_hint === 'static') && !\end($this->classlike_storages)->is_trait) { $type_string = $this->fq_classlike_names[\count($this->fq_classlike_names) - 1]; if ($lower_hint === 'static') { $type_string .= '&static'; } } else { $type_string = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($hint, $this->aliases); } if (!\in_array($lower_hint, ['self', 'static', 'parent'], \true)) { $this->codebase->scanner->queueClassLikeForScanning($type_string); $this->file_storage->referenced_classlikes[\strtolower($type_string)] = $type_string; } } $type = \Psalm\Type::parseString($type_string, [$this->php_major_version, $this->php_minor_version], []); if ($is_nullable) { $type->addType(new \Psalm\Type\Atomic\TNull()); } return $type; } /** * @param array $docblock_params * */ private function improveParamsFromDocblock(\Psalm\Storage\FunctionLikeStorage $storage, array $docblock_params, \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $function, bool $fake_method, ?string $fq_classlike_name) : void { $base = $this->fq_classlike_names ? $this->fq_classlike_names[\count($this->fq_classlike_names) - 1] . '::' : ''; $cased_method_id = $base . $storage->cased_name; $unused_docblock_params = []; $class_template_types = !$function instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod || !$function->isStatic() ? $this->class_template_types : []; foreach ($docblock_params as $docblock_param) { $param_name = $docblock_param['name']; $docblock_param_variadic = \false; if (\substr($param_name, 0, 3) === '...') { $docblock_param_variadic = \true; $param_name = \substr($param_name, 3); } $param_name = \substr($param_name, 1); $storage_param = null; foreach ($storage->params as $function_signature_param) { if ($function_signature_param->name === $param_name) { $storage_param = $function_signature_param; break; } } if (!$fake_method) { $docblock_type_location = new \Psalm\CodeLocation\DocblockTypeLocation($this->file_scanner, $docblock_param['start'], $docblock_param['end'], $docblock_param['line_number']); } else { $docblock_type_location = new \Psalm\CodeLocation($this->file_scanner, $function, null, \false, \Psalm\CodeLocation::FUNCTION_PHPDOC_METHOD, null); } if ($storage_param === null) { $param_location = new \Psalm\CodeLocation($this->file_scanner, $function, null, \true, \Psalm\CodeLocation::FUNCTION_PARAM_VAR); $param_location->setCommentLine($docblock_param['line_number']); $unused_docblock_params[$param_name] = $param_location; if (!$docblock_param_variadic || $storage->params || $this->scan_deep) { continue; } $storage_param = new \Psalm\Storage\FunctionLikeParameter($param_name, \false, null, null, null, \false, \false, \true, null); $storage->params[] = $storage_param; } try { $new_param_type = \Psalm\Internal\Type\TypeParser::parseTokens(\Psalm\Internal\Type\TypeTokenizer::getFullyQualifiedTokens($docblock_param['type'], $this->aliases, $this->function_template_types + $class_template_types, $this->type_aliases, $fq_classlike_name), null, $this->function_template_types + $class_template_types, $this->type_aliases); } catch (\Psalm\Exception\TypeParseTreeException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage() . ' in docblock for ' . $cased_method_id, $docblock_type_location); continue; } $storage_param->has_docblock_type = \true; $new_param_type->setFromDocblock(); $new_param_type->queueClassLikesForScanning($this->codebase, $this->file_storage, $storage->template_types ?: []); if ($storage->template_types) { foreach ($storage->template_types as $t => $type_map) { foreach ($type_map as $obj => [$type]) { if ($type->isMixed() && $docblock_param['type'] === 'class-string<' . $t . '>') { $storage->template_types[$t][$obj] = [\Psalm\Type::getObject()]; if (isset($this->function_template_types[$t])) { $this->function_template_types[$t][$obj] = $storage->template_types[$t][$obj]; } } } } } if (!$docblock_param_variadic && $storage_param->is_variadic && $new_param_type->hasArray()) { /** * @psalm-suppress PossiblyUndefinedStringArrayOffset * @var Type\Atomic\TArray|Type\Atomic\TKeyedArray|Type\Atomic\TList */ $array_type = $new_param_type->getAtomicTypes()['array']; if ($array_type instanceof \Psalm\Type\Atomic\TKeyedArray) { $new_param_type = $array_type->getGenericValueType(); } elseif ($array_type instanceof \Psalm\Type\Atomic\TList) { $new_param_type = $array_type->type_param; } else { $new_param_type = $array_type->type_params[1]; } } $existing_param_type_nullable = $storage_param->is_nullable; if (!$storage_param->type || $storage_param->type->hasMixed() || $storage->template_types) { if ($existing_param_type_nullable && !$new_param_type->isNullable() && !$new_param_type->hasTemplate()) { $new_param_type->addType(new \Psalm\Type\Atomic\TNull()); } if ($this->config->add_param_default_to_docblock_type && $storage_param->default_type && !$storage_param->default_type->hasMixed() && (!$storage_param->type || !$storage_param->type->hasMixed())) { $new_param_type = \Psalm\Type::combineUnionTypes($new_param_type, $storage_param->default_type); } $storage_param->type = $new_param_type; $storage_param->type_location = $docblock_type_location; continue; } $storage_param_atomic_types = $storage_param->type->getAtomicTypes(); $all_typehint_types_match = \true; foreach ($new_param_type->getAtomicTypes() as $key => $type) { if (isset($storage_param_atomic_types[$key])) { $type->from_docblock = \false; if ($storage_param_atomic_types[$key] instanceof \Psalm\Type\Atomic\TArray && $type instanceof \Psalm\Type\Atomic\TArray && $type->type_params[0]->hasArrayKey()) { $type->type_params[0]->from_docblock = \false; } } else { $all_typehint_types_match = \false; } } if ($all_typehint_types_match) { $new_param_type->from_docblock = \false; } if ($existing_param_type_nullable && !$new_param_type->isNullable()) { $new_param_type->addType(new \Psalm\Type\Atomic\TNull()); } $storage_param->type = $new_param_type; $storage_param->type_location = $docblock_type_location; } $params_without_docblock_type = \array_filter($storage->params, function (\Psalm\Storage\FunctionLikeParameter $p) : bool { return !$p->has_docblock_type && (!$p->type || $p->type->hasArray()); }); if ($params_without_docblock_type) { $storage->unused_docblock_params = $unused_docblock_params; } } private function visitPropertyDeclaration(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property $stmt, \Psalm\Config $config, \Psalm\Storage\ClassLikeStorage $storage, string $fq_classlike_name) : void { if (!$this->fq_classlike_names) { throw new \LogicException('$this->fq_classlike_names should not be empty'); } $comment = $stmt->getDocComment(); $var_comment = null; $property_is_initialized = \false; $existing_constants = $storage->constants; if ($comment && $comment->getText() && ($config->use_docblock_types || $config->use_docblock_property_types)) { if (\preg_match('/[ \\t\\*]+@psalm-suppress[ \\t]+PropertyNotSetInConstructor/', (string) $comment)) { $property_is_initialized = \true; } try { $var_comments = \Psalm\Internal\Analyzer\CommentAnalyzer::getTypeFromComment($comment, $this->file_scanner, $this->aliases, $this->function_template_types + (!$stmt->isStatic() ? $this->class_template_types : []), $this->type_aliases); $var_comment = \array_pop($var_comments); } catch (\Psalm\Exception\IncorrectDocblockException $e) { $storage->docblock_issues[] = new \Psalm\Issue\MissingDocblockType($e->getMessage(), new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); } catch (\Psalm\Exception\DocblockParseException $e) { $storage->docblock_issues[] = new \Psalm\Issue\InvalidDocblock($e->getMessage(), new \Psalm\CodeLocation($this->file_scanner, $stmt, null, \true)); } } $signature_type = null; $signature_type_location = null; if ($stmt->type) { $parser_property_type = $stmt->type; $signature_type = $this->getTypeFromTypeHint($stmt->type); $signature_type_location = new \Psalm\CodeLocation($this->file_scanner, $parser_property_type, null, \false, \Psalm\CodeLocation::FUNCTION_RETURN_TYPE); } $doc_var_group_type = $var_comment ? $var_comment->type : null; if ($doc_var_group_type) { $doc_var_group_type->queueClassLikesForScanning($this->codebase, $this->file_storage); $doc_var_group_type->setFromDocblock(); } foreach ($stmt->props as $property) { $doc_var_location = null; $property_storage = $storage->properties[$property->name->name] = new \Psalm\Storage\PropertyStorage(); $property_storage->is_static = $stmt->isStatic(); $property_storage->type = $signature_type; $property_storage->signature_type = $signature_type; $property_storage->signature_type_location = $signature_type_location; $property_storage->type_location = $signature_type_location; $property_storage->location = new \Psalm\CodeLocation($this->file_scanner, $property->name); $property_storage->stmt_location = new \Psalm\CodeLocation($this->file_scanner, $stmt); $property_storage->has_default = $property->default ? \true : \false; $property_storage->deprecated = $var_comment ? $var_comment->deprecated : \false; $property_storage->internal = $var_comment ? $var_comment->psalm_internal ?? '' : ''; if (!$property_storage->internal && $var_comment && $var_comment->internal) { $property_storage->internal = \Psalm\Internal\Analyzer\NamespaceAnalyzer::getNameSpaceRoot($fq_classlike_name); } $property_storage->readonly = $var_comment ? $var_comment->readonly : \false; $property_storage->allow_private_mutation = $var_comment ? $var_comment->allow_private_mutation : \false; if (!$signature_type && !$doc_var_group_type) { if ($property->default) { $property_storage->suggested_type = \Psalm\Internal\Analyzer\Statements\Expression\SimpleTypeInferer::infer($this->codebase, new \Psalm\Internal\Provider\NodeDataProvider(), $property->default, $this->aliases, null, $existing_constants, $fq_classlike_name); } $property_storage->type = null; } else { if ($var_comment && $var_comment->type_start && $var_comment->type_end && $var_comment->line_number) { $doc_var_location = new \Psalm\CodeLocation\DocblockTypeLocation($this->file_scanner, $var_comment->type_start, $var_comment->type_end, $var_comment->line_number); } if ($doc_var_group_type) { $property_storage->type = \count($stmt->props) === 1 ? $doc_var_group_type : clone $doc_var_group_type; } } if ($property_storage->type && $property_storage->type !== $property_storage->signature_type) { if (!$property_storage->signature_type) { $property_storage->type_location = $doc_var_location; } if ($property_storage->signature_type) { $all_typehint_types_match = \true; $signature_atomic_types = $property_storage->signature_type->getAtomicTypes(); foreach ($property_storage->type->getAtomicTypes() as $key => $type) { if (isset($signature_atomic_types[$key])) { $type->from_docblock = \false; } else { $all_typehint_types_match = \false; } } if ($all_typehint_types_match) { $property_storage->type->from_docblock = \false; } if ($property_storage->signature_type->isNullable() && !$property_storage->type->isNullable()) { $property_storage->type->addType(new \Psalm\Type\Atomic\TNull()); } } $property_storage->type->queueClassLikesForScanning($this->codebase, $this->file_storage); } if ($stmt->isPublic()) { $property_storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC; } elseif ($stmt->isProtected()) { $property_storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED; } elseif ($stmt->isPrivate()) { $property_storage->visibility = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE; } $fq_classlike_name = $this->fq_classlike_names[\count($this->fq_classlike_names) - 1]; $property_id = $fq_classlike_name . '::$' . $property->name->name; $storage->declaring_property_ids[$property->name->name] = $fq_classlike_name; $storage->appearing_property_ids[$property->name->name] = $property_id; if ($property_is_initialized) { $storage->initialized_properties[$property->name->name] = \true; } if (!$stmt->isPrivate()) { $storage->inheritable_property_ids[$property->name->name] = $property_id; } } } private function visitClassConstDeclaration(\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst $stmt, \Psalm\Storage\ClassLikeStorage $storage, string $fq_classlike_name) : void { $existing_constants = $storage->constants; $comment = $stmt->getDocComment(); $deprecated = \false; $config = $this->config; if ($comment && $comment->getText() && ($config->use_docblock_types || $config->use_docblock_property_types)) { $comments = \Psalm\DocComment::parsePreservingLength($comment); if (isset($comments->tags['deprecated'])) { $deprecated = \true; } } foreach ($stmt->consts as $const) { $const_type = \Psalm\Internal\Analyzer\Statements\Expression\SimpleTypeInferer::infer($this->codebase, new \Psalm\Internal\Provider\NodeDataProvider(), $const->value, $this->aliases, null, $existing_constants, $fq_classlike_name); $storage->constants[$const->name->name] = $constant_storage = new \Psalm\Storage\ClassConstantStorage($const_type, $stmt->isProtected() ? \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED : ($stmt->isPrivate() ? \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE : \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC), new \Psalm\CodeLocation($this->file_scanner, $const->name)); $constant_storage->stmt_location = new \Psalm\CodeLocation($this->file_scanner, $const); if ($const_type) { $existing_constants[$const->name->name] = new \Psalm\Storage\ClassConstantStorage($const_type, \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC, null); } else { $unresolved_const_expr = self::getUnresolvedClassConstExpr($const->value, $this->aliases, $fq_classlike_name); if ($unresolved_const_expr) { $constant_storage->unresolved_node = $unresolved_const_expr; } else { $constant_storage->type = \Psalm\Type::getMixed(); } } if ($deprecated) { $constant_storage->deprecated = \true; } } } public static function getUnresolvedClassConstExpr(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr $stmt, \Psalm\Aliases $aliases, string $fq_classlike_name) : ?\Psalm\Internal\Scanner\UnresolvedConstantComponent { if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp) { $left = self::getUnresolvedClassConstExpr($stmt->left, $aliases, $fq_classlike_name); $right = self::getUnresolvedClassConstExpr($stmt->right, $aliases, $fq_classlike_name); if (!$left || !$right) { return null; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Plus) { return new \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedAdditionOp($left, $right); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Minus) { return new \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedSubtractionOp($left, $right); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Mul) { return new \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedMultiplicationOp($left, $right); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Div) { return new \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedDivisionOp($left, $right); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\Concat) { return new \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedConcatOp($left, $right); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\BinaryOp\BitwiseOr) { return new \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedBitwiseOr($left, $right); } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Ternary) { $cond = self::getUnresolvedClassConstExpr($stmt->cond, $aliases, $fq_classlike_name); $if = null; if ($stmt->if) { $if = self::getUnresolvedClassConstExpr($stmt->if, $aliases, $fq_classlike_name); if ($if === null) { $if = \false; } } $else = self::getUnresolvedClassConstExpr($stmt->else, $aliases, $fq_classlike_name); if ($cond && $else && $if !== \false) { return new \Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedTernary($cond, $if, $else); } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch) { if (\strtolower($stmt->name->parts[0]) === 'false') { return new \Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue(\false); } elseif (\strtolower($stmt->name->parts[0]) === 'true') { return new \Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue(\true); } elseif (\strtolower($stmt->name->parts[0]) === 'null') { return new \Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue(null); } elseif ($stmt->name->parts[0] === '__NAMESPACE__') { return new \Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue($aliases->namespace); } return new \Psalm\Internal\Scanner\UnresolvedConstant\Constant(\implode('\\', $stmt->name->parts), $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\MagicConst\Namespace_) { return new \Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue($aliases->namespace); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ArrayDimFetch && $stmt->dim) { $left = self::getUnresolvedClassConstExpr($stmt->var, $aliases, $fq_classlike_name); $right = self::getUnresolvedClassConstExpr($stmt->dim, $aliases, $fq_classlike_name); if ($left && $right) { return new \Psalm\Internal\Scanner\UnresolvedConstant\ArrayOffsetFetch($left, $right); } } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ClassConstFetch) { if ($stmt->class instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Name && $stmt->name instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier && $fq_classlike_name && $stmt->class->parts !== ['static'] && $stmt->class->parts !== ['parent']) { if ($stmt->class->parts === ['self']) { $const_fq_class_name = $fq_classlike_name; } else { $const_fq_class_name = \Psalm\Internal\Analyzer\ClassLikeAnalyzer::getFQCLNFromNameObject($stmt->class, $aliases); } return new \Psalm\Internal\Scanner\UnresolvedConstant\ClassConstant($const_fq_class_name, $stmt->name->name); } return null; } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_ || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber || $stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber) { return new \Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue($stmt->value); } if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_) { $items = []; foreach ($stmt->items as $item) { if ($item === null) { return null; } if ($item->key) { $item_key_type = self::getUnresolvedClassConstExpr($item->key, $aliases, $fq_classlike_name); if (!$item_key_type) { return null; } } else { $item_key_type = null; } $item_value_type = self::getUnresolvedClassConstExpr($item->value, $aliases, $fq_classlike_name); if (!$item_value_type) { return null; } $items[] = new \Psalm\Internal\Scanner\UnresolvedConstant\KeyValuePair($item_key_type, $item_value_type); } return new \Psalm\Internal\Scanner\UnresolvedConstant\ArrayValue($items); } return null; } public function visitInclude(\_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Include_ $stmt) : void { $config = \Psalm\Config::getInstance(); if (!$config->allow_includes) { throw new \Psalm\Exception\FileIncludeException('File includes are not allowed per your Psalm config - check the allowFileIncludes flag.'); } if ($stmt->expr instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_) { $path_to_file = $stmt->expr->value; // attempts to resolve using get_include_path dirs $include_path = \Psalm\Internal\Analyzer\Statements\Expression\IncludeAnalyzer::resolveIncludePath($path_to_file, \dirname($this->file_path)); $path_to_file = $include_path ? $include_path : $path_to_file; if (\DIRECTORY_SEPARATOR === '/') { $is_path_relative = $path_to_file[0] !== \DIRECTORY_SEPARATOR; } else { $is_path_relative = !\preg_match('~^[A-Z]:\\\\~i', $path_to_file); } if ($is_path_relative) { $path_to_file = $config->base_dir . \DIRECTORY_SEPARATOR . $path_to_file; } } else { $path_to_file = \Psalm\Internal\Analyzer\Statements\Expression\IncludeAnalyzer::getPathTo($stmt->expr, null, null, $this->file_path, $this->config); } if ($path_to_file) { $path_to_file = \Psalm\Internal\Analyzer\Statements\Expression\IncludeAnalyzer::normalizeFilePath($path_to_file); if ($this->file_path === $path_to_file) { return; } if ($this->codebase->fileExists($path_to_file)) { if ($this->scan_deep) { $this->codebase->scanner->addFileToDeepScan($path_to_file); } else { $this->codebase->scanner->addFileToShallowScan($path_to_file); } $this->file_storage->required_file_paths[\strtolower($path_to_file)] = $path_to_file; return; } } } public function getFilePath() : string { return $this->file_path; } public function getFileName() : string { return $this->file_scanner->getFileName(); } public function getRootFilePath() : string { return $this->file_scanner->getRootFilePath(); } public function getRootFileName() : string { return $this->file_scanner->getRootFileName(); } public function getAliases() : \Psalm\Aliases { return $this->aliases; } public function afterTraverse(array $nodes) : void { $this->file_storage->type_aliases = $this->type_aliases; } } fake_type_provider = $fake_type_provider; $this->real_type_provider = $real_type_provider; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : void { $origNode = $node; /** @psalm-suppress ArgumentTypeCoercion */ $node_type = $this->fake_type_provider->getType($origNode); if ($node_type) { /** @psalm-suppress ArgumentTypeCoercion */ $this->real_type_provider->setType($origNode, clone $node_type); } } } */ private $matching_trait_nodes = []; private $fq_trait_name; public function __construct(string $fq_trait_name) { $this->fq_trait_name = $fq_trait_name; } /** * @param bool $traverseChildren * * @return int|null */ public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node, &$traverseChildren = \true) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_) { /** @var ?string */ $resolved_name = $node->getAttribute('resolvedName'); if ($resolved_name === null) { // compare ends of names, a temporary hack because PHPParser caches // may not have that attribute $fq_trait_name_parts = \explode('\\', $this->fq_trait_name); /** @psalm-suppress PossiblyNullPropertyFetch */ if ($node->name->name === \end($fq_trait_name_parts)) { $this->matching_trait_nodes[] = $node; } } elseif ($resolved_name === $this->fq_trait_name) { $this->matching_trait_nodes[] = $node; } } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike) { return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN; } return null; } public function getNode() : ?\_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_ { if (!\count($this->matching_trait_nodes)) { return null; } if (\count($this->matching_trait_nodes) === 1 || !\trait_exists($this->fq_trait_name)) { return $this->matching_trait_nodes[0]; } try { $reflection_trait = new \ReflectionClass($this->fq_trait_name); } catch (\Throwable $t) { return null; } foreach ($this->matching_trait_nodes as $node) { if ($node->getLine() === $reflection_trait->getStartLine()) { return $node; } } return null; } } > */ protected $assignment_map = []; /** * @var string|null */ protected $this_class_name; public function __construct(?string $this_class_name) { $this->this_class_name = $this_class_name; } public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : ?int { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Assign) { $left_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getRootVarId($node->var, $this->this_class_name); $right_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getRootVarId($node->expr, $this->this_class_name); if ($left_var_id) { $this->assignment_map[$left_var_id][$right_var_id ?: 'isset'] = \true; } return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN; } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostInc || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PostDec || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreInc || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\PreDec || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\AssignOp) { $var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getRootVarId($node->var, $this->this_class_name); if ($var_id) { $this->assignment_map[$var_id][$var_id] = \true; } return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::DONT_TRAVERSE_CHILDREN; } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\FuncCall) { foreach ($node->args as $arg) { $arg_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getRootVarId($arg->value, $this->this_class_name); if ($arg_var_id) { $this->assignment_map[$arg_var_id][$arg_var_id] = \true; } } } elseif ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Unset_) { foreach ($node->vars as $arg) { $arg_var_id = \Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier::getRootVarId($arg, $this->this_class_name); if ($arg_var_id) { $this->assignment_map[$arg_var_id][$arg_var_id] = \true; } } } return null; } /** * @return array> */ public function getAssignmentMap() : array { return $this->assignment_map; } } */ private $offset_map; /** @var bool */ private $must_rescan = \false; /** @var int */ private $non_method_changes; /** @var string */ private $a_file_contents; /** @var string */ private $b_file_contents; /** @var int */ private $a_file_contents_length; /** @var PhpParser\Parser */ private $parser; /** @var PhpParser\ErrorHandler\Collecting */ private $error_handler; /** @param array $offset_map */ public function __construct(\_HumbugBoxd02f763d3c56\PhpParser\Parser $parser, \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler\Collecting $error_handler, array $offset_map, string $a_file_contents, string $b_file_contents) { $this->parser = $parser; $this->error_handler = $error_handler; $this->offset_map = $offset_map; $this->a_file_contents = $a_file_contents; $this->a_file_contents_length = \strlen($a_file_contents); $this->b_file_contents = $b_file_contents; $this->non_method_changes = \count($offset_map); } /** * @param bool $traverseChildren * * @return null|int|PhpParser\Node */ public function enterNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node, &$traverseChildren = \true) { /** @var array{startFilePos: int, endFilePos: int, startLine: int} */ $attrs = $node->getAttributes(); if ($cs = $node->getComments()) { $stmt_start_pos = $cs[0]->getStartFilePos(); } else { $stmt_start_pos = $attrs['startFilePos']; } $stmt_end_pos = $attrs['endFilePos']; $start_offset = 0; $end_offset = 0; $line_offset = 0; foreach ($this->offset_map as [$a_s, $a_e, $b_s, $b_e, $line_diff]) { if ($a_s > $stmt_end_pos) { break; } $end_offset = $b_e - $a_e; if ($a_s < $stmt_start_pos) { $start_offset = $b_s - $a_s; } if ($a_e < $stmt_start_pos) { $start_offset = $end_offset; $line_offset = $line_diff; continue; } if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_ || $node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod) { if ($a_s >= $stmt_start_pos && $a_e <= $stmt_end_pos) { foreach ($this->offset_map as [$a_s2, $a_e2, $b_s2, $b_e2]) { if ($a_s2 > $stmt_end_pos) { break; } // we have a diff that goes outside the bounds that we care about if ($a_e2 > $stmt_end_pos) { $this->must_rescan = \true; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } $end_offset = $b_e2 - $a_e2; if ($a_s2 < $stmt_start_pos) { $start_offset = $b_s2 - $a_s2; } if ($a_e2 < $stmt_start_pos) { $start_offset = $end_offset; $line_offset = $line_diff; continue; } if ($a_s2 >= $stmt_start_pos && $a_e2 <= $stmt_end_pos) { --$this->non_method_changes; } } $stmt_start_pos += $start_offset; $stmt_end_pos += $end_offset; $current_line = \substr_count(\substr($this->b_file_contents, 0, $stmt_start_pos), "\n"); $method_contents = \substr($this->b_file_contents, $stmt_start_pos, $stmt_end_pos - $stmt_start_pos + 1); if (!$method_contents) { $this->must_rescan = \true; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } $error_handler = new \_HumbugBoxd02f763d3c56\PhpParser\ErrorHandler\Collecting(); $fake_class = 'parser->parse($fake_class, $error_handler) ?: []; if (!$replacement_stmts || !$replacement_stmts[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike || \count($replacement_stmts[0]->stmts) !== 1) { $hacky_class_fix = self::balanceBrackets($fake_class); if ($replacement_stmts && $replacement_stmts[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike && \count($replacement_stmts[0]->stmts) !== 1) { $this->must_rescan = \true; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } // changes "): {" to ") {" $hacky_class_fix = \preg_replace('/(\\)[\\s]*):([\\s]*\\{)/', '$1 $2', $hacky_class_fix); // allows autocompletion $hacky_class_fix = \preg_replace('/(->|::)(\\n\\s*if\\s*\\()/', '~;$2', $hacky_class_fix); if ($hacky_class_fix !== $fake_class) { $replacement_stmts = $this->parser->parse($hacky_class_fix, $error_handler) ?: []; } if (!$replacement_stmts || !$replacement_stmts[0] instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike || \count($replacement_stmts[0]->stmts) > 1) { $this->must_rescan = \true; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } } $replacement_stmts = $replacement_stmts[0]->stmts; $renumbering_traverser = new \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser(); $position_shifter = new \Psalm\Internal\PhpVisitor\OffsetShifterVisitor($stmt_start_pos - 15, $current_line); $renumbering_traverser->addVisitor($position_shifter); $replacement_stmts = $renumbering_traverser->traverse($replacement_stmts); if ($error_handler->hasErrors()) { foreach ($error_handler->getErrors() as $error) { if ($error->hasColumnInfo()) { /** @var array{startFilePos: int, endFilePos: int} */ $error_attrs = $error->getAttributes(); /** @psalm-suppress MixedOperand */ $error = new \_HumbugBoxd02f763d3c56\PhpParser\Error($error->getRawMessage(), ['startFilePos' => $stmt_start_pos + $error_attrs['startFilePos'] - 15, 'endFilePos' => $stmt_start_pos + $error_attrs['endFilePos'] - 15, 'startLine' => $error->getStartLine() + $current_line + $line_offset]); } $this->error_handler->handleError($error); } } $error_handler->clearErrors(); $traverseChildren = \false; return \reset($replacement_stmts); } $this->must_rescan = \true; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } if ($node->stmts) { /** @var int */ $stmt_inner_start_pos = $node->stmts[0]->getAttribute('startFilePos'); /** @var int */ $stmt_inner_end_pos = $node->stmts[\count($node->stmts) - 1]->getAttribute('endFilePos'); if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassLike) { /** @psalm-suppress PossiblyFalseOperand */ $stmt_inner_start_pos = \strrpos($this->a_file_contents, '{', $stmt_inner_start_pos - $this->a_file_contents_length) + 1; if ($stmt_inner_end_pos < $this->a_file_contents_length) { $stmt_inner_end_pos = \strpos($this->a_file_contents, '}', $stmt_inner_end_pos + 1); } } if ($a_s > $stmt_inner_start_pos && $a_e < $stmt_inner_end_pos) { continue; } } } $this->must_rescan = \true; return \_HumbugBoxd02f763d3c56\PhpParser\NodeTraverser::STOP_TRAVERSAL; } if ($start_offset !== 0 || $end_offset !== 0 || $line_offset !== 0) { if ($start_offset !== 0) { if ($cs) { $new_comments = []; foreach ($cs as $c) { if ($c instanceof \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc) { $new_comments[] = new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc($c->getText(), $c->getStartLine() + $line_offset, $c->getStartFilePos() + $start_offset); } else { $new_comments[] = new \_HumbugBoxd02f763d3c56\PhpParser\Comment($c->getText(), $c->getStartLine() + $line_offset, $c->getStartFilePos() + $start_offset); } } $node->setAttribute('comments', $new_comments); /** @psalm-suppress MixedOperand */ $node->setAttribute('startFilePos', $attrs['startFilePos'] + $start_offset); } else { $node->setAttribute('startFilePos', $stmt_start_pos + $start_offset); } } if ($end_offset !== 0) { $node->setAttribute('endFilePos', $stmt_end_pos + $end_offset); } if ($line_offset !== 0) { /** @psalm-suppress MixedOperand */ $node->setAttribute('startLine', $attrs['startLine'] + $line_offset); } return $node; } return null; } public function mustRescan() : bool { return $this->must_rescan || $this->non_method_changes; } /** * @psalm-pure */ private static function balanceBrackets(string $fake_class) : string { $tokens = \token_get_all($fake_class); $brace_count = 0; foreach ($tokens as $token) { if ($token === '{') { ++$brace_count; } elseif ($token === '}') { --$brace_count; } } if ($brace_count > 0) { $fake_class .= \str_repeat('}', $brace_count); } return $fake_class; } } getComments()) { $node->setAttribute('comments', \array_map( /** * @return \_HumbugBoxd02f763d3c56\PhpParser\Comment */ function (\_HumbugBoxd02f763d3c56\PhpParser\Comment $c) : \_HumbugBoxd02f763d3c56\PhpParser\Comment { return clone $c; }, $cs )); } return $node; } } ['falsy'], * '$b' => ['!falsy'], * '$c' => ['!null'], * '$d' => ['string', 'int'] * ] * * representing the formula * * !$a || $b || $c !== null || is_string($d) || is_int($d) * * @var array> */ public $possibilities; /** * An array of things that are not true * [ * '$a' => ['!falsy'], * '$b' => ['falsy'], * '$c' => ['null'], * '$d' => ['!string', '!int'] * ] * represents the formula * * $a && !$b && $c === null && !is_string($d) && !is_int($d) * * @var array>|null */ public $impossibilities; /** @var bool */ public $wedge; /** @var bool */ public $reconcilable; /** @var bool */ public $generated = \false; /** @var array */ public $redefined_vars = []; /** @var string|int */ public $hash; /** * @param array> $possibilities * @param array $redefined_vars */ public function __construct(array $possibilities, int $creating_conditional_id, int $creating_object_id, bool $wedge = \false, bool $reconcilable = \true, bool $generated = \false, array $redefined_vars = []) { $this->possibilities = $possibilities; $this->wedge = $wedge; $this->reconcilable = $reconcilable; $this->generated = $generated; $this->redefined_vars = $redefined_vars; $this->creating_conditional_id = $creating_conditional_id; $this->creating_object_id = $creating_object_id; if ($wedge || !$reconcilable) { $this->hash = ($wedge ? 'w' : '') . $creating_object_id; } else { \ksort($possibilities); foreach ($possibilities as $i => $_) { \sort($possibilities[$i]); } $this->hash = \md5((string) \json_encode($possibilities)); } } public function contains(\Psalm\Internal\Clause $other_clause) : bool { if (\count($other_clause->possibilities) > \count($this->possibilities)) { return \false; } foreach ($other_clause->possibilities as $var => $possible_types) { if (!isset($this->possibilities[$var]) || \count(\array_diff($possible_types, $this->possibilities[$var]))) { return \false; } } return \true; } /** * @psalm-mutation-free */ public function __toString() : string { $clause_strings = \array_map( /** * @param string $var_id * @param non-empty-list $values * * @return string */ function ($var_id, $values) : string { $var_id_clauses = \array_map( /** * @param string $value * * @return string */ function ($value) use($var_id) : string { if ($value === 'falsy') { return '!' . $var_id; } if ($value === '!falsy') { return $var_id; } $negate = \false; if ($value[0] === '!') { $negate = \true; $value = \substr($value, 1); } if ($value[0] === '=') { $value = \substr($value, 1); } if ($negate) { return $var_id . ' is not ' . $value; } return $var_id . ' is ' . $value; }, $values ); if (\count($var_id_clauses) > 1) { return '(' . \implode(') || (', $var_id_clauses) . ')'; } return $var_id_clauses[0]; }, \array_keys($this->possibilities), \array_values($this->possibilities) ); if (\count($clause_strings) > 1) { return '(' . \implode(') || (', $clause_strings) . ')'; } return \reset($clause_strings); } public function makeUnique() : self { $possibilities = $this->possibilities; foreach ($possibilities as $var_id => $var_possibilities) { $possibilities[$var_id] = \array_values(\array_unique($var_possibilities)); } return new self($possibilities, $this->creating_conditional_id, $this->creating_object_id, $this->wedge, $this->reconcilable, $this->generated, $this->redefined_vars); } public function removePossibilities(string $var_id) : ?self { $possibilities = $this->possibilities; unset($possibilities[$var_id]); if (!$possibilities) { return null; } return new self($possibilities, $this->creating_conditional_id, $this->creating_object_id, $this->wedge, $this->reconcilable, $this->generated, $this->redefined_vars); } /** * @param non-empty-list $clause_var_possibilities */ public function addPossibilities(string $var_id, array $clause_var_possibilities) : self { $possibilities = $this->possibilities; $possibilities[$var_id] = $clause_var_possibilities; return new self($possibilities, $this->creating_conditional_id, $this->creating_object_id, $this->wedge, $this->reconcilable, $this->generated, $this->redefined_vars); } public function calculateNegation() : self { if ($this->impossibilities !== null) { return $this; } $impossibilities = []; foreach ($this->possibilities as $var_id => $possibility) { $impossibility = []; foreach ($possibility as $type) { if ($type[0] !== '=' && $type[0] !== '~' && (!isset($type[1]) || $type[1] !== '=' && $type[1] !== '~') || \strpos($type, '(') || \strpos($type, 'getclass-')) { $impossibility[] = \Psalm\Type\Algebra::negateType($type); } } if ($impossibility) { $impossibilities[$var_id] = $impossibility; } } $clause = clone $this; $clause->impossibilities = $impossibilities; return $clause; } } stopTraversal = \false; } /** * Recursively traverse a node. * * @param Node $node node to traverse * * @return Node Result of traversal (may be original node or new one) */ protected function traverseNode(\_HumbugBoxd02f763d3c56\PhpParser\Node $node) : \_HumbugBoxd02f763d3c56\PhpParser\Node { foreach ($node->getSubNodeNames() as $name) { $subNode =& $node->{$name}; if (\is_array($subNode)) { $subNode = $this->traverseArray($subNode); if ($this->stopTraversal) { break; } } elseif ($subNode instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $traverseChildren = \true; foreach ($this->visitors as $visitor) { $return = $visitor->enterNode($subNode, $traverseChildren); if (null !== $return) { if ($return instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $subNode = $return; } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = \false; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = \true; break 2; } else { throw new \LogicException('enterNode() returned invalid value of type ' . \gettype($return)); } } } if ($traverseChildren) { $subNode = $this->traverseNode($subNode); if ($this->stopTraversal) { break; } } foreach ($this->visitors as $visitor) { $return = $visitor->leaveNode($subNode); if (null !== $return) { if ($return instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $subNode = $return; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = \true; break 2; } elseif (\is_array($return)) { throw new \LogicException('leaveNode() may only return an array ' . 'if the parent structure is an array'); } else { throw new \LogicException('leaveNode() returned invalid value of type ' . \gettype($return)); } } } } } return $node; } /** * Recursively traverse array (usually of nodes). * * @param array $nodes Array to traverse * * @return array Result of traversal (may be original array or changed one) */ protected function traverseArray(array $nodes) : array { $doNodes = []; foreach ($nodes as $i => &$node) { if ($node instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $traverseChildren = \true; foreach ($this->visitors as $visitor) { $return = $visitor->enterNode($node, $traverseChildren); if (null !== $return) { if ($return instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $node = $return; } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = \false; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = \true; break 2; } else { throw new \LogicException('enterNode() returned invalid value of type ' . \gettype($return)); } } } if ($traverseChildren) { $node = $this->traverseNode($node); if ($this->stopTraversal) { break; } } foreach ($this->visitors as $visitor) { $return = $visitor->leaveNode($node); if (null !== $return) { if ($return instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node) { $node = $return; } elseif (\is_array($return)) { $doNodes[] = [$i, $return]; break; } elseif (self::REMOVE_NODE === $return) { $doNodes[] = [$i, []]; break; } elseif (self::STOP_TRAVERSAL === $return) { $this->stopTraversal = \true; break 2; } elseif (\false === $return) { throw new \LogicException('bool(false) return from leaveNode() no longer supported. ' . 'Return NodeTraverser::REMOVE_NODE instead'); } else { throw new \LogicException('leaveNode() returned invalid value of type ' . \gettype($return)); } } } } elseif (\is_array($node)) { throw new \LogicException('Invalid node structure: Contains nested arrays'); } } if (!empty($doNodes)) { while (list($i, $replace) = \array_pop($doNodes)) { \array_splice($nodes, $i, 1, $replace); } } return $nodes; } } fq_class_name = $fq_class_name; $this->method_name = $method_name; } /** * Takes any valid reference to a method id and converts * it into a MethodIdentifier * * @param string|MethodIdentifier $method_id * * @psalm-pure */ public static function wrap($method_id) : self { return \is_string($method_id) ? static::fromMethodIdReference($method_id) : $method_id; } /** * @psalm-pure */ public static function isValidMethodIdReference(string $method_id) : bool { return \strpos($method_id, '::') !== \false; } /** * @psalm-pure */ public static function fromMethodIdReference(string $method_id) : self { if (!static::isValidMethodIdReference($method_id)) { throw new \InvalidArgumentException('Invalid method id reference provided: ' . $method_id); } // remove trailing backslash if it exists $method_id = \preg_replace('/^\\\\/', '', $method_id); $method_id_parts = \explode('::', $method_id); return new self($method_id_parts[0], \strtolower($method_id_parts[1])); } /** @return non-empty-string */ public function __toString() : string { return $this->fq_class_name . '::' . $this->method_name; } } fq_classlike_name = $fq_classlike_name; } protected function enterNode(\Psalm\Type\TypeNode $type) : ?int { if ($type instanceof \Psalm\Type\Atomic\TNamedObject) { if (\strtolower($type->value) === $this->fq_classlike_name) { $this->contains_classlike = \true; return \Psalm\Type\NodeVisitor::STOP_TRAVERSAL; } } if ($type instanceof \Psalm\Type\Atomic\TScalarClassConstant) { if (\strtolower($type->fq_classlike_name) === $this->fq_classlike_name) { $this->contains_classlike = \true; return \Psalm\Type\NodeVisitor::STOP_TRAVERSAL; } } if ($type instanceof \Psalm\Type\Atomic\TLiteralClassString) { if (\strtolower($type->value) === $this->fq_classlike_name) { $this->contains_classlike = \true; return \Psalm\Type\NodeVisitor::STOP_TRAVERSAL; } } return null; } public function matches() : bool { return $this->contains_classlike; } } from_docblock = \true; if ($type instanceof \Psalm\Type\Atomic\TTemplateParam && $type->as->isMixed()) { return \Psalm\Type\NodeVisitor::DONT_TRAVERSE_CHILDREN; } return null; } } $phantom_classes */ public function __construct(\Psalm\Internal\Codebase\Scanner $scanner, ?\Psalm\Storage\FileStorage $file_storage, array $phantom_classes) { $this->scanner = $scanner; $this->file_storage = $file_storage; $this->phantom_classes = $phantom_classes; } protected function enterNode(\Psalm\Type\TypeNode $type) : ?int { if ($type instanceof \Psalm\Type\Atomic\TNamedObject) { $fq_classlike_name_lc = \strtolower($type->value); if (!isset($this->phantom_classes[$type->value]) && !isset($this->phantom_classes[$fq_classlike_name_lc])) { $this->scanner->queueClassLikeForScanning($type->value, \false, !$type->from_docblock, $this->phantom_classes); if ($this->file_storage) { $this->file_storage->referenced_classlikes[$fq_classlike_name_lc] = $type->value; } } } if ($type instanceof \Psalm\Type\Atomic\TScalarClassConstant) { $this->scanner->queueClassLikeForScanning($type->fq_classlike_name, \false, !$type->from_docblock, $this->phantom_classes); if ($this->file_storage) { $fq_classlike_name_lc = \strtolower($type->fq_classlike_name); $this->file_storage->referenced_classlikes[$fq_classlike_name_lc] = $type->fq_classlike_name; } } if ($type instanceof \Psalm\Type\Atomic\TLiteralClassString) { $this->scanner->queueClassLikeForScanning($type->value, \false, !$type->from_docblock, $this->phantom_classes); if ($this->file_storage) { $fq_classlike_name_lc = \strtolower($type->value); $this->file_storage->referenced_classlikes[$fq_classlike_name_lc] = $type->value; } } return null; } } */ private $template_types = []; protected function enterNode(\Psalm\Type\TypeNode $type) : ?int { if ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { $this->template_types[] = $type; } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParamClass) { $extends = $type->as_type; $this->template_types[] = new \Psalm\Type\Atomic\TTemplateParam($type->param_name, $extends ? new \Psalm\Type\Union([$extends]) : \Psalm\Type::getMixed(), $type->defining_class); } elseif ($type instanceof \Psalm\Type\Atomic\TConditional) { $this->template_types[] = new \Psalm\Type\Atomic\TTemplateParam($type->param_name, \Psalm\Type::getMixed(), $type->defining_class); } return null; } /** * @return list */ public function getTemplateTypes() : array { return $this->template_types; } } */ private $suppressed_issues; /** * @var array */ private $phantom_classes; /** * @var bool */ private $inferred; /** * @var bool */ private $inherited; /** * @var bool */ private $prevent_template_covariance; /** @var bool */ private $has_errors = \false; private $calling_method_id; /** * @param array $suppressed_issues * @param array $phantom_classes */ public function __construct(\Psalm\StatementsSource $source, \Psalm\CodeLocation $code_location, array $suppressed_issues, array $phantom_classes = [], bool $inferred = \true, bool $inherited = \false, bool $prevent_template_covariance = \false, ?string $calling_method_id = null) { $this->source = $source; $this->code_location = $code_location; $this->suppressed_issues = $suppressed_issues; $this->phantom_classes = $phantom_classes; $this->inferred = $inferred; $this->inherited = $inherited; $this->prevent_template_covariance = $prevent_template_covariance; $this->calling_method_id = $calling_method_id; } /** * @psalm-suppress MoreSpecificImplementedParamType * * @param \Psalm\Type\Atomic|\Psalm\Type\Union $type */ protected function enterNode(\Psalm\Type\TypeNode $type) : ?int { if ($type->checked) { return \Psalm\Type\NodeVisitor::DONT_TRAVERSE_CHILDREN; } if ($type instanceof \Psalm\Type\Atomic\TNamedObject) { $this->checkNamedObject($type); } elseif ($type instanceof \Psalm\Type\Atomic\TScalarClassConstant) { $this->checkScalarClassConstant($type); } elseif ($type instanceof \Psalm\Type\Atomic\TTemplateParam) { $this->checkTemplateParam($type); } elseif ($type instanceof \Psalm\Type\Atomic\TResource) { $this->checkResource($type); } elseif ($type instanceof \Psalm\Type\Atomic\TArray) { if (\count($type->type_params) > 2) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooManyTemplateParams($type->getId() . ' has too many template params, expecting 2', $this->code_location), $this->suppressed_issues)) { // fall through } } } $type->checked = \true; return null; } public function hasErrors() : bool { return $this->has_errors; } private function checkNamedObject(\Psalm\Type\Atomic\TNamedObject $atomic) : void { $codebase = $this->source->getCodebase(); if ($this->code_location instanceof \Psalm\CodeLocation\DocblockTypeLocation && $codebase->store_node_types && $atomic->offset_start !== null && $atomic->offset_end !== null) { $codebase->analyzer->addOffsetReference($this->source->getFilePath(), $this->code_location->raw_file_start + $atomic->offset_start, $this->code_location->raw_file_start + $atomic->offset_end, $atomic->value); } if (!isset($this->phantom_classes[\strtolower($atomic->value)]) && \Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($this->source, $atomic->value, $this->code_location, $this->source->getFQCLN(), $this->calling_method_id, $this->suppressed_issues, $this->inferred, \false, \true, $atomic->from_docblock) === \false) { $this->has_errors = \true; return; } $fq_class_name_lc = \strtolower($atomic->value); if (!$this->inherited && $codebase->classlike_storage_provider->has($fq_class_name_lc) && $this->source->getFQCLN() !== $atomic->value) { $class_storage = $codebase->classlike_storage_provider->get($fq_class_name_lc); if ($class_storage->deprecated) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\DeprecatedClass('Class ' . $atomic->value . ' is marked as deprecated', $this->code_location, $atomic->value), $this->source->getSuppressedIssues() + $this->suppressed_issues)) { // fall through } } } if ($atomic instanceof \Psalm\Type\Atomic\TGenericObject) { $this->checkGenericParams($atomic); } } private function checkGenericParams(\Psalm\Type\Atomic\TGenericObject $atomic) : void { $codebase = $this->source->getCodebase(); try { $class_storage = $codebase->classlike_storage_provider->get(\strtolower($atomic->value)); } catch (\InvalidArgumentException $e) { return; } $expected_type_params = $class_storage->template_types ?: []; $expected_param_covariants = $class_storage->template_covariants; $template_type_count = \count($expected_type_params); $template_param_count = \count($atomic->type_params); if ($template_type_count > $template_param_count) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\MissingTemplateParam($atomic->value . ' has missing template params, expecting ' . $template_type_count, $this->code_location), $this->suppressed_issues)) { // fall through } } elseif ($template_type_count < $template_param_count) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\TooManyTemplateParams($atomic->getId() . ' has too many template params, expecting ' . $template_type_count, $this->code_location), $this->suppressed_issues)) { // fall through } } foreach ($atomic->type_params as $i => $type_param) { $this->prevent_template_covariance = $this->source instanceof \Psalm\Internal\Analyzer\MethodAnalyzer && $this->source->getMethodName() !== '__construct' && empty($expected_param_covariants[$i]); if (isset(\array_values($expected_type_params)[$i])) { $expected_type_param = \reset(\array_values($expected_type_params)[$i])[0]; $expected_type_param = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $expected_type_param, $this->source->getFQCLN(), $this->source->getFQCLN(), $this->source->getParentFQCLN()); $template_name = \array_keys($expected_type_params)[$i]; $type_param = \Psalm\Internal\Type\TypeExpander::expandUnion($codebase, $type_param, $this->source->getFQCLN(), $this->source->getFQCLN(), $this->source->getParentFQCLN()); if (!\Psalm\Internal\Type\Comparator\UnionTypeComparator::isContainedBy($codebase, $type_param, $expected_type_param)) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidTemplateParam('Extended template param ' . $template_name . ' of ' . $atomic->getId() . ' expects type ' . $expected_type_param->getId() . ', type ' . $type_param->getId() . ' given', $this->code_location), $this->suppressed_issues)) { // fall through } } } } } public function checkScalarClassConstant(\Psalm\Type\Atomic\TScalarClassConstant $atomic) : void { $fq_classlike_name = $atomic->fq_classlike_name === 'self' ? $this->source->getClassName() : $atomic->fq_classlike_name; if (!$fq_classlike_name) { return; } if (\Psalm\Internal\Analyzer\ClassLikeAnalyzer::checkFullyQualifiedClassLikeName($this->source, $fq_classlike_name, $this->code_location, null, null, $this->suppressed_issues, $this->inferred, \false, \true, $atomic->from_docblock) === \false) { $this->has_errors = \true; return; } $const_name = $atomic->const_name; if (\strpos($const_name, '*') !== \false) { $expanded = \Psalm\Internal\Type\TypeExpander::expandAtomic($this->source->getCodebase(), $atomic, $fq_classlike_name, $fq_classlike_name, null, \true, \true); $is_defined = \is_array($expanded) && \count($expanded) > 0; } else { $class_constant_type = $this->source->getCodebase()->classlikes->getClassConstantType($fq_classlike_name, $atomic->const_name, \ReflectionProperty::IS_PRIVATE, null); $is_defined = null !== $class_constant_type; } if (!$is_defined) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\UndefinedConstant('Constant ' . $fq_classlike_name . '::' . $const_name . ' is not defined', $this->code_location), $this->source->getSuppressedIssues())) { // fall through } } } public function checkTemplateParam(\Psalm\Type\Atomic\TTemplateParam $atomic) : void { if ($this->prevent_template_covariance && \substr($atomic->defining_class, 0, 3) !== 'fn-') { $codebase = $this->source->getCodebase(); $class_storage = $codebase->classlike_storage_provider->get($atomic->defining_class); $template_offset = $class_storage->template_types ? \array_search($atomic->param_name, \array_keys($class_storage->template_types), \true) : \false; if ($template_offset !== \false && isset($class_storage->template_covariants[$template_offset]) && $class_storage->template_covariants[$template_offset]) { $method_storage = $this->source instanceof \Psalm\Internal\Analyzer\MethodAnalyzer ? $this->source->getFunctionLikeStorage() : null; if ($method_storage instanceof \Psalm\Storage\MethodStorage && $method_storage->mutation_free && !$method_storage->mutation_free_inferred) { // do nothing } else { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\InvalidTemplateParam('Template param ' . $atomic->param_name . ' of ' . $atomic->defining_class . ' is marked covariant and cannot be used here', $this->code_location), $this->source->getSuppressedIssues())) { // fall through } } } } } public function checkResource(\Psalm\Type\Atomic\TResource $atomic) : void { if (!$atomic->from_docblock) { if (\Psalm\IssueBuffer::accepts(new \Psalm\Issue\ReservedWord('\'resource\' is a reserved word', $this->code_location, 'resource'), $this->source->getSuppressedIssues())) { // fall through } } } } getAll() as $storage) { if (\strpos($storage->name, 'Psalm\\') === 0) { continue; } if ($storage->location && \strpos($storage->location->file_path, $psalm_base) === 0) { continue; } if ($storage->stubbed) { continue; } $name_parts = \explode('\\', $storage->name); $classlike_name = \array_pop($name_parts); $namespace_name = \implode('\\', $name_parts); if (!isset($namespaced_nodes[$namespace_name])) { $namespaced_nodes[$namespace_name] = []; } $namespaced_nodes[$namespace_name][$classlike_name] = \Psalm\Internal\Stubs\Generator\ClassLikeStubGenerator::getClassLikeNode($codebase, $storage, $classlike_name); } $all_function_names = []; foreach ($codebase->functions->getAllStubbedFunctions() as $function_storage) { if ($function_storage->location && \strpos($function_storage->location->file_path, $psalm_base) === 0) { continue; } if (!$function_storage->cased_name) { throw new \UnexpectedValueException('very bad'); } $fq_name = $function_storage->cased_name; $all_function_names[$fq_name] = \true; $name_parts = \explode('\\', $fq_name); $function_name = \array_pop($name_parts); $namespace_name = \implode('\\', $name_parts); $namespaced_nodes[$namespace_name][$fq_name] = self::getFunctionNode($function_storage, $function_name, $namespace_name); } foreach ($codebase->getAllStubbedConstants() as $fq_name => $type) { if ($type->isMixed()) { continue; } $name_parts = \explode('\\', $fq_name); $constant_name = \array_pop($name_parts); $namespace_name = \implode('\\', $name_parts); $namespaced_nodes[$namespace_name][$fq_name] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_([new \_HumbugBoxd02f763d3c56\PhpParser\Node\Const_($constant_name, self::getExpressionFromType($type))]); } foreach ($file_provider->getAll() as $file_storage) { if (\strpos($file_storage->file_path, $psalm_base) === 0) { continue; } foreach ($file_storage->functions as $function_storage) { if (!$function_storage->cased_name) { continue; } $fq_name = $function_storage->cased_name; if (isset($all_function_names[$fq_name])) { continue; } $all_function_names[$fq_name] = \true; $name_parts = \explode('\\', $fq_name); $function_name = \array_pop($name_parts); $namespace_name = \implode('\\', $name_parts); $namespaced_nodes[$namespace_name][$fq_name] = self::getFunctionNode($function_storage, $function_name, $namespace_name); } foreach ($file_storage->constants as $fq_name => $type) { if ($type->isMixed()) { continue; } if ($type->isMixed()) { continue; } $name_parts = \explode('\\', $fq_name); $constant_name = \array_pop($name_parts); $namespace_name = \implode('\\', $name_parts); $namespaced_nodes[$namespace_name][$fq_name] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Const_([new \_HumbugBoxd02f763d3c56\PhpParser\Node\Const_($constant_name, self::getExpressionFromType($type))]); } } \ksort($namespaced_nodes); $namespace_stmts = []; foreach ($namespaced_nodes as $namespace_name => $stmts) { \ksort($stmts); $namespace_stmts[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_($namespace_name ? new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name($namespace_name) : null, \array_values($stmts), ['kind' => \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Namespace_::KIND_BRACED]); } $prettyPrinter = new \_HumbugBoxd02f763d3c56\PhpParser\PrettyPrinter\Standard(); return $prettyPrinter->prettyPrintFile($namespace_stmts); } private static function getFunctionNode(\Psalm\Storage\FunctionLikeStorage $function_storage, string $function_name, string $namespace_name) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_ { $docblock = new \Psalm\Internal\Scanner\ParsedDocblock('', []); foreach ($function_storage->template_types ?: [] as $template_name => $map) { $type = \array_values($map)[0][0]; $docblock->tags['template'][] = $template_name . ' as ' . $type->toNamespacedString($namespace_name, [], null, \false); } foreach ($function_storage->params as $param) { if ($param->type && $param->type !== $param->signature_type) { $docblock->tags['param'][] = $param->type->toNamespacedString($namespace_name, [], null, \false) . ' $' . $param->name; } } if ($function_storage->return_type && $function_storage->signature_return_type !== $function_storage->return_type) { $docblock->tags['return'][] = $function_storage->return_type->toNamespacedString($namespace_name, [], null, \false); } foreach ($function_storage->throws ?: [] as $exception_name => $_) { $docblock->tags['throws'][] = \Psalm\Type::getStringFromFQCLN($exception_name, $namespace_name, [], null, \false); } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Function_($function_name, ['params' => self::getFunctionParamNodes($function_storage), 'returnType' => $function_storage->signature_return_type ? self::getParserTypeFromPsalmType($function_storage->signature_return_type) : null, 'stmts' => []], ['comments' => $docblock->tags ? [new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc(\rtrim($docblock->render(' ')))] : []]); } /** * @return list */ public static function getFunctionParamNodes(\Psalm\Storage\FunctionLikeStorage $method_storage) : array { $param_nodes = []; foreach ($method_storage->params as $param) { $param_nodes[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Param(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable($param->name), $param->default_type ? self::getExpressionFromType($param->default_type) : null, $param->signature_type ? self::getParserTypeFromPsalmType($param->signature_type) : null, $param->by_ref, $param->is_variadic); } return $param_nodes; } /** * @return PhpParser\Node\Identifier|PhpParser\Node\Name\FullyQualified|PhpParser\Node\NullableType|null */ public static function getParserTypeFromPsalmType(\Psalm\Type\Union $type) : ?\_HumbugBoxd02f763d3c56\PhpParser\NodeAbstract { $nullable = $type->isNullable(); foreach ($type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TNull) { continue; } if ($atomic_type instanceof \Psalm\Type\Atomic\Scalar || $atomic_type instanceof \Psalm\Type\Atomic\TObject || $atomic_type instanceof \Psalm\Type\Atomic\TArray || $atomic_type instanceof \Psalm\Type\Atomic\TIterable) { $identifier_string = $atomic_type->toPhpString(null, [], null, 8, 0); if ($identifier_string === null) { throw new \UnexpectedValueException($atomic_type->getId() . ' could not be converted to an identifier'); } $identifier = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Identifier($identifier_string); if ($nullable) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType($identifier); } return $identifier; } if ($atomic_type instanceof \Psalm\Type\Atomic\TNamedObject) { $name_node = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($atomic_type->value); if ($nullable) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\NullableType($name_node); } return $name_node; } } return null; } public static function getExpressionFromType(\Psalm\Type\Union $type) : \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr { foreach ($type->getAtomicTypes() as $atomic_type) { if ($atomic_type instanceof \Psalm\Type\Atomic\TLiteralString) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_($atomic_type->value); } if ($atomic_type instanceof \Psalm\Type\Atomic\TLiteralInt) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\LNumber($atomic_type->value); } if ($atomic_type instanceof \Psalm\Type\Atomic\TLiteralFloat) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\DNumber($atomic_type->value); } if ($atomic_type instanceof \Psalm\Type\Atomic\TFalse) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('false')); } if ($atomic_type instanceof \Psalm\Type\Atomic\TTrue) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('true')); } if ($atomic_type instanceof \Psalm\Type\Atomic\TNull) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\ConstFetch(new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name('null')); } if ($atomic_type instanceof \Psalm\Type\Atomic\TArray) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Array_([]); } } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Scalar\String_('Psalm could not infer this type'); } } \array_merge(self::getConstantNodes($codebase, $storage), self::getPropertyNodes($storage), self::getMethodNodes($storage))]; $docblock = new \Psalm\Internal\Scanner\ParsedDocblock('', []); $template_offset = 0; foreach ($storage->template_types ?: [] as $template_name => $map) { $type = \array_values($map)[0][0]; $key = isset($storage->template_covariants[$template_offset]) ? 'template-covariant' : 'template'; $docblock->tags[$key][] = $template_name . ' as ' . $type->toNamespacedString(null, [], null, \false); $template_offset++; } $attrs = ['comments' => $docblock->tags ? [new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc(\rtrim($docblock->render(' ')))] : []]; if ($storage->is_interface) { if ($storage->direct_interface_parents) { $subnodes['extends'] = []; foreach ($storage->direct_interface_parents as $direct_interface_parent) { $subnodes['extends'][] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($direct_interface_parent); } } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Interface_($classlike_name, $subnodes, $attrs); } if ($storage->is_trait) { return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Trait_($classlike_name, $subnodes, $attrs); } if ($storage->parent_class) { $subnodes['extends'] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($storage->parent_class); } else { if ($storage->direct_class_interfaces) { $subnodes['implements'] = []; foreach ($storage->direct_class_interfaces as $direct_class_interface) { $subnodes['implements'][] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Name\FullyQualified($direct_class_interface); } } } return new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_($classlike_name, $subnodes, $attrs); } /** * @return list */ private static function getConstantNodes(\Psalm\Codebase $codebase, \Psalm\Storage\ClassLikeStorage $storage) : array { $constant_nodes = []; foreach ($storage->constants as $constant_name => $constant_storage) { if ($constant_storage->unresolved_node) { $type = new \Psalm\Type\Union([\Psalm\Internal\Codebase\ConstantTypeResolver::resolve($codebase->classlikes, $constant_storage->unresolved_node)]); } elseif ($constant_storage->type) { $type = $constant_storage->type; } else { throw new \UnexpectedValueException('bad'); } $constant_nodes[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassConst([new \_HumbugBoxd02f763d3c56\PhpParser\Node\Const_($constant_name, \Psalm\Internal\Stubs\Generator\StubsGenerator::getExpressionFromType($type))], $constant_storage->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PUBLIC ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC : ($constant_storage->visibility === \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED : \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE)); } return $constant_nodes; } /** * @return list */ private static function getPropertyNodes(\Psalm\Storage\ClassLikeStorage $storage) : array { $namespace_name = \implode('\\', \array_slice(\explode('\\', $storage->name), 0, -1)); $property_nodes = []; foreach ($storage->properties as $property_name => $property_storage) { switch ($property_storage->visibility) { case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE: $flag = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE; break; case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED: $flag = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED; break; default: $flag = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC; break; } $docblock = new \Psalm\Internal\Scanner\ParsedDocblock('', []); if ($property_storage->type && $property_storage->signature_type !== $property_storage->type) { $docblock->tags['var'][] = $property_storage->type->toNamespacedString($namespace_name, [], null, \false); } $property_nodes[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property($flag | ($property_storage->is_static ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC : 0), [new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\PropertyProperty($property_name, $property_storage->suggested_type ? \Psalm\Internal\Stubs\Generator\StubsGenerator::getExpressionFromType($property_storage->suggested_type) : null)], ['comments' => $docblock->tags ? [new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc(\rtrim($docblock->render(' ')))] : []], $property_storage->signature_type ? \Psalm\Internal\Stubs\Generator\StubsGenerator::getParserTypeFromPsalmType($property_storage->signature_type) : null); } return $property_nodes; } /** * @return list */ private static function getMethodNodes(\Psalm\Storage\ClassLikeStorage $storage) : array { $namespace_name = \implode('\\', \array_slice(\explode('\\', $storage->name), 0, -1)); $method_nodes = []; foreach ($storage->methods as $method_storage) { if (!$method_storage->cased_name) { throw new \UnexpectedValueException('very bad'); } switch ($method_storage->visibility) { case \ReflectionProperty::IS_PRIVATE: $flag = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE; break; case \ReflectionProperty::IS_PROTECTED: $flag = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED; break; default: $flag = \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC; break; } $docblock = new \Psalm\Internal\Scanner\ParsedDocblock('', []); foreach ($method_storage->template_types ?: [] as $template_name => $map) { $type = \array_values($map)[0][0]; $docblock->tags['template'][] = $template_name . ' as ' . $type->toNamespacedString($namespace_name, [], null, \false); } foreach ($method_storage->params as $param) { if ($param->type && $param->type !== $param->signature_type) { $docblock->tags['param'][] = $param->type->toNamespacedString($namespace_name, [], null, \false) . ' $' . $param->name; } } if ($method_storage->return_type && $method_storage->signature_return_type !== $method_storage->return_type) { $docblock->tags['return'][] = $method_storage->return_type->toNamespacedString($namespace_name, [], null, \false); } foreach ($method_storage->throws ?: [] as $exception_name => $_) { $docblock->tags['throws'][] = \Psalm\Type::getStringFromFQCLN($exception_name, $namespace_name, [], null, \false); } $method_nodes[] = new \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\ClassMethod($method_storage->cased_name, ['flags' => $flag | ($method_storage->is_static ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_STATIC : 0) | ($method_storage->abstract ? \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT : 0), 'params' => \Psalm\Internal\Stubs\Generator\StubsGenerator::getFunctionParamNodes($method_storage), 'returnType' => $method_storage->signature_return_type ? \Psalm\Internal\Stubs\Generator\StubsGenerator::getParserTypeFromPsalmType($method_storage->signature_return_type) : null, 'stmts' => $storage->is_interface || $method_storage->abstract ? null : []], ['comments' => $docblock->tags ? [new \_HumbugBoxd02f763d3c56\PhpParser\Comment\Doc(\rtrim($docblock->render(' ')))] : []]); } return $method_nodes; } } > $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. * @param \Closure $startup_closure * A closure to execute upon starting a child * @param \Closure(int, mixed):mixed $task_closure * A method to execute on each task data. * This closure must return an array (to be gathered). * @param \Closure():mixed $shutdown_closure * A closure to execute upon shutting down a child * @param ?\Closure(mixed $data):void $task_done_closure * A closure to execute when a task is done * * @psalm-suppress MixedAssignment */ public function __construct(array $process_task_data_iterator, \Closure $startup_closure, \Closure $task_closure, \Closure $shutdown_closure, ?\Closure $task_done_closure = null) { $pool_size = \count($process_task_data_iterator); $this->task_done_closure = $task_done_closure; \assert($pool_size > 1, 'The pool size must be >= 2 to use the fork pool.'); if (!\extension_loaded('pcntl') || !\extension_loaded('posix')) { echo 'The pcntl & posix extensions must be loaded in order for Psalm to be able to use multiple processes.' . \PHP_EOL; exit(1); } $disabled_functions = \array_map('trim', \explode(',', \ini_get('disable_functions'))); if (\in_array('pcntl_fork', $disabled_functions)) { echo "pcntl_fork() is disabled by php configuration (disable_functions directive).\n" . "Please enable it or run Psalm single-threaded with --threads=1 cli switch.\n"; exit(1); } if (\ini_get('pcre.jit') === '1' && \PHP_OS === 'Darwin' && \version_compare(\PHP_VERSION, '7.3.0') >= 0 && \version_compare(\PHP_VERSION, '7.4.0') < 0) { die(self::MAC_PCRE_MESSAGE . \PHP_EOL); } // We'll keep track of if this is the parent process // so that we can tell who will be doing the waiting $is_parent = \false; $sockets = []; // Fork as many times as requested to get the given // pool size for ($proc_id = 0; $proc_id < $pool_size; ++$proc_id) { // Create an IPC socket pair. $sockets = \stream_socket_pair(\STREAM_PF_UNIX, \STREAM_SOCK_STREAM, \STREAM_IPPROTO_IP); if (!$sockets) { \error_log('unable to create stream socket pair'); exit(self::EXIT_FAILURE); } // Fork if (($pid = \pcntl_fork()) < 0) { \error_log(\posix_strerror(\posix_get_last_error())); exit(self::EXIT_FAILURE); } // Parent if ($pid > 0) { $is_parent = \true; $this->child_pid_list[] = $pid; $this->read_streams[] = self::streamForParent($sockets); continue; } // Child if ($pid === 0) { $is_parent = \false; break; } } // If we're the parent, return if ($is_parent) { return; } // Get the write stream for the child. $write_stream = self::streamForChild($sockets); // Execute anything the children wanted to execute upon // starting up $startup_closure(); // Get the work for this process $task_data_iterator = \array_values($process_task_data_iterator)[$proc_id]; $task_done_buffer = ''; try { foreach ($task_data_iterator as $i => $task_data) { $task_result = $task_closure($i, $task_data); $task_done_message = new \Psalm\Internal\Fork\ForkTaskDoneMessage($task_result); $serialized_message = $task_done_buffer . \base64_encode(\serialize($task_done_message)) . "\n"; if (\strlen($serialized_message) > 200) { $bytes_written = @\fwrite($write_stream, $serialized_message); if (\strlen($serialized_message) !== $bytes_written) { $task_done_buffer = \substr($serialized_message, $bytes_written); } else { $task_done_buffer = ''; } } else { $task_done_buffer = $serialized_message; } } // Execute each child's shutdown closure before // exiting the process $results = $shutdown_closure(); // Serialize this child's produced results and send them to the parent. $process_done_message = new \Psalm\Internal\Fork\ForkProcessDoneMessage($results ?: []); } catch (\Throwable $t) { // This can happen when developing Psalm from source without running `composer update`, // or because of rare bugs in Psalm. /** @psalm-suppress MixedArgument on Windows, for some reason */ $process_done_message = new \Psalm\Internal\Fork\ForkProcessErrorMessage($t->getMessage() . "\nStack trace in the forked worker:\n" . $t->getTraceAsString()); } $serialized_message = $task_done_buffer . \base64_encode(\serialize($process_done_message)) . "\n"; $bytes_to_write = \strlen($serialized_message); $bytes_written = 0; while ($bytes_written < $bytes_to_write) { // attempt to write the remaining unsent part $bytes_written += @\fwrite($write_stream, \substr($serialized_message, $bytes_written)); if ($bytes_written < $bytes_to_write) { // wait a bit \usleep(500000); } } \fclose($write_stream); // Children exit after completing their work exit(self::EXIT_SUCCESS); } /** * Prepare the socket pair to be used in a parent process and * return the stream the parent will use to read results. * * @param resource[] $sockets the socket pair for IPC * * @return resource */ private static function streamForParent(array $sockets) { [$for_read, $for_write] = $sockets; // The parent will not use the write channel, so it // must be closed to prevent deadlock. \fclose($for_write); // stream_select will be used to read multiple streams, so these // must be set to non-blocking mode. if (!\stream_set_blocking($for_read, \false)) { \error_log('unable to set read stream to non-blocking'); exit(self::EXIT_FAILURE); } return $for_read; } /** * Prepare the socket pair to be used in a child process and return * the stream the child will use to write results. * * @param resource[] $sockets the socket pair for IPC * * @return resource */ private static function streamForChild(array $sockets) { [$for_read, $for_write] = $sockets; // The while will not use the read channel, so it must // be closed to prevent deadlock. \fclose($for_read); return $for_write; } /** * Read the results that each child process has serialized on their write streams. * The results are returned in an array, one for each worker. The order of the results * is not maintained. * * * @psalm-suppress MixedAssignment * * @return list */ private function readResultsFromChildren() : array { // Create an array of all active streams, indexed by // resource id. $streams = []; foreach ($this->read_streams as $stream) { $streams[\intval($stream)] = $stream; } // Create an array for the content received on each stream, // indexed by resource id. $content = \array_fill_keys(\array_keys($streams), ''); $terminationMessages = []; // Read the data off of all the stream. while (\count($streams) > 0) { $needs_read = \array_values($streams); $needs_write = null; $needs_except = null; // Wait for data on at least one stream. $num = @\stream_select($needs_read, $needs_write, $needs_except, null); if ($num === \false) { $err = \error_get_last(); // stream_select returns false when the `select` system call is interrupted by an incoming signal if (isset($err['message']) && \stripos($err['message'], 'interrupted system call') === \false) { \error_log('unable to select on read stream'); exit(self::EXIT_FAILURE); } continue; } // For each stream that was ready, read the content. foreach ($needs_read as $file) { $buffer = \fread($file, 1024); if ($buffer !== \false) { $content[\intval($file)] .= $buffer; } if (\strpos($buffer, "\n") !== \false) { $serialized_messages = \explode("\n", $content[\intval($file)]); $content[\intval($file)] = \array_pop($serialized_messages); foreach ($serialized_messages as $serialized_message) { $message = \unserialize(\base64_decode($serialized_message, \true)); if ($message instanceof \Psalm\Internal\Fork\ForkProcessDoneMessage) { $terminationMessages[] = $message->data; } elseif ($message instanceof \Psalm\Internal\Fork\ForkTaskDoneMessage) { if ($this->task_done_closure !== null) { ($this->task_done_closure)($message->data); } } elseif ($message instanceof \Psalm\Internal\Fork\ForkProcessErrorMessage) { throw new \Exception($message->message); } else { \error_log('Child should return ForkMessage - response type=' . \gettype($message)); $this->did_have_error = \true; } } } // If the stream has closed, stop trying to select on it. if (\feof($file)) { if ($content[\intval($file)] !== '') { \error_log('Child did not send full message before closing the connection'); $this->did_have_error = \true; } \fclose($file); unset($streams[\intval($file)]); } } } return \array_values($terminationMessages); } /** * Wait for all child processes to complete * * @return list */ public function wait() : array { // Read all the streams from child processes into an array. $content = $this->readResultsFromChildren(); // Wait for all children to return foreach ($this->child_pid_list as $child_pid) { $process_lookup = \posix_kill($child_pid, 0); $status = 0; if ($process_lookup) { /** * @psalm-suppress UndefinedConstant - does not exist on windows * @psalm-suppress MixedArgument */ \posix_kill($child_pid, \SIGALRM); if (\pcntl_waitpid($child_pid, $status) < 0) { \error_log(\posix_strerror(\posix_get_last_error())); } } // Check to see if the child died a graceful death if (\pcntl_wifsignaled($status)) { $return_code = \pcntl_wexitstatus($status); $term_sig = \pcntl_wtermsig($status); /** * @psalm-suppress UndefinedConstant - does not exist on windows */ if ($term_sig !== \SIGALRM) { $this->did_have_error = \true; \error_log("Child terminated with return code {$return_code} and signal {$term_sig}"); } } } return $content; } /** * Returns true if this had an error, e.g. due to memory limits or due to a child process crashing. * */ public function didHaveError() : bool { return $this->did_have_error; } } message = $message; } } data = $data; } } disabledExtensions[] = $disabledExtension; } /** * @param mixed $isLoaded */ protected function requiresRestart($isLoaded) : bool { $this->required = (bool) \array_filter($this->disabledExtensions, function (string $extension) : bool { return \extension_loaded($extension); }); return $isLoaded || $this->required; } /** * @param mixed $command */ protected function restart($command) : void { if ($this->required && $this->tmpIni) { $regex = '/^\\s*(extension\\s*=.*(' . \implode('|', $this->disabledExtensions) . ').*)$/mi'; $content = \file_get_contents($this->tmpIni); $content = \preg_replace($regex, ';$1', $content); \file_put_contents($this->tmpIni, $content); } /** @psalm-suppress MixedArgument */ parent::restart($command); } } data = $data; } } > */ private static $manipulators = []; /** @var Property */ private $stmt; /** @var int */ private $docblock_start; /** @var int */ private $docblock_end; /** @var null|int */ private $typehint_start; /** @var int */ private $typehint_area_start; /** @var null|int */ private $typehint_end; /** @var null|string */ private $new_php_type; /** @var bool */ private $type_is_php_compatible = \false; /** @var null|string */ private $new_phpdoc_type; /** @var null|string */ private $new_psalm_type; /** @var string */ private $indentation; /** @var bool */ private $add_newline = \false; /** @var string|null */ private $type_description; public static function getForProperty(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, string $file_path, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property $stmt) : self { if (isset(self::$manipulators[$file_path][$stmt->getLine()])) { return self::$manipulators[$file_path][$stmt->getLine()]; } $manipulator = self::$manipulators[$file_path][$stmt->getLine()] = new self($project_analyzer, $stmt, $file_path); return $manipulator; } private function __construct(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Property $stmt, string $file_path) { $this->stmt = $stmt; $docblock = $stmt->getDocComment(); $this->docblock_start = $docblock ? $docblock->getStartFilePos() : (int) $stmt->getAttribute('startFilePos'); $this->docblock_end = (int) $stmt->getAttribute('startFilePos'); $codebase = $project_analyzer->getCodebase(); $file_contents = $codebase->getFileContents($file_path); if (\count($stmt->props) > 1) { throw new \UnexpectedValueException('Cannot replace multiple inline properties in ' . $file_path); } $prop = $stmt->props[0]; if ($stmt->type) { $this->typehint_start = (int) $stmt->type->getAttribute('startFilePos'); $this->typehint_end = (int) $stmt->type->getAttribute('endFilePos'); } $this->typehint_area_start = (int) $prop->getAttribute('startFilePos') - 1; $preceding_newline_pos = \strrpos($file_contents, "\n", $this->docblock_end - \strlen($file_contents)); if ($preceding_newline_pos === \false) { $this->indentation = ''; return; } if (!$docblock) { $preceding_semicolon_pos = \strrpos($file_contents, ";", $preceding_newline_pos - \strlen($file_contents)); if ($preceding_semicolon_pos) { $preceding_space = \substr($file_contents, $preceding_semicolon_pos + 1, $preceding_newline_pos - $preceding_semicolon_pos - 1); if (!\substr_count($preceding_space, "\n")) { $this->add_newline = \true; } } } $first_line = \substr($file_contents, $preceding_newline_pos + 1, $this->docblock_end - $preceding_newline_pos); $this->indentation = \str_replace(\ltrim($first_line), '', $first_line); } public function setType(?string $php_type, string $new_type, string $phpdoc_type, bool $is_php_compatible, ?string $description = null) : void { $new_type = \str_replace(['', '', ''], '', $new_type); $this->new_php_type = $php_type; $this->new_phpdoc_type = $phpdoc_type; $this->new_psalm_type = $new_type; $this->type_is_php_compatible = $is_php_compatible; $this->type_description = $description; } /** * Gets a new docblock given the existing docblock, if one exists, and the updated return types * and/or parameters * */ private function getDocblock() : string { $docblock = $this->stmt->getDocComment(); if ($docblock) { $parsed_docblock = \Psalm\DocComment::parsePreservingLength($docblock); } else { $parsed_docblock = new \Psalm\Internal\Scanner\ParsedDocblock('', []); } $modified_docblock = \false; $old_phpdoc_type = null; if (isset($parsed_docblock->tags['var'])) { $old_phpdoc_type = \array_shift($parsed_docblock->tags['var']); } if ($this->new_phpdoc_type && $this->new_phpdoc_type !== $old_phpdoc_type) { $modified_docblock = \true; $parsed_docblock->tags['var'] = [$this->new_phpdoc_type . ($this->type_description ? ' ' . $this->type_description : '')]; } $old_psalm_type = null; if (isset($parsed_docblock->tags['psalm-var'])) { $old_psalm_type = \array_shift($parsed_docblock->tags['psalm-var']); } if ($this->new_psalm_type && $this->new_phpdoc_type !== $this->new_psalm_type && $this->new_psalm_type !== $old_psalm_type) { $modified_docblock = \true; $parsed_docblock->tags['psalm-var'] = [$this->new_psalm_type]; } if (!$parsed_docblock->tags && !$parsed_docblock->description) { return ''; } if (!$modified_docblock) { return (string) $docblock . "\n" . $this->indentation; } return $parsed_docblock->render($this->indentation); } /** * @return array */ public static function getManipulationsForFile(string $file_path) : array { if (!isset(self::$manipulators[$file_path])) { return []; } $file_manipulations = []; foreach (self::$manipulators[$file_path] as $manipulator) { if ($manipulator->new_php_type) { if ($manipulator->typehint_start && $manipulator->typehint_end) { $file_manipulations[$manipulator->typehint_start] = new \Psalm\FileManipulation($manipulator->typehint_start, $manipulator->typehint_end, $manipulator->new_php_type); } else { $file_manipulations[$manipulator->typehint_area_start] = new \Psalm\FileManipulation($manipulator->typehint_area_start, $manipulator->typehint_area_start, ' ' . $manipulator->new_php_type); } } elseif ($manipulator->new_php_type === '' && $manipulator->new_phpdoc_type && $manipulator->typehint_start && $manipulator->typehint_end) { $file_manipulations[$manipulator->typehint_start] = new \Psalm\FileManipulation($manipulator->typehint_start, $manipulator->typehint_end, ''); } if (!$manipulator->new_php_type || !$manipulator->type_is_php_compatible || $manipulator->docblock_start !== $manipulator->docblock_end) { $file_manipulations[$manipulator->docblock_start] = new \Psalm\FileManipulation($manipulator->docblock_start - ($manipulator->add_newline ? \strlen($manipulator->indentation) : 0), $manipulator->docblock_end, ($manipulator->add_newline ? "\n" . $manipulator->indentation : '') . $manipulator->getDocblock()); } } return $file_manipulations; } public static function clearCache() : void { self::$manipulators = []; } } > */ private static $manipulators = []; /** @var Closure|Function_|ClassMethod|ArrowFunction */ private $stmt; /** @var int */ private $docblock_start; /** @var int */ private $docblock_end; /** @var int */ private $return_typehint_area_start; /** @var null|int */ private $return_typehint_colon_start; /** @var null|int */ private $return_typehint_start; /** @var null|int */ private $return_typehint_end; /** @var null|string */ private $new_php_return_type; /** @var bool */ private $return_type_is_php_compatible = \false; /** @var null|string */ private $new_phpdoc_return_type; /** @var null|string */ private $new_psalm_return_type; /** @var array */ private $new_php_param_types = []; /** @var array */ private $new_phpdoc_param_types = []; /** @var array */ private $new_psalm_param_types = []; /** @var string */ private $indentation; /** @var string|null */ private $return_type_description; /** @var array */ private $param_offsets = []; /** @var array */ private $param_typehint_offsets = []; /** @var bool */ private $is_pure = \false; /** * @param Closure|Function_|ClassMethod|ArrowFunction $stmt */ public static function getForFunction(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, string $file_path, \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $stmt) : \Psalm\Internal\FileManipulation\FunctionDocblockManipulator { if (isset(self::$manipulators[$file_path][$stmt->getLine()])) { return self::$manipulators[$file_path][$stmt->getLine()]; } $manipulator = self::$manipulators[$file_path][$stmt->getLine()] = new self($file_path, $stmt, $project_analyzer); return $manipulator; } /** * @param Closure|Function_|ClassMethod|ArrowFunction $stmt */ private function __construct(string $file_path, \_HumbugBoxd02f763d3c56\PhpParser\Node\FunctionLike $stmt, \Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer) { $this->stmt = $stmt; $docblock = $stmt->getDocComment(); $this->docblock_start = $docblock ? $docblock->getStartFilePos() : (int) $stmt->getAttribute('startFilePos'); $this->docblock_end = $function_start = (int) $stmt->getAttribute('startFilePos'); $function_end = (int) $stmt->getAttribute('endFilePos'); foreach ($stmt->params as $param) { if ($param->var instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Variable && \is_string($param->var->name)) { $this->param_offsets[$param->var->name] = (int) $param->getAttribute('startFilePos'); if ($param->type) { $this->param_typehint_offsets[$param->var->name] = [(int) $param->type->getAttribute('startFilePos'), (int) $param->type->getAttribute('endFilePos')]; } } } $codebase = $project_analyzer->getCodebase(); $file_contents = $codebase->getFileContents($file_path); $last_arg_position = $stmt->params ? (int) $stmt->params[\count($stmt->params) - 1]->getAttribute('endFilePos') + 1 : null; if ($stmt instanceof \_HumbugBoxd02f763d3c56\PhpParser\Node\Expr\Closure && $stmt->uses) { $last_arg_position = (int) $stmt->uses[\count($stmt->uses) - 1]->getAttribute('endFilePos') + 1; } $end_bracket_position = (int) \strpos($file_contents, ')', $last_arg_position ?: $function_start); $this->return_typehint_area_start = $end_bracket_position + 1; $function_code = \substr($file_contents, $function_start, $function_end); $function_code_after_bracket = \substr($function_code, $end_bracket_position + 1 - $function_start); // do a little parsing here $chars = \str_split($function_code_after_bracket); $in_single_line_comment = $in_multi_line_comment = \false; for ($i = 0, $iMax = \count($chars); $i < $iMax; ++$i) { $char = $chars[$i]; switch ($char) { case "\n": $in_single_line_comment = \false; continue 2; case ':': if ($in_multi_line_comment || $in_single_line_comment) { continue 2; } $this->return_typehint_colon_start = $i + $end_bracket_position + 1; continue 2; case '/': if ($in_multi_line_comment || $in_single_line_comment) { continue 2; } if ($chars[$i + 1] === '*') { $in_multi_line_comment = \true; ++$i; } if ($chars[$i + 1] === '/') { $in_single_line_comment = \true; ++$i; } continue 2; case '*': if ($in_single_line_comment) { continue 2; } if ($chars[$i + 1] === '/') { $in_multi_line_comment = \false; ++$i; } continue 2; case '{': if ($in_multi_line_comment || $in_single_line_comment) { continue 2; } break 2; case '?': if ($in_multi_line_comment || $in_single_line_comment) { continue 2; } $this->return_typehint_start = $i + $end_bracket_position + 1; break; } if ($in_multi_line_comment || $in_single_line_comment) { continue; } if ($chars[$i] === '\\' || \preg_match('/\\w/', $char)) { if ($this->return_typehint_start === null) { $this->return_typehint_start = $i + $end_bracket_position + 1; } if ($chars[$i + 1] !== '\\' && !\preg_match('/[\\w]/', $chars[$i + 1])) { $this->return_typehint_end = $i + $end_bracket_position + 2; break; } } } $preceding_newline_pos = \strrpos($file_contents, "\n", $this->docblock_end - \strlen($file_contents)); if ($preceding_newline_pos === \false) { $this->indentation = ''; return; } $first_line = \substr($file_contents, $preceding_newline_pos + 1, $this->docblock_end - $preceding_newline_pos); $this->indentation = \str_replace(\ltrim($first_line), '', $first_line); } /** * Sets the new return type * */ public function setReturnType(?string $php_type, string $new_type, string $phpdoc_type, bool $is_php_compatible, ?string $description) : void { $new_type = \str_replace(['', ''], '', $new_type); $this->new_php_return_type = $php_type; $this->new_phpdoc_return_type = $phpdoc_type; $this->new_psalm_return_type = $new_type; $this->return_type_is_php_compatible = $is_php_compatible; $this->return_type_description = $description; } /** * Sets a new param type * * @param bool $is_php_compatible * */ public function setParamType(string $param_name, ?string $php_type, string $new_type, string $phpdoc_type) : void { $new_type = \str_replace(['', '', ''], '', $new_type); if ($php_type) { $this->new_php_param_types[$param_name] = $php_type; } if ($php_type !== $new_type) { $this->new_phpdoc_param_types[$param_name] = $phpdoc_type; $this->new_psalm_param_types[$param_name] = $new_type; } } /** * Gets a new docblock given the existing docblock, if one exists, and the updated return types * and/or parameters * */ private function getDocblock() : string { $docblock = $this->stmt->getDocComment(); if ($docblock) { $parsed_docblock = \Psalm\DocComment::parsePreservingLength($docblock); } else { $parsed_docblock = new \Psalm\Internal\Scanner\ParsedDocblock('', []); } $modified_docblock = \false; foreach ($this->new_phpdoc_param_types as $param_name => $phpdoc_type) { $found_in_params = \false; $new_param_block = $phpdoc_type . ' ' . '$' . $param_name; if (isset($parsed_docblock->tags['param'])) { foreach ($parsed_docblock->tags['param'] as &$param_block) { $doc_parts = \Psalm\Internal\Analyzer\CommentAnalyzer::splitDocLine($param_block); if (($doc_parts[1] ?? null) === '$' . $param_name) { if ($param_block !== $new_param_block) { $modified_docblock = \true; } $param_block = $new_param_block; $found_in_params = \true; break; } } } if (!$found_in_params) { $modified_docblock = \true; $parsed_docblock->tags['param'][] = $new_param_block; } } $old_phpdoc_return_type = null; if (isset($parsed_docblock->tags['return'])) { $old_phpdoc_return_type = \reset($parsed_docblock->tags['return']); } if ($this->is_pure) { $modified_docblock = \true; $parsed_docblock->tags['psalm-pure'] = ['']; } if ($this->new_phpdoc_return_type && $this->new_phpdoc_return_type !== $old_phpdoc_return_type) { $modified_docblock = \true; $parsed_docblock->tags['return'] = [$this->new_phpdoc_return_type . ($this->return_type_description ? ' ' . $this->return_type_description : '')]; } $old_psalm_return_type = null; if (isset($parsed_docblock->tags['psalm-return'])) { $old_psalm_return_type = \reset($parsed_docblock->tags['psalm-return']); } if ($this->new_psalm_return_type && $this->new_phpdoc_return_type !== $this->new_psalm_return_type && $this->new_psalm_return_type !== $old_psalm_return_type) { $modified_docblock = \true; $parsed_docblock->tags['psalm-return'] = [$this->new_psalm_return_type]; } if (!$parsed_docblock->tags && !$parsed_docblock->description) { return ''; } if (!$modified_docblock) { return (string) $docblock . "\n" . $this->indentation; } return $parsed_docblock->render($this->indentation); } /** * @return array */ public static function getManipulationsForFile(string $file_path) : array { if (!isset(self::$manipulators[$file_path])) { return []; } $file_manipulations = []; foreach (self::$manipulators[$file_path] as $manipulator) { if ($manipulator->new_php_return_type) { if ($manipulator->return_typehint_start && $manipulator->return_typehint_end) { $file_manipulations[$manipulator->return_typehint_start] = new \Psalm\FileManipulation($manipulator->return_typehint_start, $manipulator->return_typehint_end, $manipulator->new_php_return_type); } else { $file_manipulations[$manipulator->return_typehint_area_start] = new \Psalm\FileManipulation($manipulator->return_typehint_area_start, $manipulator->return_typehint_area_start, ': ' . $manipulator->new_php_return_type); } } elseif ($manipulator->new_php_return_type === '' && $manipulator->return_typehint_colon_start && $manipulator->new_phpdoc_return_type && $manipulator->return_typehint_start && $manipulator->return_typehint_end) { $file_manipulations[$manipulator->return_typehint_start] = new \Psalm\FileManipulation($manipulator->return_typehint_colon_start, $manipulator->return_typehint_end, ''); } if (!$manipulator->new_php_return_type || !$manipulator->return_type_is_php_compatible || $manipulator->docblock_start !== $manipulator->docblock_end || $manipulator->is_pure) { $file_manipulations[$manipulator->docblock_start] = new \Psalm\FileManipulation($manipulator->docblock_start, $manipulator->docblock_end, $manipulator->getDocblock()); } foreach ($manipulator->new_php_param_types as $param_name => $new_php_param_type) { if (!isset($manipulator->param_offsets[$param_name])) { continue; } $param_offset = $manipulator->param_offsets[$param_name]; $typehint_offsets = $manipulator->param_typehint_offsets[$param_name] ?? null; if ($new_php_param_type) { if ($typehint_offsets) { $file_manipulations[$typehint_offsets[0]] = new \Psalm\FileManipulation($typehint_offsets[0], $typehint_offsets[1], $new_php_param_type); } else { $file_manipulations[$param_offset] = new \Psalm\FileManipulation($param_offset, $param_offset, $new_php_param_type . ' '); } } elseif ($new_php_param_type === '' && $typehint_offsets) { $file_manipulations[$typehint_offsets[0]] = new \Psalm\FileManipulation($typehint_offsets[0], $param_offset, ''); } } } return $file_manipulations; } public function makePure() : void { $this->is_pure = \true; } public static function clearCache() : void { self::$manipulators = []; } /** * @param array> $manipulators */ public static function addManipulators(array $manipulators) : void { self::$manipulators = \array_merge($manipulators, self::$manipulators); } /** * @return array> */ public static function getManipulators() : array { return self::$manipulators; } } */ private static $file_manipulations = []; /** @var CodeMigration[] */ private static $code_migrations = []; /** * @param FileManipulation[] $file_manipulations * */ public static function add(string $file_path, array $file_manipulations) : void { if (!isset(self::$file_manipulations[$file_path])) { self::$file_manipulations[$file_path] = []; } foreach ($file_manipulations as $file_manipulation) { self::$file_manipulations[$file_path][$file_manipulation->getKey()] = $file_manipulation; } } /** @param CodeMigration[] $code_migrations */ public static function addCodeMigrations(array $code_migrations) : void { self::$code_migrations = \array_merge(self::$code_migrations, $code_migrations); } /** * @return array{int, int} */ private static function getCodeOffsets(string $source_file_path, int $source_start, int $source_end) : array { if (!isset(self::$file_manipulations[$source_file_path])) { return [0, 0]; } $start_offset = 0; $middle_offset = 0; foreach (self::$file_manipulations[$source_file_path] as $fm) { $offset = \strlen($fm->insertion_text) - $fm->end + $fm->start; if ($fm->end < $source_start) { $start_offset += $offset; $middle_offset += $offset; } elseif ($fm->start > $source_start && $fm->end < $source_end) { $middle_offset += $offset; } } return [$start_offset, $middle_offset]; } public static function addForCodeLocation(\Psalm\CodeLocation $code_location, string $replacement_text, bool $swallow_newlines = \false) : void { $bounds = $code_location->getSnippetBounds(); if ($swallow_newlines) { $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); $file_contents = $codebase->getFileContents($code_location->file_path); if (($file_contents[$bounds[0] - 1] ?? null) === "\n" && ($file_contents[$bounds[0] - 2] ?? null) === "\n") { $bounds[0] -= 2; } } self::add($code_location->file_path, [new \Psalm\FileManipulation($bounds[0], $bounds[1], $replacement_text)]); } public static function addVarAnnotationToRemove(\Psalm\CodeLocation\DocblockTypeLocation $code_location) : void { $bounds = $code_location->getSelectionBounds(); $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); $file_contents = $codebase->getFileContents($code_location->file_path); $comment_start = \strrpos($file_contents, '/**', $bounds[0] - \strlen($file_contents)); if ($comment_start === \false) { return; } $comment_end = \strpos($file_contents, '*/', $bounds[1]); if ($comment_end === \false) { return; } $comment_end += 2; $comment_text = \substr($file_contents, $comment_start, $comment_end - $comment_start); $var_type_comment_start = $bounds[0] - $comment_start; $var_type_comment_end = $bounds[1] - $comment_start; $var_start = \strrpos($comment_text, '@var', $var_type_comment_start - \strlen($comment_text)); $var_end = \strpos($comment_text, "\n", $var_type_comment_end); if ($var_start && $var_end) { $var_start = \strrpos($comment_text, "\n", $var_start - \strlen($comment_text)) ?: $var_start; $comment_text = \substr_replace($comment_text, '', $var_start, $var_end - $var_start); if (\preg_match('@^/\\*\\*\\n(\\s*\\*\\s*\\n)*\\s*\\*?\\*/$@', $comment_text)) { $comment_text = ''; } } else { $comment_text = ''; } self::add($code_location->file_path, [new \Psalm\FileManipulation($comment_start, $comment_end, $comment_text, \false, $comment_text === '')]); } /** * @return FileManipulation[] */ public static function getManipulationsForFile(string $file_path) : array { if (!isset(self::$file_manipulations[$file_path])) { return []; } return self::$file_manipulations[$file_path]; } /** * @param string $file_path * * @return array */ public static function getMigrationManipulations(\Psalm\Internal\Provider\FileProvider $file_provider) : array { $code_migration_manipulations = []; foreach (self::$code_migrations as $code_migration) { [$start_offset, $middle_offset] = self::getCodeOffsets($code_migration->source_file_path, $code_migration->source_start, $code_migration->source_end); if (!isset($code_migration_manipulations[$code_migration->source_file_path])) { $code_migration_manipulations[$code_migration->source_file_path] = []; } if (!isset($code_migration_manipulations[$code_migration->destination_file_path])) { $code_migration_manipulations[$code_migration->destination_file_path] = []; } $delete_file_manipulation = new \Psalm\FileManipulation($code_migration->source_start + $start_offset, $code_migration->source_end + $middle_offset, ''); $code_migration_manipulations[$code_migration->source_file_path][] = $delete_file_manipulation; [$destination_start_offset] = self::getCodeOffsets($code_migration->destination_file_path, $code_migration->destination_start, $code_migration->destination_start); $manipulation = new \Psalm\FileManipulation($code_migration->destination_start + $destination_start_offset, $code_migration->destination_start + $destination_start_offset, "\n" . \substr($file_provider->getContents($code_migration->source_file_path), $delete_file_manipulation->start, $delete_file_manipulation->end - $delete_file_manipulation->start) . "\n"); $code_migration_manipulations[$code_migration->destination_file_path][$manipulation->getKey()] = $manipulation; } return $code_migration_manipulations; } /** * @return array */ public static function getAll() : array { return self::$file_manipulations; } public static function clearCache() : void { self::$file_manipulations = []; self::$code_migrations = []; } } > */ private static $manipulators = []; /** @var Class_ */ private $stmt; /** @var int */ private $docblock_start; /** @var int */ private $docblock_end; /** @var bool */ private $immutable = \false; /** @var string */ private $indentation; public static function getForClass(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, string $file_path, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ $stmt) : self { if (isset(self::$manipulators[$file_path][$stmt->getLine()])) { return self::$manipulators[$file_path][$stmt->getLine()]; } $manipulator = self::$manipulators[$file_path][$stmt->getLine()] = new self($project_analyzer, $stmt, $file_path); return $manipulator; } private function __construct(\Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer, \_HumbugBoxd02f763d3c56\PhpParser\Node\Stmt\Class_ $stmt, string $file_path) { $this->stmt = $stmt; $docblock = $stmt->getDocComment(); $this->docblock_start = $docblock ? $docblock->getStartFilePos() : (int) $stmt->getAttribute('startFilePos'); $this->docblock_end = (int) $stmt->getAttribute('startFilePos'); $codebase = $project_analyzer->getCodebase(); $file_contents = $codebase->getFileContents($file_path); $preceding_newline_pos = (int) \strrpos($file_contents, "\n", $this->docblock_end - \strlen($file_contents)); $first_line = \substr($file_contents, $preceding_newline_pos + 1, $this->docblock_end - $preceding_newline_pos); $this->indentation = \str_replace(\ltrim($first_line), '', $first_line); } public function makeImmutable() : void { $this->immutable = \true; } /** * Gets a new docblock given the existing docblock, if one exists, and the updated return types * and/or parameters * */ private function getDocblock() : string { $docblock = $this->stmt->getDocComment(); if ($docblock) { $parsed_docblock = \Psalm\DocComment::parsePreservingLength($docblock); } else { $parsed_docblock = new \Psalm\Internal\Scanner\ParsedDocblock('', []); } $modified_docblock = \false; if ($this->immutable) { $modified_docblock = \true; $parsed_docblock->tags['psalm-immutable'] = ['']; } if (!$modified_docblock) { return (string) $docblock . "\n" . $this->indentation; } return $parsed_docblock->render($this->indentation); } /** * @return array */ public static function getManipulationsForFile(string $file_path) : array { if (!isset(self::$manipulators[$file_path])) { return []; } $file_manipulations = []; foreach (self::$manipulators[$file_path] as $manipulator) { if ($manipulator->immutable) { $file_manipulations[$manipulator->docblock_start] = new \Psalm\FileManipulation($manipulator->docblock_start, $manipulator->docblock_end, $manipulator->getDocblock()); } } return $file_manipulations; } public static function clearCache() : void { self::$manipulators = []; } } source_file_path = $source_file_path; $this->source_start = $source_start; $this->source_end = $source_end; $this->destination_file_path = $destination_file_path; $this->destination_start = $destination_start; } } |null */ public $new_vars = null; /** * @var array */ public $new_vars_possibly_in_scope = []; /** * @var array|null */ public $redefined_vars = null; /** * @var array|null */ public $assigned_var_ids = null; /** * @var array */ public $possibly_assigned_var_ids = []; /** * @var array */ public $possibly_redefined_vars = []; /** * @var array */ public $updated_vars = []; /** * @var array>> */ public $negated_types = []; /** * @var array */ public $if_cond_changed_var_ids = []; /** * @var array|null */ public $negatable_if_types = null; /** * @var list */ public $negated_clauses = []; /** * These are the set of clauses that could be applied after the `if` * statement, if the `if` statement contains branches with leaving statements, * and the else leaves too * * @var list */ public $reasonable_clauses = []; /** * Variables that were mixed, but are no longer * * @var array|null */ public $possible_param_types = null; /** * @var string[] */ public $final_actions = []; /** * @var ?\Psalm\Context */ public $mic_drop_context; } */ public $cond_referenced_var_ids; /** * @var array */ public $cond_assigned_var_ids; /** @var list<\Psalm\Internal\Clause> */ public $entry_clauses; /** * @param array $cond_referenced_var_ids * @param array $cond_assigned_var_ids * @param list<\Psalm\Internal\Clause> $entry_clauses */ public function __construct(\Psalm\Context $if_context, \Psalm\Context $original_context, array $cond_referenced_var_ids, array $cond_assigned_var_ids, array $entry_clauses) { $this->if_context = $if_context; $this->original_context = $original_context; $this->cond_referenced_var_ids = $cond_referenced_var_ids; $this->cond_assigned_var_ids = $cond_assigned_var_ids; $this->entry_clauses = $entry_clauses; } } |null */ public $break_vars; public function __construct(\Psalm\Context $parent_context) { $this->parent_context = $parent_context; } public function __destruct() { /** @psalm-suppress PossiblyNullPropertyAssignmentValue */ $this->parent_context = null; } } */ public $vars_in_scope = []; /** * @param array $vars_in_scope */ public function __construct(array $vars_in_scope) { $this->vars_in_scope = $vars_in_scope; } } |null */ public $new_vars_in_scope = null; /** * @var array */ public $new_vars_possibly_in_scope = []; /** * @var array|null */ public $redefined_vars = null; /** * @var array|null */ public $possibly_redefined_vars = null; /** * @var array */ public $leftover_statements = []; /** * @var PhpParser\Node\Expr|null */ public $leftover_case_equality_expr = null; /** * @var list */ public $negated_clauses = []; /** * @var array|null */ public $new_assigned_var_ids = null; } |null */ public $redefined_loop_vars = []; /** * @var array */ public $possibly_redefined_loop_vars = []; /** * @var array|null */ public $possibly_redefined_loop_parent_vars = null; /** * @var array */ public $possibly_defined_loop_parent_vars = []; /** * @var array */ public $vars_possibly_in_scope = []; /** * @var array */ public $protected_var_ids = []; /** * @var string[] */ public $final_actions = []; public function __construct(\Psalm\Context $loop_context, \Psalm\Context $parent_context) { $this->loop_context = $loop_context; $this->loop_parent_context = $parent_context; } public function __destruct() { $this->loop_context = null; $this->loop_parent_context = null; } } counter++; } } handler = $handler; $this->mapper = $mapper; } /** * Diagnostics notification are sent from the server to the client to signal results of validation runs. * * @param Diagnostic[] $diagnostics * * @return Promise */ public function publishDiagnostics(string $uri, array $diagnostics) : \_HumbugBoxd02f763d3c56\Amp\Promise { return $this->handler->notify('textDocument/publishDiagnostics', ['uri' => $uri, 'diagnostics' => $diagnostics]); } /** * The content request is sent from a server to a client * to request the current content of a text document identified by the URI * * @param TextDocumentIdentifier $textDocument The document to get the content for * * @return Promise The document's current content */ public function xcontent(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentIdentifier $textDocument) : \_HumbugBoxd02f763d3c56\Amp\Promise { return \_HumbugBoxd02f763d3c56\Amp\call( /** * @return \Generator, object, TextDocumentItem> */ function () use($textDocument) { /** @var Promise */ $promise = $this->handler->request('textDocument/xcontent', ['textDocument' => $textDocument]); $result = (yield $promise); /** @var TextDocumentItem */ return $this->mapper->map($result, new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentItem()); } ); } } */ protected $listeners = []; /** * Subscribe to an event. */ public function on(string $eventName, callable $callBack, int $priority = 100) : void { if (!isset($this->listeners[$eventName])) { $this->listeners[$eventName] = [ \true, // If there's only one item, it's sorted [$priority], [$callBack], ]; } else { $this->listeners[$eventName][0] = \false; // marked as unsorted $this->listeners[$eventName][1][] = $priority; $this->listeners[$eventName][2][] = $callBack; } } /** * Emits an event. * * This method will return true if 0 or more listeners were successfully * handled. false is returned if one of the events broke the event chain. * * If the continueCallBack is specified, this callback will be called every * time before the next event handler is called. * * If the continueCallback returns false, event propagation stops. This * allows you to use the eventEmitter as a means for listeners to implement * functionality in your application, and break the event loop as soon as * some condition is fulfilled. * * Note that returning false from an event subscriber breaks propagation * and returns false, but if the continue-callback stops propagation, this * is still considered a 'successful' operation and returns true. * * Lastly, if there are 5 event handlers for an event. The continueCallback * will be called at most 4 times. * * @param list $arguments */ public function emit(string $eventName, array $arguments = [], ?callable $continueCallBack = null) : bool { if ($continueCallBack === null) { foreach ($this->listeners($eventName) as $listener) { /** @psalm-suppress MixedAssignment */ $result = \call_user_func_array($listener, $arguments); if ($result === \false) { return \false; } } } else { $listeners = $this->listeners($eventName); $counter = \count($listeners); foreach ($listeners as $listener) { --$counter; /** @psalm-suppress MixedAssignment */ $result = \call_user_func_array($listener, $arguments); if ($result === \false) { return \false; } if ($counter > 0) { if (!$continueCallBack()) { break; } } } } return \true; } /** * Returns the list of listeners for an event. * * The list is returned as an array, and the list of events are sorted by * their priority. * * @return callable[] */ public function listeners(string $eventName) : array { if (!isset($this->listeners[$eventName])) { return []; } // The list is not sorted if (!$this->listeners[$eventName][0]) { // Sorting \array_multisort($this->listeners[$eventName][1], \SORT_NUMERIC, $this->listeners[$eventName][2]); // Marking the listeners as sorted $this->listeners[$eventName][0] = \true; } return $this->listeners[$eventName][2]; } /** * Removes a specific listener from an event. * * If the listener could not be found, this method will return false. If it * was removed it will return true. */ public function removeListener(string $eventName, callable $listener) : bool { if (!isset($this->listeners[$eventName])) { return \false; } foreach ($this->listeners[$eventName][2] as $index => $check) { if ($check === $listener) { unset($this->listeners[$eventName][1][$index], $this->listeners[$eventName][2][$index]); return \true; } } return \false; } } protocolReader = $protocolReader; $this->protocolWriter = $protocolWriter; $this->idGenerator = new \Psalm\Internal\LanguageServer\IdGenerator(); } /** * Sends a request to the client and returns a promise that is resolved with the result or rejected with the error * * @param string $method The method to call * @param array|object $params The method parameters * * @return Promise Resolved with the result of the request or rejected with an error */ public function request(string $method, $params) : \_HumbugBoxd02f763d3c56\Amp\Promise { $id = $this->idGenerator->generate(); return \_HumbugBoxd02f763d3c56\Amp\call( /** * @return \Generator> */ function () use($id, $method, $params) : \Generator { (yield $this->protocolWriter->write(new \Psalm\Internal\LanguageServer\Message(new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Request($id, $method, (object) $params)))); $deferred = new \_HumbugBoxd02f763d3c56\Amp\Deferred(); $listener = function (\Psalm\Internal\LanguageServer\Message $msg) use($id, $deferred, &$listener) : void { \error_log('request handler'); /** * @psalm-suppress UndefinedPropertyFetch * @psalm-suppress MixedArgument */ if ($msg->body && \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Response::isResponse($msg->body) && $msg->body->id === $id) { // Received a response $this->protocolReader->removeListener('message', $listener); if (\_HumbugBoxd02f763d3c56\AdvancedJsonRpc\SuccessResponse::isSuccessResponse($msg->body)) { $deferred->resolve($msg->body->result); } else { $deferred->fail($msg->body->error); } } }; $this->protocolReader->on('message', $listener); return $deferred->promise(); } ); } /** * Sends a notification to the client * * @param string $method The method to call * @param array|object $params The method parameters * * @return Promise Will be resolved as soon as the notification has been sent */ public function notify(string $method, $params) : \_HumbugBoxd02f763d3c56\Amp\Promise { /** @var Promise */ return $this->protocolWriter->write(new \Psalm\Internal\LanguageServer\Message(new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Notification($method, (object) $params))); } } */ protected $onsave_paths_to_analyze = []; /** * @var array */ protected $onchange_paths_to_analyze = []; public function __construct(\Psalm\Internal\LanguageServer\ProtocolReader $reader, \Psalm\Internal\LanguageServer\ProtocolWriter $writer, \Psalm\Internal\Analyzer\ProjectAnalyzer $project_analyzer) { parent::__construct($this, '/'); $this->project_analyzer = $project_analyzer; $this->protocolWriter = $writer; $this->protocolReader = $reader; $this->protocolReader->on('close', function () : void { $this->shutdown(); $this->exit(); }); $this->protocolReader->on('message', \_HumbugBoxd02f763d3c56\Amp\asyncCoroutine( /** * @return \Generator */ function (\Psalm\Internal\LanguageServer\Message $msg) : \Generator { if (!$msg->body) { return; } // Ignore responses, this is the handler for requests and notifications if (\_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Response::isResponse($msg->body)) { return; } /** @psalm-suppress UndefinedPropertyFetch */ if ($msg->body->method === 'textDocument/signatureHelp') { $this->doAnalysis(); } $result = null; $error = null; try { // Invoke the method handler to get a result /** * @var Promise * @psalm-suppress UndefinedDocblockClass */ $dispatched = $this->dispatch($msg->body); /** @psalm-suppress MixedAssignment */ $result = (yield $dispatched); } catch (\_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error $e) { // If a ResponseError is thrown, send it back in the Response $error = $e; } catch (\Throwable $e) { // If an unexpected error occurred, send back an INTERNAL_ERROR error response $error = new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Error((string) $e, \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorCode::INTERNAL_ERROR, null, $e); } // Only send a Response for a Request // Notifications do not send Responses /** * @psalm-suppress UndefinedPropertyFetch * @psalm-suppress MixedArgument */ if (\_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Request::isRequest($msg->body)) { if ($error !== null) { $responseBody = new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\ErrorResponse($msg->body->id, $error); } else { $responseBody = new \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\SuccessResponse($msg->body->id, $result); } (yield $this->protocolWriter->write(new \Psalm\Internal\LanguageServer\Message($responseBody))); } } )); $this->protocolReader->on('readMessageGroup', function () : void { $this->doAnalysis(); }); $this->client = new \Psalm\Internal\LanguageServer\LanguageClient($reader, $writer); $this->verboseLog("Language server has started."); } /** * 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 string|null $rootPath The rootPath of the workspace. Is null if no folder is open. * @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. * @psalm-return Promise * @psalm-suppress PossiblyUnusedMethod */ public function initialize(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\ClientCapabilities $capabilities, ?string $rootPath = null, ?int $processId = null) : \_HumbugBoxd02f763d3c56\Amp\Promise { return \_HumbugBoxd02f763d3c56\Amp\call( /** @return \Generator */ function () use($capabilities, $rootPath, $processId) { $this->verboseLog("Initializing..."); $this->clientStatus('initializing'); // Eventually, this might block on something. Leave it as a generator. /** @psalm-suppress TypeDoesNotContainType */ if (\false) { (yield \true); } $this->verboseLog("Initializing: Getting code base..."); $this->clientStatus('initializing', 'getting code base'); $codebase = $this->project_analyzer->getCodebase(); $this->verboseLog("Initializing: Scanning files..."); $this->clientStatus('initializing', 'scanning files'); $codebase->scanFiles($this->project_analyzer->threads); $this->verboseLog("Initializing: Registering stub files..."); $this->clientStatus('initializing', 'registering stub files'); $codebase->config->visitStubFiles($codebase, null); if ($this->textDocument === null) { $this->textDocument = new \Psalm\Internal\LanguageServer\Server\TextDocument($this, $codebase, $this->project_analyzer->onchange_line_limit); } $serverCapabilities = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\ServerCapabilities(); $textDocumentSyncOptions = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentSyncOptions(); if ($this->project_analyzer->onchange_line_limit === 0) { $textDocumentSyncOptions->change = \_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentSyncKind::NONE; } else { $textDocumentSyncOptions->change = \_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentSyncKind::FULL; } $serverCapabilities->textDocumentSync = $textDocumentSyncOptions; // Support "Find all symbols" $serverCapabilities->documentSymbolProvider = \false; // Support "Find all symbols in workspace" $serverCapabilities->workspaceSymbolProvider = \false; // Support "Go to definition" $serverCapabilities->definitionProvider = \true; // Support "Find all references" $serverCapabilities->referencesProvider = \false; // Support "Hover" $serverCapabilities->hoverProvider = \true; // Support "Completion" if ($this->project_analyzer->provide_completion) { $serverCapabilities->completionProvider = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionOptions(); $serverCapabilities->completionProvider->resolveProvider = \false; $serverCapabilities->completionProvider->triggerCharacters = ['$', '>', ':']; } $serverCapabilities->signatureHelpProvider = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\SignatureHelpOptions(['(', ',']); // Support global references $serverCapabilities->xworkspaceReferencesProvider = \false; $serverCapabilities->xdefinitionProvider = \false; $serverCapabilities->dependenciesProvider = \false; $this->verboseLog("Initializing: Complete."); $this->clientStatus('initialized'); return new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\InitializeResult($serverCapabilities); } ); } /** * @psalm-suppress PossiblyUnusedMethod * */ public function initialized() : void { $this->clientStatus('running'); } public function queueTemporaryFileAnalysis(string $file_path, string $uri) : void { $this->onchange_paths_to_analyze[$file_path] = $uri; } public function queueFileAnalysis(string $file_path, string $uri) : void { $this->onsave_paths_to_analyze[$file_path] = $uri; } public function doAnalysis() : void { $this->clientStatus('analyzing'); try { $codebase = $this->project_analyzer->getCodebase(); $all_files_to_analyze = $this->onchange_paths_to_analyze + $this->onsave_paths_to_analyze; if (!$all_files_to_analyze) { return; } if ($this->onsave_paths_to_analyze) { $codebase->reloadFiles($this->project_analyzer, \array_keys($this->onsave_paths_to_analyze)); } if ($this->onchange_paths_to_analyze) { $codebase->reloadFiles($this->project_analyzer, \array_keys($this->onchange_paths_to_analyze)); } $all_file_paths_to_analyze = \array_keys($all_files_to_analyze); $codebase->analyzer->addFilesToAnalyze(\array_combine($all_file_paths_to_analyze, $all_file_paths_to_analyze)); $codebase->analyzer->analyzeFiles($this->project_analyzer, 1, \false); $this->emitIssues($all_files_to_analyze); $this->onchange_paths_to_analyze = []; $this->onsave_paths_to_analyze = []; } finally { // we are done, so set the status back to running $this->clientStatus('running'); } } /** * @param array $uris * */ public function emitIssues(array $uris) : void { $data = \Psalm\IssueBuffer::clear(); foreach ($uris as $file_path => $uri) { $diagnostics = \array_map(function (\Psalm\Internal\Analyzer\IssueData $issue_data) use($file_path) : Diagnostic { //$check_name = $issue->check_name; $description = $issue_data->message; $severity = $issue_data->severity; $start_line = \max($issue_data->line_from, 1); $end_line = $issue_data->line_to; $start_column = $issue_data->column_from; $end_column = $issue_data->column_to; // Language server has 0 based lines and columns, phan has 1-based lines and columns. $range = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Range(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position($start_line - 1, $start_column - 1), new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position($end_line - 1, $end_column - 1)); switch ($severity) { case \Psalm\Config::REPORT_INFO: $diagnostic_severity = \_HumbugBoxd02f763d3c56\LanguageServerProtocol\DiagnosticSeverity::WARNING; break; case \Psalm\Config::REPORT_ERROR: default: $diagnostic_severity = \_HumbugBoxd02f763d3c56\LanguageServerProtocol\DiagnosticSeverity::ERROR; break; } $diagnostic = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Diagnostic($description, $range, null, $diagnostic_severity, 'Psalm'); //$code = 'PS' . \str_pad((string) $issue_data->shortcode, 3, "0", \STR_PAD_LEFT); $code = $issue_data->link; if ($this->project_analyzer->language_server_use_extended_diagnostic_codes) { // Added in VSCode 1.43.0 and will be part of the LSP 3.16.0 standard. // Since this new functionality is not backwards compatible, we use a // configuration option so the end user must opt in to it using the cli argument. // https://github.com/microsoft/vscode/blob/1.43.0/src/vs/vscode.d.ts#L4688-L4699 /** @psalm-suppress InvalidPropertyAssignmentValue */ $diagnostic->code = ["value" => $code, "target" => $issue_data->link]; } else { // the Diagnostic constructor only takes `int` for the code, but the property can be // `int` or `string`, so we set the property directly because we want to use a `string` $diagnostic->code = $code; } return $diagnostic; }, $data[$file_path] ?? []); $this->client->textDocument->publishDiagnostics($uri, $diagnostics); } } /** * The shutdown request is sent from the client to the server. It asks the server to shut down, * but to not exit (otherwise the response might not be delivered correctly to the client). * There is a separate exit notification that asks the server to exit. * * @psalm-return Promise */ public function shutdown() : \_HumbugBoxd02f763d3c56\Amp\Promise { $this->clientStatus('closing'); $this->verboseLog("Shutting down..."); $codebase = $this->project_analyzer->getCodebase(); $scanned_files = $codebase->scanner->getScannedFiles(); $codebase->file_reference_provider->updateReferenceCache($codebase, $scanned_files); $this->clientStatus('closed'); return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } /** * A notification to ask the server to exit its process. * */ public function exit() : void { exit(0); } /** * Send log message to the client * * @param string $message The log message to send to the client. * @psalm-param 1|2|3|4 $type * @param int $type The log type: * - 1 = Error * - 2 = Warning * - 3 = Info * - 4 = Log */ private function verboseLog(string $message, int $type = 4) : \_HumbugBoxd02f763d3c56\Amp\Promise { if ($this->project_analyzer->language_server_verbose) { try { return $this->client->logMessage('[Psalm ' . PSALM_VERSION . ' - PHP Language Server] ' . $message, $type); } catch (\Throwable $err) { // do nothing } } return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } /** * Send status message to client. This is the same as sending a log message, * except this is meant for parsing by the client to present status updates in a UI. * * @param string $status The log message to send to the client. Should not contain colons `:`. * @param string|null $additional_info This is additional info that the client * can use as part of the display message. */ private function clientStatus(string $status, ?string $additional_info = null) : \_HumbugBoxd02f763d3c56\Amp\Promise { try { // here we send a notification to the client using the telemetry notification method return $this->client->logMessage($status . (!empty($additional_info) ? ': ' . $additional_info : ''), 3, 'telemetry/event'); } catch (\Throwable $err) { return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } } /** * Transforms an absolute file path into a URI as used by the language server protocol. * * @psalm-pure */ public static function pathToUri(string $filepath) : string { $filepath = \trim(\str_replace('\\', '/', $filepath), '/'); $parts = \explode('/', $filepath); // Don't %-encode the colon after a Windows drive letter $first = \array_shift($parts); if (\substr($first, -1) !== ':') { $first = \rawurlencode($first); } $parts = \array_map('rawurlencode', $parts); \array_unshift($parts, $first); $filepath = \implode('/', $parts); return 'file:///' . $filepath; } /** * Transforms URI into file path * * */ public static function uriToPath(string $uri) : string { $fragments = \parse_url($uri); if ($fragments === \false || !isset($fragments['scheme']) || $fragments['scheme'] !== 'file' || !isset($fragments['path'])) { throw new \InvalidArgumentException("Not a valid file URI: {$uri}"); } $filepath = \urldecode((string) $fragments['path']); if (\strpos($filepath, ':') !== \false) { if ($filepath[0] === '/') { $filepath = \substr($filepath, 1); } $filepath = \str_replace('/', '\\', $filepath); } $realpath = \realpath($filepath); if ($realpath !== \false) { return $realpath; } return $filepath; } } , ?string, void> * @psalm-suppress MixedReturnTypeCoercion * @psalm-suppress MixedArgument in old Amp versions * @psalm-suppress MixedAssignment in old Amp versions */ function () use($input) : \Generator { while ($this->is_accepting_new_requests) { $read_promise = $input->read(); $chunk = (yield $read_promise); if ($chunk === null) { break; } if ($this->readMessages($chunk) > 0) { $this->emit('readMessageGroup'); } } $this->emitClose(); } ); $this->on('close', static function () use($input) : void { $input->close(); }); } private function readMessages(string $buffer) : int { $emitted_messages = 0; $i = 0; while (($buffer[$i] ?? '') !== '') { $this->buffer .= $buffer[$i++]; switch ($this->parsing_mode) { case self::PARSE_HEADERS: if ($this->buffer === "\r\n") { $this->parsing_mode = self::PARSE_BODY; $this->content_length = (int) ($this->headers['Content-Length'] ?? 0); $this->buffer = ''; } elseif (\substr($this->buffer, -2) === "\r\n") { $parts = \explode(':', $this->buffer); $this->headers[$parts[0]] = \trim($parts[1]); $this->buffer = ''; } break; case self::PARSE_BODY: if (\strlen($this->buffer) === $this->content_length) { if (!$this->is_accepting_new_requests) { // If we fork, don't read any bytes in the input buffer from the worker process. $this->emitClose(); return $emitted_messages; } // MessageBody::parse can throw an Error, maybe log an error? try { $msg = new \Psalm\Internal\LanguageServer\Message(\_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Message::parse($this->buffer), $this->headers); } catch (\Exception $_) { $msg = null; } if ($msg) { ++$emitted_messages; $this->emit('message', [$msg]); /** @psalm-suppress DocblockTypeContradiction */ if (!$this->is_accepting_new_requests) { // If we fork, don't read any bytes in the input buffer from the worker process. $this->emitClose(); return $emitted_messages; } } $this->parsing_mode = self::PARSE_HEADERS; $this->headers = []; $this->buffer = ''; } break; } } return $emitted_messages; } private function emitClose() : void { if ($this->did_emit_close) { return; } $this->did_emit_close = \true; $this->emit('close'); } } output = new \_HumbugBoxd02f763d3c56\Amp\ByteStream\ResourceOutputStream($output); } /** * {@inheritdoc} */ public function write(\Psalm\Internal\LanguageServer\Message $msg) : \_HumbugBoxd02f763d3c56\Amp\Promise { return $this->output->write((string) $msg); } } server = $server; $this->codebase = $codebase; $this->onchange_line_limit = $onchange_line_limit; } /** * The document open notification is sent from the client to the server to signal newly opened text documents. The * document's truth is now managed by the client and the server must not try to read the document's truth using the * document's uri. * * @param \LanguageServerProtocol\TextDocumentItem $textDocument the document that was opened */ public function didOpen(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentItem $textDocument) : void { $file_path = \Psalm\Internal\LanguageServer\LanguageServer::uriToPath($textDocument->uri); if (!$this->codebase->config->isInProjectDirs($file_path)) { \error_log($file_path . ' is not in project'); return; } $this->codebase->file_provider->openFile($file_path); $this->server->queueFileAnalysis($file_path, $textDocument->uri); } public function didSave(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentItem $textDocument) : void { $file_path = \Psalm\Internal\LanguageServer\LanguageServer::uriToPath($textDocument->uri); if (!$this->codebase->config->isInProjectDirs($file_path)) { return; } // reopen file $this->codebase->removeTemporaryFileChanges($file_path); $this->codebase->file_provider->setOpenContents($file_path, $textDocument->text); $this->server->queueFileAnalysis($file_path, $textDocument->uri); } /** * The document change notification is sent from the client to the server to signal changes to a text document. * * @param \LanguageServerProtocol\VersionedTextDocumentIdentifier $textDocument * @param \LanguageServerProtocol\TextDocumentContentChangeEvent[] $contentChanges */ public function didChange(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\VersionedTextDocumentIdentifier $textDocument, array $contentChanges) : void { $file_path = \Psalm\Internal\LanguageServer\LanguageServer::uriToPath($textDocument->uri); if (!$this->codebase->config->isInProjectDirs($file_path)) { return; } if ($this->onchange_line_limit === 0) { return; } if (\count($contentChanges) === 1 && $contentChanges[0]->range === null) { $new_content = $contentChanges[0]->text; } else { throw new \UnexpectedValueException('Not expecting partial diff'); } if ($this->onchange_line_limit !== null) { if (\substr_count($new_content, "\n") > $this->onchange_line_limit) { return; } } $this->codebase->addTemporaryFileChanges($file_path, $new_content); $this->server->queueTemporaryFileAnalysis($file_path, $textDocument->uri); } /** * The document close notification is sent from the client to the server when the document got closed in the client. * The document's truth now exists where the document's uri points to (e.g. if the document's uri is a file uri the * truth now exists on disk). * * @param \LanguageServerProtocol\TextDocumentIdentifier $textDocument The document that was closed * */ public function didClose(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentIdentifier $textDocument) : void { $file_path = \Psalm\Internal\LanguageServer\LanguageServer::uriToPath($textDocument->uri); $this->codebase->file_provider->closeFile($file_path); $this->server->client->textDocument->publishDiagnostics($textDocument->uri, []); } /** * The goto definition request is sent from the client to the server to resolve the definition location of a symbol * at a given text document position. * * @param TextDocumentIdentifier $textDocument The text document * @param Position $position The position inside the text document * @psalm-return Promise|Promise */ public function definition(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentIdentifier $textDocument, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position $position) : \_HumbugBoxd02f763d3c56\Amp\Promise { $file_path = \Psalm\Internal\LanguageServer\LanguageServer::uriToPath($textDocument->uri); try { $reference_location = $this->codebase->getReferenceAtPosition($file_path, $position); } catch (\Psalm\Exception\UnanalyzedFileException $e) { $this->codebase->file_provider->openFile($file_path); $this->server->queueFileAnalysis($file_path, $textDocument->uri); return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } if ($reference_location === null) { return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } [$reference] = $reference_location; $code_location = $this->codebase->getSymbolLocation($file_path, $reference); if (!$code_location) { return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } return new \_HumbugBoxd02f763d3c56\Amp\Success(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Location(\Psalm\Internal\LanguageServer\LanguageServer::pathToUri($code_location->file_path), new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Range(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position($code_location->getLineNumber() - 1, $code_location->getColumn() - 1), new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position($code_location->getEndLineNumber() - 1, $code_location->getEndColumn() - 1)))); } /** * The hover request is sent from the client to the server to request * hover information at a given text document position. * * @param TextDocumentIdentifier $textDocument The text document * @param Position $position The position inside the text document * @psalm-return Promise|Promise */ public function hover(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentIdentifier $textDocument, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position $position) : \_HumbugBoxd02f763d3c56\Amp\Promise { $file_path = \Psalm\Internal\LanguageServer\LanguageServer::uriToPath($textDocument->uri); try { $reference_location = $this->codebase->getReferenceAtPosition($file_path, $position); } catch (\Psalm\Exception\UnanalyzedFileException $e) { $this->codebase->file_provider->openFile($file_path); $this->server->queueFileAnalysis($file_path, $textDocument->uri); return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } if ($reference_location === null) { return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } [$reference, $range] = $reference_location; $symbol_information = $this->codebase->getSymbolInformation($file_path, $reference); if ($symbol_information === null) { return new \_HumbugBoxd02f763d3c56\Amp\Success(null); } $contents = []; $contents[] = new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\MarkedString('php', $symbol_information); return new \_HumbugBoxd02f763d3c56\Amp\Success(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Hover($contents, $range)); } /** * The Completion request is sent from the client to the server to compute completion items at a given cursor * position. Completion items are presented in the IntelliSense user interface. If computing full completion items * is expensive, servers can additionally provide a handler for the completion item resolve request * ('completionItem/resolve'). This request is sent when a completion item is selected in the user interface. A * typically use case is for example: the 'textDocument/completion' request doesn't fill in the documentation * property for returned completion items since it is expensive to compute. When the item is selected in the user * interface then a 'completionItem/resolve' request is sent with the selected completion item as a param. The * returned completion item should have the documentation property filled in. * * @param TextDocumentIdentifier The text document * @param Position $position The position * @psalm-return Promise>|Promise */ public function completion(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentIdentifier $textDocument, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position $position) : \_HumbugBoxd02f763d3c56\Amp\Promise { $this->server->doAnalysis(); $file_path = \Psalm\Internal\LanguageServer\LanguageServer::uriToPath($textDocument->uri); if (!$this->codebase->config->isInProjectDirs($file_path)) { return new \_HumbugBoxd02f763d3c56\Amp\Success([]); } try { $completion_data = $this->codebase->getCompletionDataAtPosition($file_path, $position); } catch (\Psalm\Exception\UnanalyzedFileException $e) { $this->codebase->file_provider->openFile($file_path); $this->server->queueFileAnalysis($file_path, $textDocument->uri); return new \_HumbugBoxd02f763d3c56\Amp\Success([]); } if (!$completion_data) { \error_log('completion not found at ' . $position->line . ':' . $position->character); return new \_HumbugBoxd02f763d3c56\Amp\Success([]); } [$recent_type, $gap, $offset] = $completion_data; if ($gap === '->' || $gap === '::') { $completion_items = $this->codebase->getCompletionItemsForClassishThing($recent_type, $gap); } else { $completion_items = $this->codebase->getCompletionItemsForPartialSymbol($recent_type, $offset, $file_path); } return new \_HumbugBoxd02f763d3c56\Amp\Success(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\CompletionList($completion_items, \false)); } public function signatureHelp(\_HumbugBoxd02f763d3c56\LanguageServerProtocol\TextDocumentIdentifier $textDocument, \_HumbugBoxd02f763d3c56\LanguageServerProtocol\Position $position) : \_HumbugBoxd02f763d3c56\Amp\Promise { $file_path = \Psalm\Internal\LanguageServer\LanguageServer::uriToPath($textDocument->uri); try { $argument_location = $this->codebase->getFunctionArgumentAtPosition($file_path, $position); } catch (\Psalm\Exception\UnanalyzedFileException $e) { $this->codebase->file_provider->openFile($file_path); $this->server->queueFileAnalysis($file_path, $textDocument->uri); return new \_HumbugBoxd02f763d3c56\Amp\Success(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\SignatureHelp()); } if ($argument_location === null) { return new \_HumbugBoxd02f763d3c56\Amp\Success(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\SignatureHelp()); } $signature_information = $this->codebase->getSignatureInformation($argument_location[0]); if (!$signature_information) { return new \_HumbugBoxd02f763d3c56\Amp\Success(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\SignatureHelp()); } return new \_HumbugBoxd02f763d3c56\Amp\Success(new \_HumbugBoxd02f763d3c56\LanguageServerProtocol\SignatureHelp([$signature_information], 0, $argument_location[1])); } } $arguments */ public function emit(string $eventName, array $arguments = [], ?callable $continueCallBack = null) : bool; /** * Returns the list of listeners for an event. * * The list is returned as an array, and the list of events are sorted by * their priority. * * @return callable[] */ public function listeners(string $eventName) : array; /** * Removes a specific listener from an event. * * If the listener could not be found, this method will return false. If it * was removed it will return true. */ public function removeListener(string $eventName, callable $listener) : bool; } body = \_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Message::parse(\array_pop($parts)); foreach ($parts as $line) { if ($line) { $pair = \explode(': ', $line); $obj->headers[$pair[0]] = $pair[1]; } } return $obj; } /** * @param string[] $headers */ public function __construct(?\_HumbugBoxd02f763d3c56\AdvancedJsonRpc\Message $body = null, array $headers = []) { $this->body = $body; if (!isset($headers['Content-Type'])) { $headers['Content-Type'] = 'application/vscode-jsonrpc; charset=utf8'; } $this->headers = $headers; } public function __toString() : string { $body = (string) $this->body; $contentLength = \strlen($body); $this->headers['Content-Length'] = (string) $contentLength; $headers = ''; foreach ($this->headers as $name => $value) { $headers .= "{$name}: {$value}\r\n"; } return $headers . "\r\n" . $body; } } handler = new \Psalm\Internal\LanguageServer\ClientHandler($reader, $writer); $mapper = new \_HumbugBoxd02f763d3c56\JsonMapper(); $this->textDocument = new \Psalm\Internal\LanguageServer\Client\TextDocument($this->handler, $mapper); } /** * Send a log message to the client. * * @param string $message The message to send to the client. * @psalm-param 1|2|3|4 $type * @param int $type The log type: * - 1 = Error * - 2 = Warning * - 3 = Info * - 4 = Log * * @return Promise */ public function logMessage(string $message, int $type = 4, string $method = 'window/logMessage') : \_HumbugBoxd02f763d3c56\Amp\Promise { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage if ($type < 1 || $type > 4) { $type = 4; } return $this->handler->notify($method, ['type' => $type, 'message' => $message]); } } start = $start; $this->end = $end; $this->insertion_text = $insertion_text; $this->preserve_indentation = $preserve_indentation; $this->remove_trailing_newline = $remove_trailing_newline; } public function getKey() : string { return $this->start === $this->end ? $this->start . ':' . \sha1($this->insertion_text) : $this->start . ':' . $this->end; } public function transform(string $existing_contents) : string { if ($this->preserve_indentation) { $newline_pos = \strrpos($existing_contents, "\n", $this->start - \strlen($existing_contents)); $newline_pos = $newline_pos !== \false ? $newline_pos + 1 : 0; $indentation = \substr($existing_contents, $newline_pos, $this->start - $newline_pos); if (\trim($indentation) === '') { $this->insertion_text = $this->insertion_text . $indentation; } } if ($this->remove_trailing_newline && \strlen($existing_contents) > $this->end && $existing_contents[$this->end] === "\n") { $newline_pos = \strrpos($existing_contents, "\n", $this->start - \strlen($existing_contents)); $newline_pos = $newline_pos !== \false ? $newline_pos + 1 : 0; $indentation = \substr($existing_contents, $newline_pos, $this->start - $newline_pos); if (\trim($indentation) === '') { $this->start -= \strlen($indentation); $this->end++; } } return \substr($existing_contents, 0, $this->start) . $this->insertion_text . \substr($existing_contents, $this->end); } } */ public $constants = []; /** * Aliases to help Psalm understand constant refs * * @var ?\Psalm\Aliases */ public $aliases; /** * @var bool */ public $populated = \false; /** * @var bool */ public $stubbed = \false; /** * @var bool */ public $deprecated = \false; /** * @var string */ public $internal = ''; /** * @var null|Type\Atomic\TTemplateParam|Type\Atomic\TNamedObject * @deprecated */ public $mixin = null; /** * @var Type\Atomic\TTemplateParam[] */ public $templatedMixins = []; /** * @var Type\Atomic\TNamedObject[] */ public $namedMixins = []; /** * @var ?string */ public $mixin_declaring_fqcln = null; /** * @var bool */ public $sealed_properties = \false; /** * @var bool */ public $sealed_methods = \false; /** * @var bool */ public $override_property_visibility = \false; /** * @var bool */ public $override_method_visibility = \false; /** * @var array */ public $suppressed_issues = []; /** * @var string */ public $name; /** * Is this class user-defined * * @var bool */ public $user_defined = \false; /** * Interfaces this class implements directly * * @var array */ public $direct_class_interfaces = []; /** * Interfaces this class implements explicitly and implicitly * * @var array */ public $class_implements = []; /** * Parent interfaces listed explicitly * * @var array */ public $direct_interface_parents = []; /** * Parent interfaces * * @var array */ public $parent_interfaces = []; /** * There can only be one direct parent class * * @var ?string */ public $parent_class; /** * Parent classes * * @var array */ public $parent_classes = []; /** * @var CodeLocation|null */ public $location; /** * @var CodeLocation|null */ public $stmt_location; /** * @var CodeLocation|null */ public $namespace_name_location; /** * @var bool */ public $abstract = \false; /** * @var bool */ public $final = \false; /** * @var array */ public $used_traits = []; /** * @var array */ public $trait_alias_map = []; /** * @var array */ public $trait_final_map = []; /** * @var array */ public $trait_visibility_map = []; /** * @var bool */ public $is_trait = \false; /** * @var bool */ public $is_interface = \false; /** * @var bool */ public $external_mutation_free = \false; /** * @var bool */ public $mutation_free = \false; /** * @var bool */ public $specialize_instance = \false; /** * @var array */ public $methods = []; /** * @var array */ public $pseudo_methods = []; /** * @var array */ public $pseudo_static_methods = []; /** * @var array */ public $declaring_method_ids = []; /** * @var array */ public $appearing_method_ids = []; /** * @var array> */ public $overridden_method_ids = []; /** * @var array */ public $documenting_method_ids = []; /** * @var array */ public $inheritable_method_ids = []; /** * @var array> */ public $potential_declaring_method_ids = []; /** * @var array */ public $properties = []; /** * @var array */ public $pseudo_property_set_types = []; /** * @var array */ public $pseudo_property_get_types = []; /** * @var array */ public $declaring_property_ids = []; /** * @var array */ public $appearing_property_ids = []; /** * @var array */ public $inheritable_property_ids = []; /** * @var array> */ public $overridden_property_ids = []; /** * @var array>|null */ public $template_types; /** * @var array|null */ public $template_covariants; /** * @var array>|null */ public $template_type_extends; /** * @var ?int */ public $template_type_extends_count; /** * @var array|null */ public $template_type_implements_count; /** * @var ?Type\Union */ public $yield; /** * @var array|null */ public $template_type_uses_count; /** * @var array */ public $initialized_properties = []; /** * @var array */ public $invalid_dependencies = []; /** * @var array */ public $dependent_classlikes = []; /** * A hash of the source file's name, contents, and this file's modified on date * * @var string */ public $hash = ''; /** * @var bool */ public $has_visitor_issues = \false; /** * @var list<\Psalm\Issue\CodeIssue> */ public $docblock_issues = []; /** * @var array */ public $type_aliases = []; /** * @var bool */ public $preserve_constructor_signature = \false; /** * @var null|string */ public $extension_requirement; /** * @var array */ public $implementation_requirements = []; public function __construct(string $name) { $this->name = $name; } } */ public $byref_uses = []; } */ public $classlikes_in_file = []; /** * @var array */ public $referenced_classlikes = []; /** * @var array */ public $required_classes = []; /** * @var array */ public $required_interfaces = []; /** * @var bool */ public $has_trait = \false; /** @var string */ public $file_path; /** * @var array */ public $functions = []; /** @var array */ public $declaring_function_ids = []; /** * @var array */ public $constants = []; /** @var array */ public $declaring_constants = []; /** @var array */ public $required_file_paths = []; /** @var array */ public $required_by_file_paths = []; /** @var bool */ public $populated = \false; /** @var bool */ public $deep_scan = \false; /** @var bool */ public $has_extra_statements = \false; /** * @var string */ public $hash = ''; /** * @var bool */ public $has_visitor_issues = \false; /** * @var list<\Psalm\Issue\CodeIssue> */ public $docblock_issues = []; /** * @var array */ public $type_aliases = []; /** * @var array */ public $classlike_aliases = []; /** @var ?Aliases */ public $aliases; /** @var Aliases[] */ public $namespace_aliases = []; public function __construct(string $file_path) { $this->file_path = $file_path; } } > the rule being asserted */ public $rule; /** * @var int|string the id of the property/variable, or * the parameter offset of the affected arg */ public $var_id; /** * @param string|int $var_id * @param array> $rule */ public function __construct($var_id, array $rule) { $this->rule = $rule; $this->var_id = $var_id; } /** * @param array> $template_type_map */ public function getUntemplatedCopy(array $template_type_map, ?string $this_var_id) : self { return new \Psalm\Storage\Assertion(\is_string($this->var_id) && $this_var_id ? \str_replace('$this->', $this_var_id . '->', $this->var_id) : $this->var_id, \array_map( /** * @param array $rules * * @return array{0: string} */ function (array $rules) use($template_type_map) : array { $first_rule = $rules[0]; if ($template_type_map) { $rule_tokens = \Psalm\Internal\Type\TypeTokenizer::tokenize($first_rule); $substitute = \false; foreach ($rule_tokens as &$rule_token) { if (isset($template_type_map[$rule_token[0]])) { foreach ($template_type_map[$rule_token[0]] as [$type]) { $substitute = \true; $first_type = \array_values($type->getAtomicTypes())[0]; if ($first_type instanceof \Psalm\Type\Atomic\TTemplateParam) { $rule_token[0] = $first_type->param_name; } else { $rule_token[0] = $first_type->getKey(); } } } } if ($substitute) { return [\implode('', \array_map(function ($f) { return $f[0]; }, $rule_tokens))]; } } return [$first_rule]; }, $this->rule )); } } */ public $custom_metadata = []; } visibility) { case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE: $visibility_text = 'private'; break; case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED: $visibility_text = 'protected'; break; default: $visibility_text = 'public'; } return $visibility_text . ' ' . ($this->type ? $this->type->getId() : 'mixed'); } } |null */ public $sinks; /** * @var bool */ public $assert_untainted = \false; /** * @var bool */ public $type_inferred = \false; /** * @var bool */ public $expect_variable = \false; public function __construct(string $name, bool $by_ref, ?\Psalm\Type\Union $type = null, ?\Psalm\CodeLocation $location = null, ?\Psalm\CodeLocation $type_location = null, bool $is_optional = \true, bool $is_nullable = \false, bool $is_variadic = \false, ?\Psalm\Type\Union $default_type = null) { $this->name = $name; $this->by_ref = $by_ref; $this->type = $type; $this->signature_type = $type; $this->is_optional = $is_optional; $this->is_nullable = $is_nullable; $this->is_variadic = $is_variadic; $this->location = $location; $this->type_location = $type_location; $this->signature_type_location = $type_location; $this->default_type = $default_type; } public function getId() : string { return ($this->type ? $this->type->getId() : 'mixed') . ($this->is_variadic ? '...' : '') . ($this->is_optional ? '=' : ''); } public function __clone() { if ($this->type) { $this->type = clone $this->type; } } } */ public $params = []; /** * @var array */ public $param_lookup = []; /** * @var Type\Union|null */ public $return_type; /** * @var CodeLocation|null */ public $return_type_location; /** * @var Type\Union|null */ public $signature_return_type; /** * @var CodeLocation|null */ public $signature_return_type_location; /** * @var ?string */ public $cased_name; /** * @var array */ public $suppressed_issues = []; /** * @var ?bool */ public $deprecated; /** * @var string */ public $internal = ''; /** * @var bool */ public $variadic = \false; /** * @var bool */ public $returns_by_ref = \false; /** * @var ?int */ public $required_param_count; /** * @var array */ public $defined_constants = []; /** * @var array */ public $global_variables = []; /** * @var array */ public $global_types = []; /** * @var array>|null */ public $template_types; /** * @var array|null */ public $template_covariants; /** * @var array */ public $assertions = []; /** * @var array */ public $if_true_assertions = []; /** * @var array */ public $if_false_assertions = []; /** * @var bool */ public $has_visitor_issues = \false; /** * @var list<\Psalm\Issue\CodeIssue> */ public $docblock_issues = []; /** * @var array */ public $throws = []; /** * @var array */ public $throw_locations = []; /** * @var bool */ public $has_yield = \false; /** * @var bool */ public $mutation_free = \false; /** * @var string|null */ public $return_type_description; /** * @var array|null */ public $unused_docblock_params; /** * @var bool */ public $pure = \false; /** * Whether or not the function output is dependent solely on input - a function can be * impure but still have this property (e.g. var_export). Useful for taint analysis. * * @var bool */ public $specialize_call = \false; /** * @var array */ public $taint_source_types = []; /** * @var array */ public $added_taints = []; /** * @var array */ public $removed_taints = []; /** * @var array */ public $return_source_params = []; /** * @var bool */ public $allow_named_arg_calls = \true; public function __toString() : string { return $this->getSignature(\false); } public function getSignature(bool $allow_newlines = \false) : string { $newlines = $allow_newlines && !empty($this->params); $symbol_text = 'function ' . $this->cased_name . '(' . ($newlines ? "\n" : '') . \implode(',' . ($newlines ? "\n" : ' '), \array_map(function (\Psalm\Storage\FunctionLikeParameter $param) use($newlines) : string { return ($newlines ? ' ' : '') . ($param->type ?: 'mixed') . ' $' . $param->name; }, $this->params)) . ($newlines ? "\n" : '') . ') : ' . ($this->return_type ?: 'mixed'); if (!$this instanceof \Psalm\Storage\MethodStorage) { return $symbol_text; } switch ($this->visibility) { case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PRIVATE: $visibility_text = 'private'; break; case \Psalm\Internal\Analyzer\ClassLikeAnalyzer::VISIBILITY_PROTECTED: $visibility_text = 'protected'; break; default: $visibility_text = 'public'; } return $visibility_text . ' ' . $symbol_text; } } visibility = $visibility; $this->location = $location; $this->type = $type; } } */ public $this_property_mutations = null; /** * @var Type\Union|null */ public $self_out_type = null; } */ protected $directories = []; /** * @var array */ protected $files = []; /** * @var array */ protected $fq_classlike_names = []; /** * @var array */ protected $fq_classlike_patterns = []; /** * @var array */ protected $method_ids = []; /** * @var array */ protected $property_ids = []; /** * @var array */ protected $var_names = []; /** * @var array */ protected $files_lowercase = []; /** * @var bool */ protected $inclusive; /** * @var array */ protected $ignore_type_stats = []; /** * @var array */ protected $declare_strict_types = []; public function __construct(bool $inclusive) { $this->inclusive = $inclusive; } /** * @return static */ public static function loadFromXMLElement(\SimpleXMLElement $e, string $base_dir, bool $inclusive) { $allow_missing_files = (string) $e['allowMissingFiles'] === 'true'; $filter = new static($inclusive); if ($e->directory) { /** @var \SimpleXMLElement $directory */ foreach ($e->directory as $directory) { $directory_path = (string) $directory['name']; $ignore_type_stats = \strtolower(isset($directory['ignoreTypeStats']) ? (string) $directory['ignoreTypeStats'] : '') === 'true'; $declare_strict_types = \strtolower(isset($directory['useStrictTypes']) ? (string) $directory['useStrictTypes'] : '') === 'true'; if ($directory_path[0] === '/' && \DIRECTORY_SEPARATOR === '/') { $prospective_directory_path = $directory_path; } else { $prospective_directory_path = $base_dir . \DIRECTORY_SEPARATOR . $directory_path; } if (\strpos($prospective_directory_path, '*') !== \false) { $globs = \array_map('realpath', \glob($prospective_directory_path, \GLOB_ONLYDIR)); if (empty($globs)) { if ($allow_missing_files) { continue; } throw new \Psalm\Exception\ConfigException('Could not resolve config path to ' . $base_dir . \DIRECTORY_SEPARATOR . (string) $directory['name']); } foreach ($globs as $glob_index => $directory_path) { if (!$directory_path) { if ($allow_missing_files) { continue; } throw new \Psalm\Exception\ConfigException('Could not resolve config path to ' . $base_dir . \DIRECTORY_SEPARATOR . (string) $directory['name'] . ':' . $glob_index); } if ($ignore_type_stats && $filter instanceof \Psalm\Config\ProjectFileFilter) { $filter->ignore_type_stats[$directory_path] = \true; } if ($declare_strict_types && $filter instanceof \Psalm\Config\ProjectFileFilter) { $filter->declare_strict_types[$directory_path] = \true; } $filter->addDirectory($directory_path); } continue; } $directory_path = \realpath($prospective_directory_path); if (!$directory_path) { if ($allow_missing_files) { continue; } throw new \Psalm\Exception\ConfigException('Could not resolve config path to ' . $base_dir . \DIRECTORY_SEPARATOR . (string) $directory['name']); } if (!\is_dir($directory_path)) { throw new \Psalm\Exception\ConfigException($base_dir . \DIRECTORY_SEPARATOR . (string) $directory['name'] . ' is not a directory'); } /** @var \RecursiveDirectoryIterator */ $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory_path)); $iterator->rewind(); while ($iterator->valid()) { if (!$iterator->isDot() && $iterator->isLink()) { $linked_path = \readlink($iterator->getPathname()); if (\stripos($linked_path, $directory_path) !== 0) { if ($ignore_type_stats && $filter instanceof \Psalm\Config\ProjectFileFilter) { $filter->ignore_type_stats[$directory_path] = \true; } if ($declare_strict_types && $filter instanceof \Psalm\Config\ProjectFileFilter) { $filter->declare_strict_types[$directory_path] = \true; } if (\is_dir($linked_path)) { $filter->addDirectory($linked_path); } } } $iterator->next(); } if ($ignore_type_stats && $filter instanceof \Psalm\Config\ProjectFileFilter) { $filter->ignore_type_stats[$directory_path] = \true; } if ($declare_strict_types && $filter instanceof \Psalm\Config\ProjectFileFilter) { $filter->declare_strict_types[$directory_path] = \true; } $filter->addDirectory($directory_path); } } if ($e->file) { /** @var \SimpleXMLElement $file */ foreach ($e->file as $file) { $file_path = (string) $file['name']; if ($file_path[0] === '/' && \DIRECTORY_SEPARATOR === '/') { $prospective_file_path = $file_path; } else { $prospective_file_path = $base_dir . \DIRECTORY_SEPARATOR . $file_path; } if (\strpos($prospective_file_path, '*') !== \false) { $globs = \array_map('realpath', \array_filter(\glob($prospective_file_path, \GLOB_NOSORT), 'file_exists')); if (empty($globs)) { throw new \Psalm\Exception\ConfigException('Could not resolve config path to ' . $base_dir . \DIRECTORY_SEPARATOR . (string) $file['name']); } foreach ($globs as $glob_index => $file_path) { if (!$file_path) { throw new \Psalm\Exception\ConfigException('Could not resolve config path to ' . $base_dir . \DIRECTORY_SEPARATOR . (string) $file['name'] . ':' . $glob_index); } $filter->addFile($file_path); } continue; } $file_path = \realpath($prospective_file_path); if (!$file_path && !$allow_missing_files) { throw new \Psalm\Exception\ConfigException('Could not resolve config path to ' . $base_dir . \DIRECTORY_SEPARATOR . (string) $file['name']); } $filter->addFile($file_path); } } if ($e->referencedClass) { /** @var \SimpleXMLElement $referenced_class */ foreach ($e->referencedClass as $referenced_class) { $class_name = \strtolower((string) $referenced_class['name']); if (\strpos($class_name, '*') !== \false) { $regex = '/' . \str_replace('*', '.*', \str_replace('\\', '\\\\', $class_name)) . '/i'; $filter->fq_classlike_patterns[] = $regex; } else { $filter->fq_classlike_names[] = $class_name; } } } if ($e->referencedMethod) { /** @var \SimpleXMLElement $referenced_method */ foreach ($e->referencedMethod as $referenced_method) { $method_id = (string) $referenced_method['name']; if (!\preg_match('/^[^:]+::[^:]+$/', $method_id) && !static::isRegularExpression($method_id)) { throw new \Psalm\Exception\ConfigException('Invalid referencedMethod ' . $method_id); } $filter->method_ids[] = \strtolower($method_id); } } if ($e->referencedFunction) { /** @var \SimpleXMLElement $referenced_function */ foreach ($e->referencedFunction as $referenced_function) { $filter->method_ids[] = \strtolower((string) $referenced_function['name']); } } if ($e->referencedProperty) { /** @var \SimpleXMLElement $referenced_property */ foreach ($e->referencedProperty as $referenced_property) { $filter->property_ids[] = \strtolower((string) $referenced_property['name']); } } if ($e->referencedVariable) { /** @var \SimpleXMLElement $referenced_variable */ foreach ($e->referencedVariable as $referenced_variable) { $filter->var_names[] = \strtolower((string) $referenced_variable['name']); } } return $filter; } private static function isRegularExpression(string $string) : bool { \set_error_handler(function () : bool { return \false; }, \E_WARNING); $is_regexp = \preg_match($string, '') !== \false; \restore_error_handler(); return $is_regexp; } /** * @psalm-pure */ protected static function slashify(string $str) : string { return \preg_replace('/\\/?$/', \DIRECTORY_SEPARATOR, $str); } public function allows(string $file_name, bool $case_sensitive = \false) : bool { if ($this->inclusive) { foreach ($this->directories as $include_dir) { if ($case_sensitive) { if (\strpos($file_name, $include_dir) === 0) { return \true; } } else { if (\stripos($file_name, $include_dir) === 0) { return \true; } } } if ($case_sensitive) { if (\in_array($file_name, $this->files, \true)) { return \true; } } else { if (\in_array(\strtolower($file_name), $this->files_lowercase, \true)) { return \true; } } return \false; } // exclusive foreach ($this->directories as $exclude_dir) { if ($case_sensitive) { if (\strpos($file_name, $exclude_dir) === 0) { return \false; } } else { if (\stripos($file_name, $exclude_dir) === 0) { return \false; } } } if ($case_sensitive) { if (\in_array($file_name, $this->files, \true)) { return \false; } } else { if (\in_array(\strtolower($file_name), $this->files_lowercase, \true)) { return \false; } } return \true; } public function allowsClass(string $fq_classlike_name) : bool { if ($this->fq_classlike_patterns) { foreach ($this->fq_classlike_patterns as $pattern) { if (\preg_match($pattern, $fq_classlike_name)) { return \true; } } } return \in_array(\strtolower($fq_classlike_name), $this->fq_classlike_names, \true); } public function allowsMethod(string $method_id) : bool { if (!$this->method_ids) { return \false; } if (\preg_match('/^[^:]+::[^:]+$/', $method_id)) { $method_stub = '*::' . \explode('::', $method_id)[1]; foreach ($this->method_ids as $config_method_id) { if ($config_method_id === $method_id) { return \true; } if ($config_method_id === $method_stub) { return \true; } if ($config_method_id[0] === '/' && \preg_match($config_method_id, $method_id)) { return \true; } } return \false; } return \in_array($method_id, $this->method_ids, \true); } public function allowsProperty(string $property_id) : bool { return \in_array(\strtolower($property_id), $this->property_ids, \true); } public function allowsVariable(string $var_name) : bool { return \in_array(\strtolower($var_name), $this->var_names, \true); } /** * @return array */ public function getDirectories() : array { return $this->directories; } /** * @return array */ public function getFiles() : array { return $this->files; } public function addFile(string $file_name) : void { $this->files[] = $file_name; $this->files_lowercase[] = \strtolower($file_name); } public function addDirectory(string $dir_name) : void { $this->directories[] = self::slashify($dir_name); } } error_level = (string) $e['type']; if (!\in_array($filter->error_level, \Psalm\Config::$ERROR_LEVELS, \true)) { throw new \Psalm\Exception\ConfigException('Unexpected error level ' . $filter->error_level); } } else { throw new \Psalm\Exception\ConfigException(' element expects a level'); } return $filter; } public function getErrorLevel() : string { return $this->error_level; } } '; public static function getContents(string $current_dir, ?string $suggested_dir, int $level, string $vendor_dir) : string { $paths = self::getPaths($current_dir, $suggested_dir); $template = \str_replace('', \implode("\n ", $paths), self::TEMPLATE); $template = \str_replace('', '', $template); $template = \str_replace('errorLevel="1"', 'errorLevel="' . $level . '"', $template); return $template; } public static function createBareConfig(string $current_dir, ?string $suggested_dir, string $vendor_dir) : void { $config_contents = self::getContents($current_dir, $suggested_dir, 1, $vendor_dir); \Psalm\Config::loadFromXML($current_dir, $config_contents); } /** * @param array<\Psalm\Internal\Analyzer\IssueData> $issues */ public static function getLevel(array $issues, int $counted_types) : int { if ($counted_types === 0) { $counted_types = 1; } $issues_at_level = []; foreach ($issues as $issue) { $issue_type = $issue->type; $issue_level = $issue->error_level; if ($issue_level < 1) { continue; } // exclude some directories that are probably ignorable if (\strpos($issue->file_path, 'vendor') || \strpos($issue->file_path, 'stub')) { continue; } if (!isset($issues_at_level[$issue_level][$issue_type])) { $issues_at_level[$issue_level][$issue_type] = 0; } $issues_at_level[$issue_level][$issue_type] += 100 / $counted_types; } foreach ($issues_at_level as $level => $issues) { \ksort($issues); // remove any issues where < 0.1% of expressions are affected $filtered_issues = \array_filter($issues, function ($amount) : bool { return $amount > 0.1; }); if (\array_sum($filtered_issues) > 0.5) { $issues_at_level[$level] = $filtered_issues; } else { unset($issues_at_level[$level]); } } if (!$issues_at_level) { return 1; } if (\count($issues_at_level) === 1) { return \array_keys($issues_at_level)[0] + 1; } return \max(...\array_keys($issues_at_level)) + 1; } /** * @return non-empty-list */ public static function getPaths(string $current_dir, ?string $suggested_dir) : array { $replacements = []; if ($suggested_dir) { if (\is_dir($current_dir . \DIRECTORY_SEPARATOR . $suggested_dir)) { $replacements[] = ''; } else { $bad_dir_path = $current_dir . \DIRECTORY_SEPARATOR . $suggested_dir; throw new \Psalm\Exception\ConfigCreationException('The given path "' . $bad_dir_path . '" does not appear to be a directory'); } } elseif (\is_dir($current_dir . \DIRECTORY_SEPARATOR . 'src')) { $replacements[] = ''; } else { $composer_json_location = \Psalm\Internal\Composer::getJsonFilePath($current_dir); if (!\file_exists($composer_json_location)) { throw new \Psalm\Exception\ConfigCreationException('Problem during config autodiscovery - could not find composer.json during initialization.'); } /** @psalm-suppress MixedAssignment */ if (!($composer_json = \json_decode(\file_get_contents($composer_json_location), \true))) { throw new \Psalm\Exception\ConfigCreationException('Invalid composer.json at ' . $composer_json_location); } if (!\is_array($composer_json)) { throw new \Psalm\Exception\ConfigCreationException('Invalid composer.json at ' . $composer_json_location); } $replacements = self::getPsr4Or0Paths($current_dir, $composer_json); if (!$replacements) { throw new \Psalm\Exception\ConfigCreationException('Could not located any PSR-0 or PSR-4-compatible paths in ' . $composer_json_location); } } return $replacements; } /** * @return list * @psalm-suppress MixedAssignment * @psalm-suppress MixedArgument */ private static function getPsr4Or0Paths(string $current_dir, array $composer_json) : array { $psr_paths = \array_merge($composer_json['autoload']['psr-4'] ?? [], $composer_json['autoload']['psr-0'] ?? []); if (!$psr_paths) { return self::guessPhpFileDirs($current_dir); } $nodes = []; foreach ($psr_paths as $paths) { if (!\is_array($paths)) { $paths = [$paths]; } foreach ($paths as $path) { if ($path === '') { $nodes = \array_merge($nodes, self::guessPhpFileDirs($current_dir)); continue; } $path = \preg_replace('@[\\\\/]$@', '', $path); if ($path !== 'tests') { $nodes[] = ''; } } } $nodes = \array_unique($nodes); \sort($nodes); return $nodes; } /** * @return list */ private static function guessPhpFileDirs(string $current_dir) : array { $nodes = []; /** @var string[] */ $php_files = \array_merge(\glob($current_dir . \DIRECTORY_SEPARATOR . '*.php', \GLOB_NOSORT), \glob($current_dir . \DIRECTORY_SEPARATOR . '**/*.php', \GLOB_NOSORT), \glob($current_dir . \DIRECTORY_SEPARATOR . '**/**/*.php', \GLOB_NOSORT)); foreach ($php_files as $php_file) { $php_file = \str_replace($current_dir . \DIRECTORY_SEPARATOR, '', $php_file); $parts = \explode(\DIRECTORY_SEPARATOR, $php_file); if (!$parts[0]) { \array_shift($parts); } if ($parts[0] === 'vendor' || $parts[0] === 'tests') { continue; } if (\count($parts) === 1) { $nodes[] = ''; } else { $nodes[] = ''; } } return \array_values(\array_unique($nodes)); } } */ private $custom_levels = []; public static function loadFromXMLElement(\SimpleXMLElement $e, string $base_dir) : \Psalm\Config\IssueHandler { $handler = new self(); if (isset($e['errorLevel'])) { $handler->error_level = (string) $e['errorLevel']; if (!\in_array($handler->error_level, \Psalm\Config::$ERROR_LEVELS, \true)) { throw new \Psalm\Exception\ConfigException('Unexpected error level ' . $handler->error_level); } } /** @var \SimpleXMLElement $error_level */ foreach ($e->errorLevel as $error_level) { $handler->custom_levels[] = \Psalm\Config\ErrorLevelFileFilter::loadFromXMLElement($error_level, $base_dir, \true); } return $handler; } public function setErrorLevel(string $error_level) : void { if (!\in_array($error_level, \Psalm\Config::$ERROR_LEVELS, \true)) { throw new \Psalm\Exception\ConfigException('Unexpected error level ' . $error_level); } $this->error_level = $error_level; } public function getReportingLevelForFile(string $file_path) : string { foreach ($this->custom_levels as $custom_level) { if ($custom_level->allows($file_path)) { return $custom_level->getErrorLevel(); } } return $this->error_level; } public function getReportingLevelForClass(string $fq_classlike_name) : ?string { foreach ($this->custom_levels as $custom_level) { if ($custom_level->allowsClass($fq_classlike_name)) { return $custom_level->getErrorLevel(); } } return null; } public function getReportingLevelForMethod(string $method_id) : ?string { foreach ($this->custom_levels as $custom_level) { if ($custom_level->allowsMethod(\strtolower($method_id))) { return $custom_level->getErrorLevel(); } } return null; } public function getReportingLevelForFunction(string $function_id) : ?string { foreach ($this->custom_levels as $custom_level) { if ($custom_level->allowsMethod(\strtolower($function_id))) { return $custom_level->getErrorLevel(); } } return null; } public function getReportingLevelForArgument(string $function_id) : ?string { foreach ($this->custom_levels as $custom_level) { if ($custom_level->allowsMethod(\strtolower($function_id))) { return $custom_level->getErrorLevel(); } } return null; } public function getReportingLevelForProperty(string $property_id) : ?string { foreach ($this->custom_levels as $custom_level) { if ($custom_level->allowsProperty($property_id)) { return $custom_level->getErrorLevel(); } } return null; } public function getReportingLevelForVariable(string $var_name) : ?string { foreach ($this->custom_levels as $custom_level) { if ($custom_level->allowsVariable($var_name)) { return $custom_level->getErrorLevel(); } } return null; } /** * @return array */ public static function getAllIssueTypes() : array { return \array_filter(\array_map( /** * @param string $file_name * * @return string */ function ($file_name) { return \substr($file_name, 0, -4); }, \scandir(\dirname(__DIR__) . '/Issue', \SCANDIR_SORT_NONE) ), function (string $issue_name) : bool { return $issue_name !== '' && $issue_name !== 'MethodIssue' && $issue_name !== 'PropertyIssue' && $issue_name !== 'FunctionIssue' && $issue_name !== 'ArgumentIssue' && $issue_name !== 'VariableIssue' && $issue_name !== 'ClassIssue' && $issue_name !== 'CodeIssue' && $issue_name !== 'PsalmInternalError' && $issue_name !== 'ParseError' && $issue_name !== 'PluginIssue'; }); } } ignoreFiles)) { if (!$inclusive) { throw new \Psalm\Exception\ConfigException('Cannot nest ignoreFiles inside itself'); } /** @var \SimpleXMLElement $e->ignoreFiles */ $filter->file_filter = static::loadFromXMLElement($e->ignoreFiles, $base_dir, \false); } return $filter; } public function allows(string $file_name, bool $case_sensitive = \false) : bool { if ($this->inclusive && $this->file_filter) { if (!$this->file_filter->allows($file_name, $case_sensitive)) { return \false; } } return parent::allows($file_name, $case_sensitive); } public function forbids(string $file_name, bool $case_sensitive = \false) : bool { if ($this->inclusive && $this->file_filter) { if (!$this->file_filter->allows($file_name, $case_sensitive)) { return \true; } } return \false; } public function reportTypeStats(string $file_name, bool $case_sensitive = \false) : bool { foreach ($this->ignore_type_stats as $exclude_dir => $_) { if ($case_sensitive) { if (\strpos($file_name, $exclude_dir) === 0) { return \false; } } else { if (\stripos($file_name, $exclude_dir) === 0) { return \false; } } } return \true; } public function useStrictTypes(string $file_name, bool $case_sensitive = \false) : bool { foreach ($this->declare_strict_types as $exclude_dir => $_) { if ($case_sensitive) { if (\strpos($file_name, $exclude_dir) === 0) { return \true; } } else { if (\stripos($file_name, $exclude_dir) === 0) { return \true; } } } return \false; } } */ protected $issues_data; /** @var array */ protected $fixable_issue_counts; /** @var bool */ protected $use_color; /** @var bool */ protected $show_snippet; /** @var bool */ protected $show_info; /** @var bool */ protected $pretty; /** @var int */ protected $mixed_expression_count; /** @var int */ protected $total_expression_count; /** * @param array $issues_data * @param array $fixable_issue_counts * @param bool $use_color * @param bool $show_snippet * @param bool $show_info */ public function __construct(array $issues_data, array $fixable_issue_counts, \Psalm\Report\ReportOptions $report_options, int $mixed_expression_count = 1, int $total_expression_count = 1) { if (!$report_options->show_info) { $this->issues_data = \array_filter($issues_data, function ($issue_data) : bool { return $issue_data->severity !== \Psalm\Config::REPORT_INFO; }); } else { $this->issues_data = $issues_data; } $this->fixable_issue_counts = $fixable_issue_counts; $this->use_color = $report_options->use_color; $this->show_snippet = $report_options->show_snippet; $this->show_info = $report_options->show_info; $this->pretty = $report_options->pretty; $this->mixed_expression_count = $mixed_expression_count; $this->total_expression_count = $total_expression_count; } public abstract function create() : string; } }>> $existingIssues * * * @psalm-pure */ public static function countTotalIssues(array $existingIssues) : int { $totalIssues = 0; foreach ($existingIssues as $existingIssue) { $totalIssues += \array_reduce( $existingIssue, /** * @param array{o:int, s:array} $existingIssue */ function (int $carry, array $existingIssue) : int { return $carry + $existingIssue['o']; }, 0 ); } return $totalIssues; } /** * @param array> $issues * */ public static function create(\Psalm\Internal\Provider\FileProvider $fileProvider, string $baselineFile, array $issues, bool $include_php_versions) : void { $groupedIssues = self::countIssueTypesByFile($issues); self::writeToFile($fileProvider, $baselineFile, $groupedIssues, $include_php_versions); } /** * @return array}>> * * @throws Exception\ConfigException */ public static function read(\Psalm\Internal\Provider\FileProvider $fileProvider, string $baselineFile) : array { if (!$fileProvider->fileExists($baselineFile)) { throw new \Psalm\Exception\ConfigException("{$baselineFile} does not exist or is not readable"); } $xmlSource = $fileProvider->getContents($baselineFile); $baselineDoc = new \DOMDocument(); $baselineDoc->loadXML($xmlSource, \LIBXML_NOBLANKS); $filesElement = $baselineDoc->getElementsByTagName('files'); if ($filesElement->length === 0) { throw new \Psalm\Exception\ConfigException('Baseline file does not contain '); } $files = []; /** @var \DOMElement $filesElement */ $filesElement = $filesElement[0]; foreach ($filesElement->getElementsByTagName('file') as $file) { $fileName = $file->getAttribute('src'); $fileName = \str_replace('\\', '/', $fileName); $files[$fileName] = []; foreach ($file->childNodes as $issue) { if (!$issue instanceof \DOMElement) { continue; } $issueType = $issue->tagName; $files[$fileName][$issueType] = ['o' => (int) $issue->getAttribute('occurrences'), 's' => []]; $codeSamples = $issue->getElementsByTagName('code'); foreach ($codeSamples as $codeSample) { $files[$fileName][$issueType]['s'][] = $codeSample->textContent; } } } return $files; } /** * @param array> $issues * * @return array}>> * * @throws Exception\ConfigException */ public static function update(\Psalm\Internal\Provider\FileProvider $fileProvider, string $baselineFile, array $issues, bool $include_php_versions) : array { $existingIssues = self::read($fileProvider, $baselineFile); $newIssues = self::countIssueTypesByFile($issues); foreach ($existingIssues as $file => &$existingIssuesCount) { if (!isset($newIssues[$file])) { unset($existingIssues[$file]); continue; } foreach ($existingIssuesCount as $issueType => $existingIssueType) { if (!isset($newIssues[$file][$issueType])) { unset($existingIssuesCount[$issueType]); continue; } $existingIssuesCount[$issueType]['o'] = \min($existingIssueType['o'], $newIssues[$file][$issueType]['o']); $existingIssuesCount[$issueType]['s'] = \array_intersect($existingIssueType['s'], $newIssues[$file][$issueType]['s']); } } $groupedIssues = \array_filter($existingIssues); self::writeToFile($fileProvider, $baselineFile, $groupedIssues, $include_php_versions); return $groupedIssues; } /** * @param array> $issues * * @return array}>> */ private static function countIssueTypesByFile(array $issues) : array { if ($issues === []) { return []; } $groupedIssues = \array_reduce( \array_merge(...\array_values($issues)), /** * @param array}>> $carry * * @return array}>> */ function (array $carry, \Psalm\Internal\Analyzer\IssueData $issue) : array { if ($issue->severity !== \Psalm\Config::REPORT_ERROR) { return $carry; } $fileName = $issue->file_name; $fileName = \str_replace('\\', '/', $fileName); $issueType = $issue->type; if (!isset($carry[$fileName])) { $carry[$fileName] = []; } if (!isset($carry[$fileName][$issueType])) { $carry[$fileName][$issueType] = ['o' => 0, 's' => []]; } ++$carry[$fileName][$issueType]['o']; if (!\strpos($issue->selected_text, "\n")) { $carry[$fileName][$issueType]['s'][] = $issue->selected_text; } return $carry; }, [] ); // Sort files first \ksort($groupedIssues); foreach ($groupedIssues as &$issues) { \ksort($issues); } return $groupedIssues; } /** * @param array}>> $groupedIssues * */ private static function writeToFile(\Psalm\Internal\Provider\FileProvider $fileProvider, string $baselineFile, array $groupedIssues, bool $include_php_versions) : void { $baselineDoc = new \DOMDocument('1.0', 'UTF-8'); $filesNode = $baselineDoc->createElement('files'); $filesNode->setAttribute('psalm-version', PSALM_VERSION); if ($include_php_versions) { $extensions = \array_merge(\get_loaded_extensions(), \get_loaded_extensions(\true)); \usort($extensions, 'strnatcasecmp'); $filesNode->setAttribute('php-version', \implode(';' . "\n\t", \array_merge(['php:' . \PHP_VERSION], \array_map(function (string $extension) : string { return $extension . ':' . \phpversion($extension); }, $extensions)))); } foreach ($groupedIssues as $file => $issueTypes) { $fileNode = $baselineDoc->createElement('file'); $fileNode->setAttribute('src', $file); foreach ($issueTypes as $issueType => $existingIssueType) { $issueNode = $baselineDoc->createElement($issueType); $issueNode->setAttribute('occurrences', (string) $existingIssueType['o']); \sort($existingIssueType['s']); foreach ($existingIssueType['s'] as $selection) { $codeNode = $baselineDoc->createElement('code'); $codeNode->textContent = $selection; $issueNode->appendChild($codeNode); } $fileNode->appendChild($issueNode); } $filesNode->appendChild($fileNode); } $baselineDoc->appendChild($filesNode); $baselineDoc->formatOutput = \true; $xml = \preg_replace_callback( '/)\\n)/', /** * @param array $matches */ function (array $matches) : string { return 'saveXML() ); if ($xml === null) { throw new \RuntimeException('Failed to reformat opening attributes!'); } $fileProvider->setContents($baselineFile, $xml); } } */ public function getAliasedClassesFlipped() : array; /** * @return array */ public function getAliasedClassesFlippedReplaceable() : array; public function getFQCLN() : ?string; public function getClassName() : ?string; public function getParentFQCLN() : ?string; /** * @return array>|null */ public function getTemplateTypeMap() : ?array; public function setRootFilePath(string $file_path, string $file_name) : void; public function hasParentFilePath(string $file_path) : bool; public function hasAlreadyRequiredFilePath(string $file_path) : bool; public function getRequireNesting() : int; public function isStatic() : bool; public function getSource() : \Psalm\StatementsSource; public function getCodebase() : \Psalm\Codebase; /** * Get a list of suppressed issues * * @return array */ public function getSuppressedIssues() : array; /** * @param list $new_issues */ public function addSuppressedIssues(array $new_issues) : void; /** * @param list $new_issues */ public function removeSuppressedIssues(array $new_issues) : void; public function getNodeTypeProvider() : \Psalm\NodeTypeProvider; } file_start = (int) $stmt->getAttribute('startFilePos'); $this->file_end = (int) $stmt->getAttribute('endFilePos'); $this->raw_file_start = $this->file_start; $this->raw_file_end = $this->file_end; $this->file_path = $file_source->getFilePath(); $this->file_name = $file_source->getFileName(); $this->single_line = $single_line; $this->regex_type = $regex_type; $this->previous_location = $previous_location; $this->text = $selected_text; $doc_comment = $stmt->getDocComment(); $this->docblock_start = $doc_comment ? $doc_comment->getStartFilePos() : null; $this->docblock_end = $doc_comment ? $this->file_start : null; $this->docblock_start_line_number = $doc_comment ? $doc_comment->getStartLine() : null; $this->preview_start = $this->docblock_start ?: $this->file_start; $this->raw_line_number = $stmt->getLine(); } public function setCommentLine(int $line) : void { $this->docblock_line_number = $line; } /** * @psalm-suppress MixedArrayAccess */ private function calculateRealLocation() : void { if ($this->have_recalculated) { return; } $this->have_recalculated = \true; $this->selection_start = $this->file_start; $this->selection_end = $this->file_end + 1; $project_analyzer = \Psalm\Internal\Analyzer\ProjectAnalyzer::getInstance(); $codebase = $project_analyzer->getCodebase(); $file_contents = $codebase->getFileContents($this->file_path); $file_length = \strlen($file_contents); $search_limit = $this->single_line ? $this->selection_start : $this->selection_end; if ($search_limit <= $file_length) { $preview_end = \strpos($file_contents, "\n", $search_limit); } else { $preview_end = \false; } // if the string didn't contain a newline if ($preview_end === \false) { $preview_end = $this->selection_end; } $this->preview_end = $preview_end; if ($this->docblock_line_number && $this->docblock_start_line_number && $this->preview_start < $this->selection_start) { $preview_lines = \explode("\n", \substr($file_contents, $this->preview_start, $this->selection_start - $this->preview_start - 1)); $preview_offset = 0; $comment_line_offset = $this->docblock_line_number - $this->docblock_start_line_number; for ($i = 0; $i < $comment_line_offset; ++$i) { $preview_offset += \strlen($preview_lines[$i]) + 1; } if (!isset($preview_lines[$i])) { throw new \Exception('Should have offset'); } $key_line = $preview_lines[$i]; $indentation = (int) \strpos($key_line, '@'); $key_line = \trim(\preg_replace('@\\**/\\s*@', '', \substr($key_line, $indentation))); $this->selection_start = $preview_offset + $indentation + $this->preview_start; $this->selection_end = $this->selection_start + \strlen($key_line); } if ($this->regex_type !== null) { switch ($this->regex_type) { case self::VAR_TYPE: $regex = '/@(psalm-)?var[ \\t]+' . \Psalm\Internal\Analyzer\CommentAnalyzer::TYPE_REGEX . '/'; $match_offset = 2; break; case self::FUNCTION_RETURN_TYPE: $regex = '/\\:\\s+(\\??\\s*[A-Za-z0-9_\\\\\\[\\]]+)/'; $match_offset = 1; break; case self::FUNCTION_PARAM_TYPE: $regex = '/^(\\??\\s*[A-Za-z0-9_\\\\\\[\\]]+)\\s/'; $match_offset = 1; break; case self::FUNCTION_PHPDOC_RETURN_TYPE: $regex = '/@(psalm-)?return[ \\t]+' . \Psalm\Internal\Analyzer\CommentAnalyzer::TYPE_REGEX . '/'; $match_offset = 2; break; case self::FUNCTION_PHPDOC_METHOD: $regex = '/@(psalm-)method[ \\t]+.*/'; $match_offset = 2; break; case self::FUNCTION_PHPDOC_PARAM_TYPE: $regex = '/@(psalm-)?param[ \\t]+' . \Psalm\Internal\Analyzer\CommentAnalyzer::TYPE_REGEX . '/'; $match_offset = 2; break; case self::FUNCTION_PARAM_VAR: $regex = '/(\\$[^ ]*)/'; $match_offset = 1; break; case self::CATCH_VAR: $regex = '/(\\$[^ ^\\)]*)/'; $match_offset = 1; break; default: throw new \UnexpectedValueException('Unrecognised regex type ' . $this->regex_type); } $preview_snippet = \substr($file_contents, $this->selection_start, $this->selection_end - $this->selection_start); if ($this->text) { $regex = '/(' . \str_replace(',', ',[ ]*', \preg_quote($this->text, '/')) . ')/'; $match_offset = 1; } if (\preg_match($regex, $preview_snippet, $matches, \PREG_OFFSET_CAPTURE)) { $this->selection_start = $this->selection_start + (int) $matches[$match_offset][1]; $this->selection_end = $this->selection_start + \strlen((string) $matches[$match_offset][0]); } } // reset preview start to beginning of line $this->preview_start = (int) \strrpos($file_contents, "\n", \min($this->preview_start, $this->selection_start) - \strlen($file_contents)) + 1; $this->selection_start = \max($this->preview_start, $this->selection_start); $this->selection_end = \min($this->preview_end, $this->selection_end); if ($this->preview_end - $this->selection_end > 200) { $this->preview_end = (int) \strrpos($file_contents, "\n", $this->selection_end + 200 - \strlen($file_contents)); // if the line is over 200 characters long if ($this->preview_end < $this->selection_end) { $this->preview_end = $this->selection_end + 50; } } $this->snippet = \substr($file_contents, $this->preview_start, $this->preview_end - $this->preview_start); $this->text = \substr($file_contents, $this->selection_start, $this->selection_end - $this->selection_start); // reset preview start to beginning of line $this->column_from = $this->selection_start - (int) \strrpos($file_contents, "\n", $this->selection_start - \strlen($file_contents)); $newlines = \substr_count($this->text, "\n"); if ($newlines) { $this->column_to = $this->selection_end - (int) \strrpos($file_contents, "\n", $this->selection_end - \strlen($file_contents)); } else { $this->column_to = $this->column_from + \strlen($this->text); } $this->end_line_number = $this->getLineNumber() + $newlines; } public function getLineNumber() : int { return $this->docblock_line_number ?: $this->raw_line_number; } public function getEndLineNumber() : int { $this->calculateRealLocation(); return $this->end_line_number; } public function getSnippet() : string { $this->calculateRealLocation(); return $this->snippet; } public function getSelectedText() : string { $this->calculateRealLocation(); return (string) $this->text; } public function getColumn() : int { $this->calculateRealLocation(); return $this->column_from; } public function getEndColumn() : int { $this->calculateRealLocation(); return $this->column_to; } /** * @return array{0: int, 1: int} */ public function getSelectionBounds() : array { $this->calculateRealLocation(); return [$this->selection_start, $this->selection_end]; } /** * @return array{0: int, 1: int} */ public function getSnippetBounds() : array { $this->calculateRealLocation(); return [$this->preview_start, $this->preview_end]; } public function getHash() : string { return (string) $this->file_start; } public function getShortSummary() : string { return $this->file_name . ':' . $this->getLineNumber() . ':' . $this->getColumn(); } } config = $config; $this->codebase = $codebase; } public function addStubFile(string $file_name) : void { $this->config->addStubFile($file_name); } public function registerHooksFromClass(string $handler) : void { if (!\class_exists($handler, \false)) { throw new \InvalidArgumentException('Plugins must be loaded before registration'); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterFileAnalysisInterface::class)) { $this->config->after_file_checks[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterMethodCallAnalysisInterface::class)) { $this->config->after_method_checks[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterFunctionCallAnalysisInterface::class)) { $this->config->after_function_checks[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterEveryFunctionCallAnalysisInterface::class)) { $this->config->after_every_function_checks[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterExpressionAnalysisInterface::class)) { $this->config->after_expression_checks[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterStatementAnalysisInterface::class)) { $this->config->after_statement_checks[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterClassLikeExistenceCheckInterface::class)) { $this->config->after_classlike_exists_checks[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterClassLikeAnalysisInterface::class)) { $this->config->after_classlike_checks[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterClassLikeVisitInterface::class)) { $this->config->after_visit_classlikes[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterCodebasePopulatedInterface::class)) { $this->config->after_codebase_populated[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\BeforeFileAnalysisInterface::class)) { $this->config->before_file_checks[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\PropertyExistenceProviderInterface::class)) { $this->codebase->properties->property_existence_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\PropertyVisibilityProviderInterface::class)) { $this->codebase->properties->property_visibility_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\PropertyTypeProviderInterface::class)) { $this->codebase->properties->property_type_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\MethodExistenceProviderInterface::class)) { $this->codebase->methods->existence_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\MethodVisibilityProviderInterface::class)) { $this->codebase->methods->visibility_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\MethodReturnTypeProviderInterface::class)) { $this->codebase->methods->return_type_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\MethodParamsProviderInterface::class)) { $this->codebase->methods->params_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\FunctionExistenceProviderInterface::class)) { $this->codebase->functions->existence_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\FunctionParamsProviderInterface::class)) { $this->codebase->functions->params_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\FunctionReturnTypeProviderInterface::class)) { $this->codebase->functions->return_type_provider->registerClass($handler); } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterAnalysisInterface::class)) { $this->config->after_analysis[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\StringInterpreterInterface::class)) { $this->config->string_interpreters[$handler] = $handler; } if (\is_subclass_of($handler, \Psalm\Plugin\Hook\AfterFunctionLikeAnalysisInterface::class)) { $this->config->after_functionlike_checks[$handler] = $handler; } } } */ class CommitInfo { /** * Commit ID. * * @var null|string */ protected $id; /** * Author name. * * @var null|string */ protected $author_name; /** * Author email. * * @var null|string */ protected $author_email; /** * Committer name. * * @var null|string */ protected $committer_name; /** * Committer email. * * @var null|string */ protected $committer_email; /** * Commit message. * * @var null|string */ protected $message; /** * Commit message. * * @var null|int */ protected $date; public function toArray() : array { return ['id' => $this->id, 'author_name' => $this->author_name, 'author_email' => $this->author_email, 'committer_name' => $this->committer_name, 'committer_email' => $this->committer_email, 'message' => $this->message, 'date' => $this->date]; } // accessor /** * Set commit ID. */ public function setId(string $id) : self { $this->id = $id; return $this; } /** * Return commit ID. * */ public function getId() : ?string { return $this->id; } /** * Set author name. */ public function setAuthorName(string $author_name) : self { $this->author_name = $author_name; return $this; } /** * Return author name. * */ public function getAuthorName() : ?string { return $this->author_name; } /** * Set author email. * */ public function setAuthorEmail(string $author_email) : self { $this->author_email = $author_email; return $this; } /** * Return author email. * */ public function getAuthorEmail() : ?string { return $this->author_email; } /** * Set committer name. */ public function setCommitterName(string $committer_name) : self { $this->committer_name = $committer_name; return $this; } /** * Return committer name. * */ public function getCommitterName() : ?string { return $this->committer_name; } /** * Set committer email. */ public function setCommitterEmail(string $committer_email) : self { $this->committer_email = $committer_email; return $this; } /** * Return committer email. * */ public function getCommitterEmail() : ?string { return $this->committer_email; } /** * Set commit message. */ public function setMessage(string $message) : self { $this->message = $message; return $this; } /** * Return commit message. * */ public function getMessage() : ?string { return $this->message; } /** * Set commit date */ public function setDate(int $date) : self { $this->date = $date; return $this; } /** * Return commit date. * */ public function getDate() : ?int { return $this->date; } } */ class GitInfo extends \Psalm\SourceControl\SourceControlInfo { /** * Branch name. * * @var string */ protected $branch; /** * Head. * * @var CommitInfo */ protected $head; /** * Remote. * * @var RemoteInfo[] */ protected $remotes; /** * Constructor. * * @param string $branch branch name * @param CommitInfo $head hEAD commit * @param RemoteInfo[] $remotes remote repositories */ public function __construct(string $branch, \Psalm\SourceControl\Git\CommitInfo $head, array $remotes) { $this->branch = $branch; $this->head = $head; $this->remotes = $remotes; } public function toArray() : array { $remotes = []; foreach ($this->remotes as $remote) { $remotes[] = $remote->toArray(); } return ['branch' => $this->branch, 'head' => $this->head->toArray(), 'remotes' => $remotes]; } // accessor /** * Return branch name. * */ public function getBranch() : string { return $this->branch; } /** * Return HEAD commit. * */ public function getHead() : \Psalm\SourceControl\Git\CommitInfo { return $this->head; } /** * Return remote repositories. * * @return RemoteInfo[] */ public function getRemotes() : array { return $this->remotes; } } */ class RemoteInfo { /** * Remote name. * * @var null|string */ protected $name; /** * Remote URL. * * @var null|string */ protected $url; public function toArray() : array { return ['name' => $this->name, 'url' => $this->url]; } // accessor /** * Set remote name. * * @param string $name remote name * * @return $this */ public function setName(string $name) : \Psalm\SourceControl\Git\RemoteInfo { $this->name = $name; return $this; } /** * Return remote name. * */ public function getName() : ?string { return $this->name; } /** * Set remote URL. * * @param string $url remote URL * * @return $this */ public function setUrl(string $url) : \Psalm\SourceControl\Git\RemoteInfo { $this->url = $url; return $this; } /** * Return remote URL. * */ public function getUrl() : ?string { return $this->url; } } ' => [', ''=>''] * alternative signature for the same function * '' => [', ''=>''] * * A '&' in front of the means the arg is always passed by reference. * (i.e. ReflectionParameter->isPassedByReference()) * This was previously only used in cases where the function actually created the * variable in the local scope. * Some reference arguments will have prefixes in to indicate the way the argument is used. * Currently, the only prefixes with meaning are 'rw_' (read-write) and 'w_' (write). * Those prefixes don't mean anything for non-references. * Code using these signatures should remove those prefixes from messages rendered to the user. * 1. '&rw_' indicates that a parameter with a value is expected to be passed in, and may be modified. * Phan will warn if the variable has an incompatible type, or is undefined. * 2. '&w_' indicates that a parameter is expected to be passed in, and the value will be ignored, and may be overwritten. * 3. The absence of a prefix is treated by Phan the same way as having the prefix 'w_' (Some may be changed to 'rw_name'). These will have prefixes added later. * * So, for functions like sort() where technically the arg is by-ref, * indicate the reference param's signature by-ref and read-write, * as `'&rw_array'=>'array'` * so that Phan won't create it in the local scope * * However, for a function like preg_match() where the 3rd arg is an array of sub-pattern matches (and optional), * this arg needs to be marked as by-ref and write-only, as `'&w_matches='=>'array'`. * * A '=' following the indicates this arg is optional. * * The can begin with '...' to indicate the arg is variadic. * '...args=' indicates it is both variadic and optional. * * Some reference arguments will have prefixes in to indicate the way the argument is used. * Currently, the only prefixes with meaning are 'rw_' and 'w_'. * Code using these signatures should remove those prefixes from messages rendered to the user. * 1. '&rw_name' indicates that a parameter with a value is expected to be passed in, and may be modified. * 2. '&w_name' indicates that a parameter is expected to be passed in, and the value will be ignored, and may be overwritten. * * This file contains the signatures for the most recent minor release of PHP supported by phan (php 7.2) * * Changes: * * In Phan 0.12.3, * * - This started using array shapes for union types (array{...}). * * \Phan\Language\UnionType->withFlattenedArrayShapeOrLiteralTypeInstances() may be of help to programmatically convert these to array|array * * - This started using array shapes with optional fields for union types (array{key?:int}). * A `?` after the array shape field's key indicates that the field is optional. * * - This started adding param signatures and return signatures to `callable` types. * E.g. 'usort' => ['bool', '&rw_array_arg'=>'array', 'cmp_function'=>'callable(mixed,mixed):int']. * See NEWS.md for 0.12.3 for possible syntax. A suffix of `=` within `callable(...)` means that a parameter is optional. * * (Phan assumes that callbacks with optional arguments can be cast to callbacks with/without those args (Similar to inheritance checks) * (e.g. callable(T1,T2=) can be cast to callable(T1) or callable(T1,T2), in the same way that a subclass would check). * For some signatures, e.g. set_error_handler, this results in repetition, because callable(T1=) can't cast to callable(T1). * * Sources of stub info: * * 1. Reflection * 2. docs.php.net's SVN repo or website, and examples (See internal/internalsignatures.php) * * See https://secure.php.net/manual/en/copyright.php * * The PHP manual text and comments are covered by the [Creative Commons Attribution 3.0 License](http://creativecommons.org/licenses/by/3.0/legalcode), * copyright (c) the PHP Documentation Group * 3. Various websites documenting individual extensions * 4. PHPStorm stubs (For anything missing from the above sources) * See internal/internalsignatures.php * * Available from https://github.com/JetBrains/phpstorm-stubs under the [Apache 2 license](https://www.apache.org/licenses/LICENSE-2.0) * * @phan-file-suppress PhanPluginMixedKeyNoKey (read by Phan when analyzing this file) * * Note: Some of Phan's inferences about return types are written as plugins for functions/methods where the return type depends on the parameter types. * E.g. src/Phan/Plugin/Internal/DependentReturnTypeOverridePlugin.php is one plugin */ return [ '_' => ['string', 'message'=>'string'], '__halt_compiler' => ['void'], 'abs' => ['int', 'number'=>'int'], 'abs\'1' => ['float', 'number'=>'float'], 'abs\'2' => ['numeric', 'number'=>'numeric'], 'accelerator_get_configuration' => ['array'], 'accelerator_get_scripts' => ['array'], 'accelerator_get_status' => ['array', 'fetch_scripts'=>'bool'], 'accelerator_reset' => [''], 'accelerator_set_status' => ['void', 'status'=>'bool'], 'acos' => ['float', 'number'=>'float'], 'acosh' => ['float', 'number'=>'float'], 'addcslashes' => ['string', 'string'=>'string', 'charlist'=>'string'], 'addslashes' => ['string', 'string'=>'string'], 'AMQPBasicProperties::__construct' => ['void', 'content_type='=>'string', 'content_encoding='=>'string', 'headers='=>'array', 'delivery_mode='=>'int', 'priority='=>'int', 'correlation_id='=>'string', 'reply_to='=>'string', 'expiration='=>'string', 'message_id='=>'string', 'timestamp='=>'int', 'type='=>'string', 'user_id='=>'string', 'app_id='=>'string', 'cluster_id='=>'string'], 'AMQPBasicProperties::getAppId' => ['string'], 'AMQPBasicProperties::getClusterId' => ['string'], 'AMQPBasicProperties::getContentEncoding' => ['string'], 'AMQPBasicProperties::getContentType' => ['string'], 'AMQPBasicProperties::getCorrelationId' => ['string'], 'AMQPBasicProperties::getDeliveryMode' => ['int'], 'AMQPBasicProperties::getExpiration' => ['string'], 'AMQPBasicProperties::getHeaders' => ['array'], 'AMQPBasicProperties::getMessageId' => ['string'], 'AMQPBasicProperties::getPriority' => ['int'], 'AMQPBasicProperties::getReplyTo' => ['string'], 'AMQPBasicProperties::getTimestamp' => ['string'], 'AMQPBasicProperties::getType' => ['string'], 'AMQPBasicProperties::getUserId' => ['string'], 'AMQPChannel::__construct' => ['void', 'amqp_connection'=>'AMQPConnection'], 'AMQPChannel::basicRecover' => ['', 'requeue='=>'bool'], 'AMQPChannel::close' => [''], 'AMQPChannel::commitTransaction' => ['bool'], 'AMQPChannel::confirmSelect' => [''], 'AMQPChannel::getChannelId' => ['int'], 'AMQPChannel::getConnection' => ['AMQPConnection'], 'AMQPChannel::getConsumers' => ['AMQPQueue[]'], 'AMQPChannel::getPrefetchCount' => ['int'], 'AMQPChannel::getPrefetchSize' => ['int'], 'AMQPChannel::isConnected' => ['bool'], 'AMQPChannel::qos' => ['bool', 'size'=>'int', 'count'=>'int'], 'AMQPChannel::rollbackTransaction' => ['bool'], 'AMQPChannel::setConfirmCallback' => ['', 'ack_callback='=>'?callable', 'nack_callback='=>'?callable'], 'AMQPChannel::setPrefetchCount' => ['bool', 'count'=>'int'], 'AMQPChannel::setPrefetchSize' => ['bool', 'size'=>'int'], 'AMQPChannel::setReturnCallback' => ['', 'return_callback='=>'?callable'], 'AMQPChannel::startTransaction' => ['bool'], 'AMQPChannel::waitForBasicReturn' => ['', 'timeout='=>'float'], 'AMQPChannel::waitForConfirm' => ['', 'timeout='=>'float'], 'AMQPConnection::__construct' => ['void', 'credentials='=>'array'], 'AMQPConnection::connect' => ['bool'], 'AMQPConnection::disconnect' => ['bool'], 'AMQPConnection::getCACert' => ['string'], 'AMQPConnection::getCert' => ['string'], 'AMQPConnection::getHeartbeatInterval' => ['int'], 'AMQPConnection::getHost' => ['string'], 'AMQPConnection::getKey' => ['string'], 'AMQPConnection::getLogin' => ['string'], 'AMQPConnection::getMaxChannels' => ['?int'], 'AMQPConnection::getMaxFrameSize' => ['int'], 'AMQPConnection::getPassword' => ['string'], 'AMQPConnection::getPort' => ['int'], 'AMQPConnection::getReadTimeout' => ['float'], 'AMQPConnection::getTimeout' => ['float'], 'AMQPConnection::getUsedChannels' => ['int'], 'AMQPConnection::getVerify' => ['bool'], 'AMQPConnection::getVhost' => ['string'], 'AMQPConnection::getWriteTimeout' => ['float'], 'AMQPConnection::isConnected' => ['bool'], 'AMQPConnection::isPersistent' => ['?bool'], 'AMQPConnection::pconnect' => ['bool'], 'AMQPConnection::pdisconnect' => ['bool'], 'AMQPConnection::preconnect' => ['bool'], 'AMQPConnection::reconnect' => ['bool'], 'AMQPConnection::setCACert' => ['', 'cacert'=>'string'], 'AMQPConnection::setCert' => ['', 'cert'=>'string'], 'AMQPConnection::setHost' => ['bool', 'host'=>'string'], 'AMQPConnection::setKey' => ['', 'key'=>'string'], 'AMQPConnection::setLogin' => ['bool', 'login'=>'string'], 'AMQPConnection::setPassword' => ['bool', 'password'=>'string'], 'AMQPConnection::setPort' => ['bool', 'port'=>'int'], 'AMQPConnection::setReadTimeout' => ['bool', 'timeout'=>'int'], 'AMQPConnection::setTimeout' => ['bool', 'timeout'=>'int'], 'AMQPConnection::setVerify' => ['', 'verify'=>'bool'], 'AMQPConnection::setVhost' => ['bool', 'vhost'=>'string'], 'AMQPConnection::setWriteTimeout' => ['bool', 'timeout'=>'int'], 'AMQPDecimal::__construct' => ['void', 'exponent'=>'', 'significand'=>''], 'AMQPDecimal::getExponent' => ['int'], 'AMQPDecimal::getSignificand' => ['int'], 'AMQPEnvelope::__construct' => ['void'], 'AMQPEnvelope::getAppId' => ['string'], 'AMQPEnvelope::getBody' => ['string'], 'AMQPEnvelope::getClusterId' => ['string'], 'AMQPEnvelope::getConsumerTag' => ['string'], 'AMQPEnvelope::getContentEncoding' => ['string'], 'AMQPEnvelope::getContentType' => ['string'], 'AMQPEnvelope::getCorrelationId' => ['string'], 'AMQPEnvelope::getDeliveryMode' => ['int'], 'AMQPEnvelope::getDeliveryTag' => ['string'], 'AMQPEnvelope::getExchangeName' => ['string'], 'AMQPEnvelope::getExpiration' => ['string'], 'AMQPEnvelope::getHeader' => ['string|false', 'header_key'=>'string'], 'AMQPEnvelope::getHeaders' => ['array'], 'AMQPEnvelope::getMessageId' => ['string'], 'AMQPEnvelope::getPriority' => ['int'], 'AMQPEnvelope::getReplyTo' => ['string'], 'AMQPEnvelope::getRoutingKey' => ['string'], 'AMQPEnvelope::getTimeStamp' => ['string'], 'AMQPEnvelope::getType' => ['string'], 'AMQPEnvelope::getUserId' => ['string'], 'AMQPEnvelope::hasHeader' => ['bool', 'header_key'=>'string'], 'AMQPEnvelope::isRedelivery' => ['bool'], 'AMQPExchange::__construct' => ['void', 'amqp_channel'=>'AMQPChannel'], 'AMQPExchange::bind' => ['bool', 'exchange_name'=>'string', 'routing_key='=>'string', 'arguments='=>'array'], 'AMQPExchange::declareExchange' => ['bool'], 'AMQPExchange::delete' => ['bool', 'exchangeName='=>'string', 'flags='=>'int'], 'AMQPExchange::getArgument' => ['int|string|false', 'key'=>'string'], 'AMQPExchange::getArguments' => ['array'], 'AMQPExchange::getChannel' => ['AMQPChannel'], 'AMQPExchange::getConnection' => ['AMQPConnection'], 'AMQPExchange::getFlags' => ['int'], 'AMQPExchange::getName' => ['string'], 'AMQPExchange::getType' => ['string'], 'AMQPExchange::hasArgument' => ['bool', 'key'=>'string'], 'AMQPExchange::publish' => ['bool', 'message'=>'string', 'routing_key='=>'string', 'flags='=>'int', 'attributes='=>'array'], 'AMQPExchange::setArgument' => ['bool', 'key'=>'string', 'value'=>'int|string'], 'AMQPExchange::setArguments' => ['bool', 'arguments'=>'array'], 'AMQPExchange::setFlags' => ['bool', 'flags'=>'int'], 'AMQPExchange::setName' => ['bool', 'exchange_name'=>'string'], 'AMQPExchange::setType' => ['bool', 'exchange_type'=>'string'], 'AMQPExchange::unbind' => ['bool', 'exchange_name'=>'string', 'routing_key='=>'string', 'arguments='=>'array'], 'AMQPQueue::__construct' => ['void', 'amqp_channel'=>'AMQPChannel'], 'AMQPQueue::ack' => ['bool', 'delivery_tag'=>'string', 'flags='=>'int'], 'AMQPQueue::bind' => ['bool', 'exchange_name'=>'string', 'routing_key='=>'string', 'arguments='=>'array'], 'AMQPQueue::cancel' => ['bool', 'consumer_tag='=>'string'], 'AMQPQueue::consume' => ['void', 'callback='=>'?callable', 'flags='=>'int', 'consumerTag='=>'string'], 'AMQPQueue::declareQueue' => ['int'], 'AMQPQueue::delete' => ['int', 'flags='=>'int'], 'AMQPQueue::get' => ['AMQPEnvelope|false', 'flags='=>'int'], 'AMQPQueue::getArgument' => ['int|string|false', 'key'=>'string'], 'AMQPQueue::getArguments' => ['array'], 'AMQPQueue::getChannel' => ['AMQPChannel'], 'AMQPQueue::getConnection' => ['AMQPConnection'], 'AMQPQueue::getConsumerTag' => ['?string'], 'AMQPQueue::getFlags' => ['int'], 'AMQPQueue::getName' => ['string'], 'AMQPQueue::hasArgument' => ['bool', 'key'=>'string'], 'AMQPQueue::nack' => ['bool', 'delivery_tag'=>'string', 'flags='=>'int'], 'AMQPQueue::purge' => ['bool'], 'AMQPQueue::reject' => ['bool', 'delivery_tag'=>'string', 'flags='=>'int'], 'AMQPQueue::setArgument' => ['bool', 'key'=>'string', 'value'=>'mixed'], 'AMQPQueue::setArguments' => ['bool', 'arguments'=>'array'], 'AMQPQueue::setFlags' => ['bool', 'flags'=>'int'], 'AMQPQueue::setName' => ['bool', 'queue_name'=>'string'], 'AMQPQueue::unbind' => ['bool', 'exchange_name'=>'string', 'routing_key='=>'string', 'arguments='=>'array'], 'AMQPTimestamp::__construct' => ['void', 'timestamp'=>'string'], 'AMQPTimestamp::__toString' => ['string'], 'AMQPTimestamp::getTimestamp' => ['string'], 'apache_child_terminate' => ['bool'], 'apache_get_modules' => ['array'], 'apache_get_version' => ['string|false'], 'apache_getenv' => ['string|false', 'variable'=>'string', 'walk_to_top='=>'bool'], 'apache_lookup_uri' => ['object', 'filename'=>'string'], 'apache_note' => ['string|false', 'note_name'=>'string', 'note_value='=>'string'], 'apache_request_headers' => ['array|false'], 'apache_reset_timeout' => ['bool'], 'apache_response_headers' => ['array|false'], 'apache_setenv' => ['bool', 'variable'=>'string', 'value'=>'string', 'walk_to_top='=>'bool'], 'apc_add' => ['bool', 'key'=>'string', 'var'=>'mixed', 'ttl='=>'int'], 'apc_add\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'apc_bin_dump' => ['string|false|null', 'files='=>'array', 'user_vars='=>'array'], 'apc_bin_dumpfile' => ['int|false', 'files'=>'array', 'user_vars'=>'array', 'filename'=>'string', 'flags='=>'int', 'context='=>'resource'], 'apc_bin_load' => ['bool', 'data'=>'string', 'flags='=>'int'], 'apc_bin_loadfile' => ['bool', 'filename'=>'string', 'context='=>'resource', 'flags='=>'int'], 'apc_cache_info' => ['array|false', 'cache_type='=>'string', 'limited='=>'bool'], 'apc_cas' => ['bool', 'key'=>'string', 'old'=>'int', 'new'=>'int'], 'apc_clear_cache' => ['bool', 'cache_type='=>'string'], 'apc_compile_file' => ['bool', 'filename'=>'string', 'atomic='=>'bool'], 'apc_dec' => ['int|false', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool'], 'apc_define_constants' => ['bool', 'key'=>'string', 'constants'=>'array', 'case_sensitive='=>'bool'], 'apc_delete' => ['bool', 'key'=>'string|string[]|APCIterator'], 'apc_delete_file' => ['bool|string[]', 'keys'=>'mixed'], 'apc_exists' => ['bool', 'keys'=>'string'], 'apc_exists\'1' => ['array', 'keys'=>'string[]'], 'apc_fetch' => ['mixed|false', 'key'=>'string', '&w_success='=>'bool'], 'apc_fetch\'1' => ['array|false', 'key'=>'string[]', '&w_success='=>'bool'], 'apc_inc' => ['int|false', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool'], 'apc_load_constants' => ['bool', 'key'=>'string', 'case_sensitive='=>'bool'], 'apc_sma_info' => ['array|false', 'limited='=>'bool'], 'apc_store' => ['bool', 'key'=>'string', 'var'=>'', 'ttl='=>'int'], 'apc_store\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'APCIterator::__construct' => ['void', 'cache'=>'string', 'search='=>'null|string|string[]', 'format='=>'int', 'chunk_size='=>'int', 'list='=>'int'], 'APCIterator::current' => ['mixed|false'], 'APCIterator::getTotalCount' => ['int|false'], 'APCIterator::getTotalHits' => ['int|false'], 'APCIterator::getTotalSize' => ['int|false'], 'APCIterator::key' => ['string'], 'APCIterator::next' => ['void'], 'APCIterator::rewind' => ['void'], 'APCIterator::valid' => ['bool'], 'apcu_add' => ['bool', 'key'=>'string', 'var'=>'', 'ttl='=>'int'], 'apcu_add\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'apcu_cache_info' => ['array|false', 'limited='=>'bool'], 'apcu_cas' => ['bool', 'key'=>'string', 'old'=>'int', 'new'=>'int'], 'apcu_clear_cache' => ['bool'], 'apcu_dec' => ['int|false', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool', 'ttl='=>'int'], 'apcu_delete' => ['bool', 'key'=>'string|APCuIterator'], 'apcu_delete\'1' => ['list', 'key'=>'string[]'], 'apcu_enabled' => ['bool'], 'apcu_entry' => ['mixed', 'key'=>'string', 'generator'=>'callable', 'ttl='=>'int'], 'apcu_exists' => ['bool', 'keys'=>'string'], 'apcu_exists\'1' => ['array', 'keys'=>'string[]'], 'apcu_fetch' => ['mixed|false', 'key'=>'string', '&w_success='=>'bool'], 'apcu_fetch\'1' => ['array|false', 'key'=>'string[]', '&w_success='=>'bool'], 'apcu_inc' => ['int|false', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool', 'ttl='=>'int'], 'apcu_key_info' => ['?array', 'key'=>'string'], 'apcu_sma_info' => ['array|false', 'limited='=>'bool'], 'apcu_store' => ['bool', 'key'=>'string', 'var='=>'', 'ttl='=>'int'], 'apcu_store\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'APCuIterator::__construct' => ['void', 'search='=>'string|string[]|null', 'format='=>'int', 'chunk_size='=>'int', 'list='=>'int'], 'APCuIterator::current' => ['mixed'], 'APCuIterator::getTotalCount' => ['int'], 'APCuIterator::getTotalHits' => ['int'], 'APCuIterator::getTotalSize' => ['int'], 'APCuIterator::key' => ['string'], 'APCuIterator::next' => ['void'], 'APCuIterator::rewind' => ['void'], 'APCuIterator::valid' => ['bool'], 'apd_breakpoint' => ['bool', 'debug_level'=>'int'], 'apd_callstack' => ['array'], 'apd_clunk' => ['void', 'warning'=>'string', 'delimiter='=>'string'], 'apd_continue' => ['bool', 'debug_level'=>'int'], 'apd_croak' => ['void', 'warning'=>'string', 'delimiter='=>'string'], 'apd_dump_function_table' => ['void'], 'apd_dump_persistent_resources' => ['array'], 'apd_dump_regular_resources' => ['array'], 'apd_echo' => ['bool', 'output'=>'string'], 'apd_get_active_symbols' => ['array'], 'apd_set_pprof_trace' => ['string', 'dump_directory='=>'string', 'fragment='=>'string'], 'apd_set_session' => ['void', 'debug_level'=>'int'], 'apd_set_session_trace' => ['void', 'debug_level'=>'int', 'dump_directory='=>'string'], 'apd_set_session_trace_socket' => ['bool', 'tcp_server'=>'string', 'socket_type'=>'int', 'port'=>'int', 'debug_level'=>'int'], 'AppendIterator::__construct' => ['void'], 'AppendIterator::append' => ['void', 'iterator'=>'Iterator'], 'AppendIterator::current' => ['mixed'], 'AppendIterator::getArrayIterator' => ['ArrayIterator'], 'AppendIterator::getInnerIterator' => ['Iterator'], 'AppendIterator::getIteratorIndex' => ['int'], 'AppendIterator::key' => ['int|string|float|bool'], 'AppendIterator::next' => ['void'], 'AppendIterator::rewind' => ['void'], 'AppendIterator::valid' => ['bool'], 'ArgumentCountError::__clone' => ['void'], 'ArgumentCountError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?Error'], 'ArgumentCountError::__toString' => ['string'], 'ArgumentCountError::__wakeup' => ['void'], 'ArgumentCountError::getCode' => ['int'], 'ArgumentCountError::getFile' => ['string'], 'ArgumentCountError::getLine' => ['int'], 'ArgumentCountError::getMessage' => ['string'], 'ArgumentCountError::getPrevious' => ['?Throwable'], 'ArgumentCountError::getTrace' => ['list>'], 'ArgumentCountError::getTraceAsString' => ['string'], 'ArithmeticError::__clone' => ['void'], 'ArithmeticError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?Error'], 'ArithmeticError::__toString' => ['string'], 'ArithmeticError::__wakeup' => ['void'], 'ArithmeticError::getCode' => ['int'], 'ArithmeticError::getFile' => ['string'], 'ArithmeticError::getLine' => ['int'], 'ArithmeticError::getMessage' => ['string'], 'ArithmeticError::getPrevious' => ['?Throwable'], 'ArithmeticError::getTrace' => ['list>'], 'ArithmeticError::getTraceAsString' => ['string'], 'array_change_key_case' => ['associative-array', 'array'=>'array', 'case='=>'int'], 'array_chunk' => ['list', 'input'=>'array', 'size'=>'int', 'preserve_keys='=>'bool'], 'array_column' => ['array', 'array'=>'array', 'column_key'=>'mixed', 'index_key='=>'mixed'], 'array_combine' => ['array|false', 'keys'=>'string[]|int[]', 'values'=>'array'], 'array_count_values' => ['associative-array', 'array'=>'array'], 'array_diff' => ['associative-array', 'array1'=>'array', 'array2'=>'array', '...args='=>'array'], 'array_diff_assoc' => ['associative-array', 'array1'=>'array', 'array2'=>'array', '...args='=>'array'], 'array_diff_key' => ['associative-array', 'array1'=>'array', 'array2'=>'array', '...args='=>'array'], 'array_diff_uassoc' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'data_comp_func'=>'callable(mixed,mixed):int'], 'array_diff_uassoc\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_diff_ukey' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'key_comp_func'=>'callable(mixed,mixed):int'], 'array_diff_ukey\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_fill' => ['array', 'start_key'=>'int', 'num'=>'int', 'value'=>'mixed'], 'array_fill_keys' => ['array', 'keys'=>'array', 'value'=>'mixed'], 'array_filter' => ['associative-array', 'array'=>'array', 'callback='=>'callable(mixed,mixed=):scalar', 'flag='=>'int'], 'array_flip' => ['associative-array|associative-array', 'array'=>'array'], 'array_intersect' => ['associative-array', 'array1'=>'array', 'array2'=>'array', '...args='=>'array'], 'array_intersect_assoc' => ['associative-array', 'array1'=>'array', 'array2'=>'array', '...args='=>'array'], 'array_intersect_key' => ['associative-array', 'array1'=>'array', 'array2'=>'array', '...args='=>'array'], 'array_intersect_uassoc' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'key_compare_func'=>'callable(mixed,mixed):int'], 'array_intersect_uassoc\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest'=>'array|callable(mixed,mixed):int'], 'array_intersect_ukey' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'key_compare_func'=>'callable(mixed,mixed):int'], 'array_intersect_ukey\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest'=>'array|callable(mixed,mixed):int'], 'array_key_exists' => ['bool', 'key'=>'string|int', 'search'=>'array|ArrayObject'], 'array_key_first' => ['int|string|null', 'array'=>'array'], 'array_key_last' => ['int|string|null', 'array'=>'array'], 'array_keys' => ['list', 'input'=>'array', 'search_value='=>'mixed', 'strict='=>'bool'], 'array_map' => ['array', 'callback'=>'?callable', 'input1'=>'array', '...args='=>'array'], 'array_merge' => ['array', 'array1'=>'array', '...args='=>'array'], 'array_merge_recursive' => ['array', 'array1'=>'array', '...args='=>'array'], 'array_multisort' => ['bool', '&rw_array1'=>'array', 'array1_sort_order='=>'array|int', 'array1_sort_flags='=>'array|int', '...args='=>'array|int'], 'array_pad' => ['array', 'array'=>'array', 'pad_size'=>'int', 'pad_value'=>'mixed'], 'array_pop' => ['mixed', '&rw_stack'=>'array'], 'array_product' => ['int|float', 'array'=>'array'], 'array_push' => ['int', '&rw_stack'=>'array', 'var'=>'mixed', '...vars='=>'mixed'], 'array_rand' => ['int|string|array|array', 'array'=>'non-empty-array', 'num_req'=>'int'], 'array_rand\'1' => ['int|string', 'array'=>'array'], 'array_reduce' => ['mixed', 'array'=>'array', 'callback'=>'callable(mixed,mixed):mixed', 'initial='=>'mixed'], 'array_replace' => ['?array', 'arr1'=>'array', 'arr2'=>'array', '...args='=>'array'], 'array_replace_recursive' => ['array', 'array1'=>'array', 'array2'=>'array', '...args='=>'array'], 'array_reverse' => ['array', 'array'=>'array', 'preserve='=>'bool'], 'array_search' => ['int|string|false', 'needle'=>'mixed', 'haystack'=>'array', 'strict='=>'bool'], 'array_shift' => ['mixed|null', '&rw_stack'=>'array'], 'array_slice' => ['array', 'array'=>'array', 'offset'=>'int', 'length='=>'?int', 'preserve_keys='=>'bool'], 'array_splice' => ['array', '&rw_input'=>'array', 'offset'=>'int', 'length='=>'int', 'replacement='=>'array|string'], 'array_sum' => ['int|float', 'array'=>'array'], 'array_udiff' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'data_comp_func'=>'callable(mixed,mixed):int'], 'array_udiff\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_udiff_assoc' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'key_comp_func'=>'callable(mixed,mixed):int'], 'array_udiff_assoc\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_udiff_uassoc' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'data_comp_func'=>'callable(mixed,mixed):int', 'key_comp_func'=>'callable(mixed,mixed):int'], 'array_udiff_uassoc\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', 'arg5'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_uintersect' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int'], 'array_uintersect\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_uintersect_assoc' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int'], 'array_uintersect_assoc\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable', '...rest='=>'array|callable(mixed,mixed):int'], 'array_uintersect_uassoc' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int', 'key_compare_func'=>'callable(mixed,mixed):int'], 'array_uintersect_uassoc\'1' => ['associative-array', 'array1'=>'array', 'array2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', 'arg5'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_unique' => ['associative-array', 'array'=>'array', 'sort_flags='=>'int'], 'array_unshift' => ['int', '&rw_stack'=>'array', 'var'=>'mixed', '...vars='=>'mixed'], 'array_values' => ['list', 'input'=>'array'], 'array_walk' => ['bool', '&rw_input'=>'array', 'callback'=>'callable', 'userdata='=>'mixed'], 'array_walk_recursive' => ['bool', '&rw_input'=>'array', 'callback'=>'callable', 'userdata='=>'mixed'], 'ArrayAccess::offsetExists' => ['bool', 'offset'=>'mixed'], 'ArrayAccess::offsetGet' => ['mixed', 'offset'=>'mixed'], 'ArrayAccess::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'ArrayAccess::offsetUnset' => ['void', 'offset'=>'mixed'], 'ArrayIterator::__construct' => ['void', 'array='=>'array|object', 'flags='=>'int'], 'ArrayIterator::append' => ['void', 'value'=>'mixed'], 'ArrayIterator::asort' => ['void'], 'ArrayIterator::count' => ['int'], 'ArrayIterator::current' => ['mixed'], 'ArrayIterator::getArrayCopy' => ['array'], 'ArrayIterator::getFlags' => ['int'], 'ArrayIterator::key' => ['int|string|false'], 'ArrayIterator::ksort' => ['void'], 'ArrayIterator::natcasesort' => ['void'], 'ArrayIterator::natsort' => ['void'], 'ArrayIterator::next' => ['void'], 'ArrayIterator::offsetExists' => ['bool', 'index'=>'string|int'], 'ArrayIterator::offsetGet' => ['mixed', 'index'=>'string|int'], 'ArrayIterator::offsetSet' => ['void', 'index'=>'string|int', 'newval'=>'mixed'], 'ArrayIterator::offsetUnset' => ['void', 'index'=>'string|int'], 'ArrayIterator::rewind' => ['void'], 'ArrayIterator::seek' => ['void', 'position'=>'int'], 'ArrayIterator::serialize' => ['string'], 'ArrayIterator::setFlags' => ['void', 'flags'=>'string'], 'ArrayIterator::uasort' => ['void', 'cmp_function'=>'callable(mixed,mixed):int'], 'ArrayIterator::uksort' => ['void', 'cmp_function'=>'callable(mixed,mixed):int'], 'ArrayIterator::unserialize' => ['void', 'serialized'=>'string'], 'ArrayIterator::valid' => ['bool'], 'ArrayObject::__construct' => ['void', 'input='=>'array|object', 'flags='=>'int', 'iterator_class='=>'string'], 'ArrayObject::append' => ['void', 'value'=>'mixed'], 'ArrayObject::asort' => ['void'], 'ArrayObject::count' => ['int'], 'ArrayObject::exchangeArray' => ['array', 'ar'=>'mixed'], 'ArrayObject::getArrayCopy' => ['array'], 'ArrayObject::getFlags' => ['int'], 'ArrayObject::getIterator' => ['ArrayIterator'], 'ArrayObject::getIteratorClass' => ['string'], 'ArrayObject::ksort' => ['void'], 'ArrayObject::natcasesort' => ['void'], 'ArrayObject::natsort' => ['void'], 'ArrayObject::offsetExists' => ['bool', 'index'=>'int|string'], 'ArrayObject::offsetGet' => ['mixed|null', 'index'=>'int|string'], 'ArrayObject::offsetSet' => ['void', 'index'=>'int|string', 'newval'=>'mixed'], 'ArrayObject::offsetUnset' => ['void', 'index'=>'int|string'], 'ArrayObject::serialize' => ['string'], 'ArrayObject::setFlags' => ['void', 'flags'=>'int'], 'ArrayObject::setIteratorClass' => ['void', 'iterator_class'=>'string'], 'ArrayObject::uasort' => ['void', 'cmp_function'=>'callable(mixed,mixed):int'], 'ArrayObject::uksort' => ['void', 'cmp_function'=>'callable(mixed,mixed):int'], 'ArrayObject::unserialize' => ['void', 'serialized'=>'string'], 'arsort' => ['bool', '&rw_array'=>'array', 'sort_flags='=>'int'], 'asin' => ['float', 'number'=>'float'], 'asinh' => ['float', 'number'=>'float'], 'asort' => ['bool', '&rw_array'=>'array', 'sort_flags='=>'int'], 'assert' => ['bool', 'assertion'=>'string|bool', 'description='=>'string|Throwable|null'], 'assert_options' => ['mixed|false', 'what'=>'int', 'value='=>'mixed'], 'ast\get_kind_name' => ['string', 'kind'=>'int'], 'ast\get_metadata' => ['array'], 'ast\get_supported_versions' => ['array', 'exclude_deprecated='=>'bool'], 'ast\kind_uses_flags' => ['bool', 'kind'=>'int'], 'ast\Node::__construct' => ['void', 'kind='=>'int', 'flags='=>'int', 'children='=>'ast\Node\Decl[]|ast\Node[]|int[]|string[]|float[]|bool[]|null[]', 'start_line='=>'int'], 'ast\parse_code' => ['ast\Node', 'code'=>'string', 'version'=>'int', 'filename='=>'string'], 'ast\parse_file' => ['ast\Node', 'filename'=>'string', 'version'=>'int'], 'atan' => ['float', 'number'=>'float'], 'atan2' => ['float', 'y'=>'float', 'x'=>'float'], 'atanh' => ['float', 'number'=>'float'], 'BadFunctionCallException::__clone' => ['void'], 'BadFunctionCallException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?BadFunctionCallException'], 'BadFunctionCallException::__toString' => ['string'], 'BadFunctionCallException::getCode' => ['int'], 'BadFunctionCallException::getFile' => ['string'], 'BadFunctionCallException::getLine' => ['int'], 'BadFunctionCallException::getMessage' => ['string'], 'BadFunctionCallException::getPrevious' => ['?Throwable|?BadFunctionCallException'], 'BadFunctionCallException::getTrace' => ['list>'], 'BadFunctionCallException::getTraceAsString' => ['string'], 'BadMethodCallException::__clone' => ['void'], 'BadMethodCallException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?BadMethodCallException'], 'BadMethodCallException::__toString' => ['string'], 'BadMethodCallException::getCode' => ['int'], 'BadMethodCallException::getFile' => ['string'], 'BadMethodCallException::getLine' => ['int'], 'BadMethodCallException::getMessage' => ['string'], 'BadMethodCallException::getPrevious' => ['?Throwable|?BadMethodCallException'], 'BadMethodCallException::getTrace' => ['list>'], 'BadMethodCallException::getTraceAsString' => ['string'], 'base64_decode' => ['string|false', 'string'=>'string', 'strict='=>'bool'], 'base64_encode' => ['string', 'string'=>'string'], 'base_convert' => ['string', 'number'=>'string', 'frombase'=>'int', 'tobase'=>'int'], 'basename' => ['string', 'path'=>'string', 'suffix='=>'string'], 'bbcode_add_element' => ['bool', 'bbcode_container'=>'resource', 'tag_name'=>'string', 'tag_rules'=>'array'], 'bbcode_add_smiley' => ['bool', 'bbcode_container'=>'resource', 'smiley'=>'string', 'replace_by'=>'string'], 'bbcode_create' => ['resource', 'bbcode_initial_tags='=>'array'], 'bbcode_destroy' => ['bool', 'bbcode_container'=>'resource'], 'bbcode_parse' => ['string', 'bbcode_container'=>'resource', 'to_parse'=>'string'], 'bbcode_set_arg_parser' => ['bool', 'bbcode_container'=>'resource', 'bbcode_arg_parser'=>'resource'], 'bbcode_set_flags' => ['bool', 'bbcode_container'=>'resource', 'flags'=>'int', 'mode='=>'int'], 'bcadd' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bccomp' => ['int', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bcdiv' => ['?numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bcmod' => ['?numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bcmul' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bcompiler_load' => ['bool', 'filename'=>'string'], 'bcompiler_load_exe' => ['bool', 'filename'=>'string'], 'bcompiler_parse_class' => ['bool', 'class'=>'string', 'callback'=>'string'], 'bcompiler_read' => ['bool', 'filehandle'=>'resource'], 'bcompiler_write_class' => ['bool', 'filehandle'=>'resource', 'classname'=>'string', 'extends='=>'string'], 'bcompiler_write_constant' => ['bool', 'filehandle'=>'resource', 'constantname'=>'string'], 'bcompiler_write_exe_footer' => ['bool', 'filehandle'=>'resource', 'startpos'=>'int'], 'bcompiler_write_file' => ['bool', 'filehandle'=>'resource', 'filename'=>'string'], 'bcompiler_write_footer' => ['bool', 'filehandle'=>'resource'], 'bcompiler_write_function' => ['bool', 'filehandle'=>'resource', 'functionname'=>'string'], 'bcompiler_write_functions_from_file' => ['bool', 'filehandle'=>'resource', 'filename'=>'string'], 'bcompiler_write_header' => ['bool', 'filehandle'=>'resource', 'write_ver='=>'string'], 'bcompiler_write_included_filename' => ['bool', 'filehandle'=>'resource', 'filename'=>'string'], 'bcpow' => ['numeric-string', 'base'=>'numeric-string', 'exponent'=>'numeric-string', 'scale='=>'int'], 'bcpowmod' => ['?numeric-string', 'base'=>'numeric-string', 'exponent'=>'numeric-string', 'modulus'=>'numeric-string', 'scale='=>'int'], 'bcscale' => ['int', 'scale='=>'int'], 'bcsqrt' => ['?numeric-string', 'operand'=>'numeric-string', 'scale='=>'int'], 'bcsub' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bin2hex' => ['string', 'data'=>'string'], 'bind_textdomain_codeset' => ['string', 'domain'=>'string', 'codeset'=>'string'], 'bindec' => ['float|int', 'binary_number'=>'string'], 'bindtextdomain' => ['string', 'domain_name'=>'string', 'dir'=>'string'], 'birdstep_autocommit' => ['bool', 'index'=>'int'], 'birdstep_close' => ['bool', 'id'=>'int'], 'birdstep_commit' => ['bool', 'index'=>'int'], 'birdstep_connect' => ['int', 'server'=>'string', 'user'=>'string', 'pass'=>'string'], 'birdstep_exec' => ['int', 'index'=>'int', 'exec_str'=>'string'], 'birdstep_fetch' => ['bool', 'index'=>'int'], 'birdstep_fieldname' => ['string', 'index'=>'int', 'col'=>'int'], 'birdstep_fieldnum' => ['int', 'index'=>'int'], 'birdstep_freeresult' => ['bool', 'index'=>'int'], 'birdstep_off_autocommit' => ['bool', 'index'=>'int'], 'birdstep_result' => ['', 'index'=>'int', 'col'=>''], 'birdstep_rollback' => ['bool', 'index'=>'int'], 'blenc_encrypt' => ['string', 'plaintext'=>'string', 'encodedfile'=>'string', 'encryption_key='=>'string'], 'boolval' => ['bool', 'value'=>'mixed'], 'bson_decode' => ['array', 'bson'=>'string'], 'bson_encode' => ['string', 'anything'=>'mixed'], 'bzclose' => ['bool', 'bz'=>'resource'], 'bzcompress' => ['string|int', 'source'=>'string', 'blocksize100k='=>'int', 'workfactor='=>'int'], 'bzdecompress' => ['string|int', 'source'=>'string', 'small='=>'int'], 'bzerrno' => ['int', 'bz'=>'resource'], 'bzerror' => ['array', 'bz'=>'resource'], 'bzerrstr' => ['string', 'bz'=>'resource'], 'bzflush' => ['bool', 'bz'=>'resource'], 'bzopen' => ['resource|false', 'file'=>'string|resource', 'mode'=>'string'], 'bzread' => ['string|false', 'bz'=>'resource', 'length='=>'int'], 'bzwrite' => ['int|false', 'bz'=>'resource', 'data'=>'string', 'length='=>'int'], 'CachingIterator::__construct' => ['void', 'iterator'=>'Iterator', 'flags='=>''], 'CachingIterator::__toString' => ['string'], 'CachingIterator::count' => ['int'], 'CachingIterator::current' => ['mixed'], 'CachingIterator::getCache' => ['array'], 'CachingIterator::getFlags' => ['int'], 'CachingIterator::getInnerIterator' => ['Iterator'], 'CachingIterator::hasNext' => ['bool'], 'CachingIterator::key' => ['int|string|float|bool'], 'CachingIterator::next' => ['void'], 'CachingIterator::offsetExists' => ['bool', 'index'=>'string'], 'CachingIterator::offsetGet' => ['mixed', 'index'=>'string'], 'CachingIterator::offsetSet' => ['void', 'index'=>'string', 'newval'=>'mixed'], 'CachingIterator::offsetUnset' => ['void', 'index'=>'string'], 'CachingIterator::rewind' => ['void'], 'CachingIterator::setFlags' => ['void', 'flags'=>'int'], 'CachingIterator::valid' => ['bool'], 'Cairo::availableFonts' => ['array'], 'Cairo::availableSurfaces' => ['array'], 'Cairo::statusToString' => ['string', 'status'=>'int'], 'Cairo::version' => ['int'], 'Cairo::versionString' => ['string'], 'cairo_append_path' => ['', 'path'=>'cairopath', 'context'=>'cairocontext'], 'cairo_arc' => ['', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'angle1'=>'float', 'angle2'=>'float', 'context'=>'cairocontext'], 'cairo_arc_negative' => ['', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'angle1'=>'float', 'angle2'=>'float', 'context'=>'cairocontext'], 'cairo_available_fonts' => ['array'], 'cairo_available_surfaces' => ['array'], 'cairo_clip' => ['', 'context'=>'cairocontext'], 'cairo_clip_extents' => ['array', 'context'=>'cairocontext'], 'cairo_clip_preserve' => ['', 'context'=>'cairocontext'], 'cairo_clip_rectangle_list' => ['array', 'context'=>'cairocontext'], 'cairo_close_path' => ['', 'context'=>'cairocontext'], 'cairo_copy_page' => ['', 'context'=>'cairocontext'], 'cairo_copy_path' => ['CairoPath', 'context'=>'cairocontext'], 'cairo_copy_path_flat' => ['CairoPath', 'context'=>'cairocontext'], 'cairo_create' => ['CairoContext', 'surface'=>'cairosurface'], 'cairo_curve_to' => ['', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float', 'context'=>'cairocontext'], 'cairo_device_to_user' => ['array', 'x'=>'float', 'y'=>'float', 'context'=>'cairocontext'], 'cairo_device_to_user_distance' => ['array', 'x'=>'float', 'y'=>'float', 'context'=>'cairocontext'], 'cairo_fill' => ['', 'context'=>'cairocontext'], 'cairo_fill_extents' => ['array', 'context'=>'cairocontext'], 'cairo_fill_preserve' => ['', 'context'=>'cairocontext'], 'cairo_font_extents' => ['array', 'context'=>'cairocontext'], 'cairo_font_face_get_type' => ['int', 'fontface'=>'cairofontface'], 'cairo_font_face_status' => ['int', 'fontface'=>'cairofontface'], 'cairo_font_options_create' => ['CairoFontOptions'], 'cairo_font_options_equal' => ['bool', 'options'=>'cairofontoptions', 'other'=>'cairofontoptions'], 'cairo_font_options_get_antialias' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_get_hint_metrics' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_get_hint_style' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_get_subpixel_order' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_hash' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_merge' => ['void', 'options'=>'cairofontoptions', 'other'=>'cairofontoptions'], 'cairo_font_options_set_antialias' => ['void', 'options'=>'cairofontoptions', 'antialias'=>'int'], 'cairo_font_options_set_hint_metrics' => ['void', 'options'=>'cairofontoptions', 'hint_metrics'=>'int'], 'cairo_font_options_set_hint_style' => ['void', 'options'=>'cairofontoptions', 'hint_style'=>'int'], 'cairo_font_options_set_subpixel_order' => ['void', 'options'=>'cairofontoptions', 'subpixel_order'=>'int'], 'cairo_font_options_status' => ['int', 'options'=>'cairofontoptions'], 'cairo_format_stride_for_width' => ['int', 'format'=>'int', 'width'=>'int'], 'cairo_get_antialias' => ['int', 'context'=>'cairocontext'], 'cairo_get_current_point' => ['array', 'context'=>'cairocontext'], 'cairo_get_dash' => ['array', 'context'=>'cairocontext'], 'cairo_get_dash_count' => ['int', 'context'=>'cairocontext'], 'cairo_get_fill_rule' => ['int', 'context'=>'cairocontext'], 'cairo_get_font_face' => ['', 'context'=>'cairocontext'], 'cairo_get_font_matrix' => ['', 'context'=>'cairocontext'], 'cairo_get_font_options' => ['', 'context'=>'cairocontext'], 'cairo_get_group_target' => ['', 'context'=>'cairocontext'], 'cairo_get_line_cap' => ['int', 'context'=>'cairocontext'], 'cairo_get_line_join' => ['int', 'context'=>'cairocontext'], 'cairo_get_line_width' => ['float', 'context'=>'cairocontext'], 'cairo_get_matrix' => ['', 'context'=>'cairocontext'], 'cairo_get_miter_limit' => ['float', 'context'=>'cairocontext'], 'cairo_get_operator' => ['int', 'context'=>'cairocontext'], 'cairo_get_scaled_font' => ['', 'context'=>'cairocontext'], 'cairo_get_source' => ['', 'context'=>'cairocontext'], 'cairo_get_target' => ['', 'context'=>'cairocontext'], 'cairo_get_tolerance' => ['float', 'context'=>'cairocontext'], 'cairo_glyph_path' => ['', 'glyphs'=>'array', 'context'=>'cairocontext'], 'cairo_has_current_point' => ['bool', 'context'=>'cairocontext'], 'cairo_identity_matrix' => ['', 'context'=>'cairocontext'], 'cairo_image_surface_create' => ['CairoImageSurface', 'format'=>'int', 'width'=>'int', 'height'=>'int'], 'cairo_image_surface_create_for_data' => ['CairoImageSurface', 'data'=>'string', 'format'=>'int', 'width'=>'int', 'height'=>'int', 'stride='=>'int'], 'cairo_image_surface_create_from_png' => ['CairoImageSurface', 'file'=>'string'], 'cairo_image_surface_get_data' => ['string', 'surface'=>'cairoimagesurface'], 'cairo_image_surface_get_format' => ['int', 'surface'=>'cairoimagesurface'], 'cairo_image_surface_get_height' => ['int', 'surface'=>'cairoimagesurface'], 'cairo_image_surface_get_stride' => ['int', 'surface'=>'cairoimagesurface'], 'cairo_image_surface_get_width' => ['int', 'surface'=>'cairoimagesurface'], 'cairo_in_fill' => ['bool', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_in_stroke' => ['bool', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_line_to' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_mask' => ['', 'pattern'=>'cairopattern', 'context'=>'cairocontext'], 'cairo_mask_surface' => ['', 'surface'=>'cairosurface', 'x='=>'string', 'y='=>'string', 'context='=>'cairocontext'], 'cairo_matrix_create_scale' => ['object', 'sx'=>'float', 'sy'=>'float'], 'cairo_matrix_init' => ['object', 'xx='=>'float', 'yx='=>'float', 'xy='=>'float', 'yy='=>'float', 'x0='=>'float', 'y0='=>'float'], 'cairo_matrix_init_identity' => ['object'], 'cairo_matrix_init_rotate' => ['object', 'radians'=>'float'], 'cairo_matrix_init_scale' => ['object', 'sx'=>'float', 'sy'=>'float'], 'cairo_matrix_init_translate' => ['object', 'tx'=>'float', 'ty'=>'float'], 'cairo_matrix_invert' => ['void', 'matrix'=>'cairomatrix'], 'cairo_matrix_multiply' => ['CairoMatrix', 'matrix1'=>'cairomatrix', 'matrix2'=>'cairomatrix'], 'cairo_matrix_rotate' => ['', 'matrix'=>'cairomatrix', 'radians'=>'float'], 'cairo_matrix_scale' => ['', 'sx'=>'float', 'sy'=>'float', 'context'=>'cairocontext'], 'cairo_matrix_transform_distance' => ['array', 'matrix'=>'cairomatrix', 'dx'=>'float', 'dy'=>'float'], 'cairo_matrix_transform_point' => ['array', 'matrix'=>'cairomatrix', 'dx'=>'float', 'dy'=>'float'], 'cairo_matrix_translate' => ['void', 'matrix'=>'cairomatrix', 'tx'=>'float', 'ty'=>'float'], 'cairo_move_to' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_new_path' => ['', 'context'=>'cairocontext'], 'cairo_new_sub_path' => ['', 'context'=>'cairocontext'], 'cairo_paint' => ['', 'context'=>'cairocontext'], 'cairo_paint_with_alpha' => ['', 'alpha'=>'string', 'context'=>'cairocontext'], 'cairo_path_extents' => ['array', 'context'=>'cairocontext'], 'cairo_pattern_add_color_stop_rgb' => ['void', 'pattern'=>'cairogradientpattern', 'offset'=>'float', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'cairo_pattern_add_color_stop_rgba' => ['void', 'pattern'=>'cairogradientpattern', 'offset'=>'float', 'red'=>'float', 'green'=>'float', 'blue'=>'float', 'alpha'=>'float'], 'cairo_pattern_create_for_surface' => ['CairoPattern', 'surface'=>'cairosurface'], 'cairo_pattern_create_linear' => ['CairoPattern', 'x0'=>'float', 'y0'=>'float', 'x1'=>'float', 'y1'=>'float'], 'cairo_pattern_create_radial' => ['CairoPattern', 'x0'=>'float', 'y0'=>'float', 'r0'=>'float', 'x1'=>'float', 'y1'=>'float', 'r1'=>'float'], 'cairo_pattern_create_rgb' => ['CairoPattern', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'cairo_pattern_create_rgba' => ['CairoPattern', 'red'=>'float', 'green'=>'float', 'blue'=>'float', 'alpha'=>'float'], 'cairo_pattern_get_color_stop_count' => ['int', 'pattern'=>'cairogradientpattern'], 'cairo_pattern_get_color_stop_rgba' => ['array', 'pattern'=>'cairogradientpattern', 'index'=>'int'], 'cairo_pattern_get_extend' => ['int', 'pattern'=>'string'], 'cairo_pattern_get_filter' => ['int', 'pattern'=>'cairosurfacepattern'], 'cairo_pattern_get_linear_points' => ['array', 'pattern'=>'cairolineargradient'], 'cairo_pattern_get_matrix' => ['CairoMatrix', 'pattern'=>'cairopattern'], 'cairo_pattern_get_radial_circles' => ['array', 'pattern'=>'cairoradialgradient'], 'cairo_pattern_get_rgba' => ['array', 'pattern'=>'cairosolidpattern'], 'cairo_pattern_get_surface' => ['CairoSurface', 'pattern'=>'cairosurfacepattern'], 'cairo_pattern_get_type' => ['int', 'pattern'=>'cairopattern'], 'cairo_pattern_set_extend' => ['void', 'pattern'=>'string', 'extend'=>'string'], 'cairo_pattern_set_filter' => ['void', 'pattern'=>'cairosurfacepattern', 'filter'=>'int'], 'cairo_pattern_set_matrix' => ['void', 'pattern'=>'cairopattern', 'matrix'=>'cairomatrix'], 'cairo_pattern_status' => ['int', 'pattern'=>'cairopattern'], 'cairo_pdf_surface_create' => ['CairoPdfSurface', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'cairo_pdf_surface_set_size' => ['void', 'surface'=>'cairopdfsurface', 'width'=>'float', 'height'=>'float'], 'cairo_pop_group' => ['', 'context'=>'cairocontext'], 'cairo_pop_group_to_source' => ['', 'context'=>'cairocontext'], 'cairo_ps_get_levels' => ['array'], 'cairo_ps_level_to_string' => ['string', 'level'=>'int'], 'cairo_ps_surface_create' => ['CairoPsSurface', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'cairo_ps_surface_dsc_begin_page_setup' => ['void', 'surface'=>'cairopssurface'], 'cairo_ps_surface_dsc_begin_setup' => ['void', 'surface'=>'cairopssurface'], 'cairo_ps_surface_dsc_comment' => ['void', 'surface'=>'cairopssurface', 'comment'=>'string'], 'cairo_ps_surface_get_eps' => ['bool', 'surface'=>'cairopssurface'], 'cairo_ps_surface_restrict_to_level' => ['void', 'surface'=>'cairopssurface', 'level'=>'int'], 'cairo_ps_surface_set_eps' => ['void', 'surface'=>'cairopssurface', 'level'=>'bool'], 'cairo_ps_surface_set_size' => ['void', 'surface'=>'cairopssurface', 'width'=>'float', 'height'=>'float'], 'cairo_push_group' => ['', 'context'=>'cairocontext'], 'cairo_push_group_with_content' => ['', 'content'=>'string', 'context'=>'cairocontext'], 'cairo_rectangle' => ['', 'x'=>'string', 'y'=>'string', 'width'=>'string', 'height'=>'string', 'context'=>'cairocontext'], 'cairo_rel_curve_to' => ['', 'x1'=>'string', 'y1'=>'string', 'x2'=>'string', 'y2'=>'string', 'x3'=>'string', 'y3'=>'string', 'context'=>'cairocontext'], 'cairo_rel_line_to' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_rel_move_to' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_reset_clip' => ['', 'context'=>'cairocontext'], 'cairo_restore' => ['', 'context'=>'cairocontext'], 'cairo_rotate' => ['', 'sx'=>'string', 'sy'=>'string', 'context'=>'cairocontext', 'angle'=>'string'], 'cairo_save' => ['', 'context'=>'cairocontext'], 'cairo_scale' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_scaled_font_create' => ['CairoScaledFont', 'fontface'=>'cairofontface', 'matrix'=>'cairomatrix', 'ctm'=>'cairomatrix', 'fontoptions'=>'cairofontoptions'], 'cairo_scaled_font_extents' => ['array', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_ctm' => ['CairoMatrix', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_font_face' => ['CairoFontFace', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_font_matrix' => ['CairoFontOptions', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_font_options' => ['CairoFontOptions', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_scale_matrix' => ['CairoMatrix', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_type' => ['int', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_glyph_extents' => ['array', 'scaledfont'=>'cairoscaledfont', 'glyphs'=>'array'], 'cairo_scaled_font_status' => ['int', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_text_extents' => ['array', 'scaledfont'=>'cairoscaledfont', 'text'=>'string'], 'cairo_select_font_face' => ['', 'family'=>'string', 'slant='=>'string', 'weight='=>'string', 'context='=>'cairocontext'], 'cairo_set_antialias' => ['', 'antialias='=>'string', 'context='=>'cairocontext'], 'cairo_set_dash' => ['', 'dashes'=>'array', 'offset='=>'string', 'context='=>'cairocontext'], 'cairo_set_fill_rule' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'cairo_set_font_face' => ['', 'fontface'=>'cairofontface', 'context'=>'cairocontext'], 'cairo_set_font_matrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'cairo_set_font_options' => ['', 'fontoptions'=>'cairofontoptions', 'context'=>'cairocontext'], 'cairo_set_font_size' => ['', 'size'=>'string', 'context'=>'cairocontext'], 'cairo_set_line_cap' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'cairo_set_line_join' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'cairo_set_line_width' => ['', 'width'=>'string', 'context'=>'cairocontext'], 'cairo_set_matrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'cairo_set_miter_limit' => ['', 'limit'=>'string', 'context'=>'cairocontext'], 'cairo_set_operator' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'cairo_set_scaled_font' => ['', 'scaledfont'=>'cairoscaledfont', 'context'=>'cairocontext'], 'cairo_set_source' => ['', 'red'=>'string', 'green'=>'string', 'blue'=>'string', 'alpha'=>'string', 'context'=>'cairocontext', 'pattern'=>'cairopattern'], 'cairo_set_source_surface' => ['', 'surface'=>'cairosurface', 'x='=>'string', 'y='=>'string', 'context='=>'cairocontext'], 'cairo_set_tolerance' => ['', 'tolerance'=>'string', 'context'=>'cairocontext'], 'cairo_show_page' => ['', 'context'=>'cairocontext'], 'cairo_show_text' => ['', 'text'=>'string', 'context'=>'cairocontext'], 'cairo_status' => ['int', 'context'=>'cairocontext'], 'cairo_status_to_string' => ['string', 'status'=>'int'], 'cairo_stroke' => ['', 'context'=>'cairocontext'], 'cairo_stroke_extents' => ['array', 'context'=>'cairocontext'], 'cairo_stroke_preserve' => ['', 'context'=>'cairocontext'], 'cairo_surface_copy_page' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_create_similar' => ['CairoSurface', 'surface'=>'cairosurface', 'content'=>'int', 'width'=>'float', 'height'=>'float'], 'cairo_surface_finish' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_flush' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_get_content' => ['int', 'surface'=>'cairosurface'], 'cairo_surface_get_device_offset' => ['array', 'surface'=>'cairosurface'], 'cairo_surface_get_font_options' => ['CairoFontOptions', 'surface'=>'cairosurface'], 'cairo_surface_get_type' => ['int', 'surface'=>'cairosurface'], 'cairo_surface_mark_dirty' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_mark_dirty_rectangle' => ['void', 'surface'=>'cairosurface', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'cairo_surface_set_device_offset' => ['void', 'surface'=>'cairosurface', 'x'=>'float', 'y'=>'float'], 'cairo_surface_set_fallback_resolution' => ['void', 'surface'=>'cairosurface', 'x'=>'float', 'y'=>'float'], 'cairo_surface_show_page' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_status' => ['int', 'surface'=>'cairosurface'], 'cairo_surface_write_to_png' => ['void', 'surface'=>'cairosurface', 'stream'=>'resource'], 'cairo_svg_get_versions' => ['array'], 'cairo_svg_surface_create' => ['CairoSvgSurface', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'cairo_svg_surface_get_versions' => ['array'], 'cairo_svg_surface_restrict_to_version' => ['void', 'surface'=>'cairosvgsurface', 'version'=>'int'], 'cairo_svg_version_to_string' => ['string', 'version'=>'int'], 'cairo_text_extents' => ['array', 'text'=>'string', 'context'=>'cairocontext'], 'cairo_text_path' => ['', 'string'=>'string', 'context'=>'cairocontext', 'text'=>'string'], 'cairo_transform' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'cairo_translate' => ['', 'tx'=>'string', 'ty'=>'string', 'context'=>'cairocontext', 'x'=>'string', 'y'=>'string'], 'cairo_user_to_device' => ['array', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_user_to_device_distance' => ['array', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_version' => ['int'], 'cairo_version_string' => ['string'], 'CairoContext::__construct' => ['void', 'surface'=>'CairoSurface'], 'CairoContext::appendPath' => ['', 'path'=>'cairopath', 'context'=>'cairocontext'], 'CairoContext::arc' => ['', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'angle1'=>'float', 'angle2'=>'float', 'context'=>'cairocontext'], 'CairoContext::arcNegative' => ['', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'angle1'=>'float', 'angle2'=>'float', 'context'=>'cairocontext'], 'CairoContext::clip' => ['', 'context'=>'cairocontext'], 'CairoContext::clipExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::clipPreserve' => ['', 'context'=>'cairocontext'], 'CairoContext::clipRectangleList' => ['array', 'context'=>'cairocontext'], 'CairoContext::closePath' => ['', 'context'=>'cairocontext'], 'CairoContext::copyPage' => ['', 'context'=>'cairocontext'], 'CairoContext::copyPath' => ['CairoPath', 'context'=>'cairocontext'], 'CairoContext::copyPathFlat' => ['CairoPath', 'context'=>'cairocontext'], 'CairoContext::curveTo' => ['', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float', 'context'=>'cairocontext'], 'CairoContext::deviceToUser' => ['array', 'x'=>'float', 'y'=>'float', 'context'=>'cairocontext'], 'CairoContext::deviceToUserDistance' => ['array', 'x'=>'float', 'y'=>'float', 'context'=>'cairocontext'], 'CairoContext::fill' => ['', 'context'=>'cairocontext'], 'CairoContext::fillExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::fillPreserve' => ['', 'context'=>'cairocontext'], 'CairoContext::fontExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::getAntialias' => ['int', 'context'=>'cairocontext'], 'CairoContext::getCurrentPoint' => ['array', 'context'=>'cairocontext'], 'CairoContext::getDash' => ['array', 'context'=>'cairocontext'], 'CairoContext::getDashCount' => ['int', 'context'=>'cairocontext'], 'CairoContext::getFillRule' => ['int', 'context'=>'cairocontext'], 'CairoContext::getFontFace' => ['', 'context'=>'cairocontext'], 'CairoContext::getFontMatrix' => ['', 'context'=>'cairocontext'], 'CairoContext::getFontOptions' => ['', 'context'=>'cairocontext'], 'CairoContext::getGroupTarget' => ['', 'context'=>'cairocontext'], 'CairoContext::getLineCap' => ['int', 'context'=>'cairocontext'], 'CairoContext::getLineJoin' => ['int', 'context'=>'cairocontext'], 'CairoContext::getLineWidth' => ['float', 'context'=>'cairocontext'], 'CairoContext::getMatrix' => ['', 'context'=>'cairocontext'], 'CairoContext::getMiterLimit' => ['float', 'context'=>'cairocontext'], 'CairoContext::getOperator' => ['int', 'context'=>'cairocontext'], 'CairoContext::getScaledFont' => ['', 'context'=>'cairocontext'], 'CairoContext::getSource' => ['', 'context'=>'cairocontext'], 'CairoContext::getTarget' => ['', 'context'=>'cairocontext'], 'CairoContext::getTolerance' => ['float', 'context'=>'cairocontext'], 'CairoContext::glyphPath' => ['', 'glyphs'=>'array', 'context'=>'cairocontext'], 'CairoContext::hasCurrentPoint' => ['bool', 'context'=>'cairocontext'], 'CairoContext::identityMatrix' => ['', 'context'=>'cairocontext'], 'CairoContext::inFill' => ['bool', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::inStroke' => ['bool', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::lineTo' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::mask' => ['', 'pattern'=>'cairopattern', 'context'=>'cairocontext'], 'CairoContext::maskSurface' => ['', 'surface'=>'cairosurface', 'x='=>'string', 'y='=>'string', 'context='=>'cairocontext'], 'CairoContext::moveTo' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::newPath' => ['', 'context'=>'cairocontext'], 'CairoContext::newSubPath' => ['', 'context'=>'cairocontext'], 'CairoContext::paint' => ['', 'context'=>'cairocontext'], 'CairoContext::paintWithAlpha' => ['', 'alpha'=>'string', 'context'=>'cairocontext'], 'CairoContext::pathExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::popGroup' => ['', 'context'=>'cairocontext'], 'CairoContext::popGroupToSource' => ['', 'context'=>'cairocontext'], 'CairoContext::pushGroup' => ['', 'context'=>'cairocontext'], 'CairoContext::pushGroupWithContent' => ['', 'content'=>'string', 'context'=>'cairocontext'], 'CairoContext::rectangle' => ['', 'x'=>'string', 'y'=>'string', 'width'=>'string', 'height'=>'string', 'context'=>'cairocontext'], 'CairoContext::relCurveTo' => ['', 'x1'=>'string', 'y1'=>'string', 'x2'=>'string', 'y2'=>'string', 'x3'=>'string', 'y3'=>'string', 'context'=>'cairocontext'], 'CairoContext::relLineTo' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::relMoveTo' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::resetClip' => ['', 'context'=>'cairocontext'], 'CairoContext::restore' => ['', 'context'=>'cairocontext'], 'CairoContext::rotate' => ['', 'angle'=>'string', 'context'=>'cairocontext'], 'CairoContext::save' => ['', 'context'=>'cairocontext'], 'CairoContext::scale' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::selectFontFace' => ['', 'family'=>'string', 'slant='=>'string', 'weight='=>'string', 'context='=>'cairocontext'], 'CairoContext::setAntialias' => ['', 'antialias='=>'string', 'context='=>'cairocontext'], 'CairoContext::setDash' => ['', 'dashes'=>'array', 'offset='=>'string', 'context='=>'cairocontext'], 'CairoContext::setFillRule' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'CairoContext::setFontFace' => ['', 'fontface'=>'cairofontface', 'context'=>'cairocontext'], 'CairoContext::setFontMatrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'CairoContext::setFontOptions' => ['', 'fontoptions'=>'cairofontoptions', 'context'=>'cairocontext'], 'CairoContext::setFontSize' => ['', 'size'=>'string', 'context'=>'cairocontext'], 'CairoContext::setLineCap' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'CairoContext::setLineJoin' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'CairoContext::setLineWidth' => ['', 'width'=>'string', 'context'=>'cairocontext'], 'CairoContext::setMatrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'CairoContext::setMiterLimit' => ['', 'limit'=>'string', 'context'=>'cairocontext'], 'CairoContext::setOperator' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'CairoContext::setScaledFont' => ['', 'scaledfont'=>'cairoscaledfont', 'context'=>'cairocontext'], 'CairoContext::setSource' => ['', 'pattern'=>'cairopattern', 'context'=>'cairocontext'], 'CairoContext::setSourceRGB' => ['', 'red'=>'string', 'green'=>'string', 'blue'=>'string', 'context'=>'cairocontext', 'pattern'=>'cairopattern'], 'CairoContext::setSourceRGBA' => ['', 'red'=>'string', 'green'=>'string', 'blue'=>'string', 'alpha'=>'string', 'context'=>'cairocontext', 'pattern'=>'cairopattern'], 'CairoContext::setSourceSurface' => ['', 'surface'=>'cairosurface', 'x='=>'string', 'y='=>'string', 'context='=>'cairocontext'], 'CairoContext::setTolerance' => ['', 'tolerance'=>'string', 'context'=>'cairocontext'], 'CairoContext::showPage' => ['', 'context'=>'cairocontext'], 'CairoContext::showText' => ['', 'text'=>'string', 'context'=>'cairocontext'], 'CairoContext::status' => ['int', 'context'=>'cairocontext'], 'CairoContext::stroke' => ['', 'context'=>'cairocontext'], 'CairoContext::strokeExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::strokePreserve' => ['', 'context'=>'cairocontext'], 'CairoContext::textExtents' => ['array', 'text'=>'string', 'context'=>'cairocontext'], 'CairoContext::textPath' => ['', 'string'=>'string', 'context'=>'cairocontext', 'text'=>'string'], 'CairoContext::transform' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'CairoContext::translate' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::userToDevice' => ['array', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::userToDeviceDistance' => ['array', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoFontFace::__construct' => ['void'], 'CairoFontFace::getType' => ['int'], 'CairoFontFace::status' => ['int', 'fontface'=>'cairofontface'], 'CairoFontOptions::__construct' => ['void'], 'CairoFontOptions::equal' => ['bool', 'other'=>'string'], 'CairoFontOptions::getAntialias' => ['int', 'context'=>'cairocontext'], 'CairoFontOptions::getHintMetrics' => ['int'], 'CairoFontOptions::getHintStyle' => ['int'], 'CairoFontOptions::getSubpixelOrder' => ['int'], 'CairoFontOptions::hash' => ['int'], 'CairoFontOptions::merge' => ['void', 'other'=>'string'], 'CairoFontOptions::setAntialias' => ['', 'antialias='=>'string', 'context='=>'cairocontext'], 'CairoFontOptions::setHintMetrics' => ['void', 'hint_metrics'=>'string'], 'CairoFontOptions::setHintStyle' => ['void', 'hint_style'=>'string'], 'CairoFontOptions::setSubpixelOrder' => ['void', 'subpixel_order'=>'string'], 'CairoFontOptions::status' => ['int', 'context'=>'cairocontext'], 'CairoFormat::strideForWidth' => ['int', 'format'=>'int', 'width'=>'int'], 'CairoGradientPattern::addColorStopRgb' => ['void', 'offset'=>'string', 'red'=>'string', 'green'=>'string', 'blue'=>'string'], 'CairoGradientPattern::addColorStopRgba' => ['void', 'offset'=>'string', 'red'=>'string', 'green'=>'string', 'blue'=>'string', 'alpha'=>'string'], 'CairoGradientPattern::getColorStopCount' => ['int'], 'CairoGradientPattern::getColorStopRgba' => ['array', 'index'=>'string'], 'CairoGradientPattern::getExtend' => ['int'], 'CairoGradientPattern::setExtend' => ['void', 'extend'=>'int'], 'CairoImageSurface::__construct' => ['void', 'format'=>'int', 'width'=>'int', 'height'=>'int'], 'CairoImageSurface::createForData' => ['void', 'data'=>'string', 'format'=>'int', 'width'=>'int', 'height'=>'int', 'stride='=>'int'], 'CairoImageSurface::createFromPng' => ['CairoImageSurface', 'file'=>'string'], 'CairoImageSurface::getData' => ['string'], 'CairoImageSurface::getFormat' => ['int'], 'CairoImageSurface::getHeight' => ['int'], 'CairoImageSurface::getStride' => ['int'], 'CairoImageSurface::getWidth' => ['int'], 'CairoLinearGradient::__construct' => ['void', 'x0'=>'float', 'y0'=>'float', 'x1'=>'float', 'y1'=>'float'], 'CairoLinearGradient::getPoints' => ['array'], 'CairoMatrix::__construct' => ['void', 'xx='=>'float', 'yx='=>'float', 'xy='=>'float', 'yy='=>'float', 'x0='=>'float', 'y0='=>'float'], 'CairoMatrix::initIdentity' => ['object'], 'CairoMatrix::initRotate' => ['object', 'radians'=>'float'], 'CairoMatrix::initScale' => ['object', 'sx'=>'float', 'sy'=>'float'], 'CairoMatrix::initTranslate' => ['object', 'tx'=>'float', 'ty'=>'float'], 'CairoMatrix::invert' => ['void'], 'CairoMatrix::multiply' => ['CairoMatrix', 'matrix1'=>'cairomatrix', 'matrix2'=>'cairomatrix'], 'CairoMatrix::rotate' => ['', 'sx'=>'string', 'sy'=>'string', 'context'=>'cairocontext', 'angle'=>'string'], 'CairoMatrix::scale' => ['', 'sx'=>'float', 'sy'=>'float', 'context'=>'cairocontext'], 'CairoMatrix::transformDistance' => ['array', 'dx'=>'string', 'dy'=>'string'], 'CairoMatrix::transformPoint' => ['array', 'dx'=>'string', 'dy'=>'string'], 'CairoMatrix::translate' => ['', 'tx'=>'string', 'ty'=>'string', 'context'=>'cairocontext', 'x'=>'string', 'y'=>'string'], 'CairoPattern::__construct' => ['void'], 'CairoPattern::getMatrix' => ['', 'context'=>'cairocontext'], 'CairoPattern::getType' => ['int'], 'CairoPattern::setMatrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'CairoPattern::status' => ['int', 'context'=>'cairocontext'], 'CairoPdfSurface::__construct' => ['void', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'CairoPdfSurface::setSize' => ['void', 'width'=>'string', 'height'=>'string'], 'CairoPsSurface::__construct' => ['void', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'CairoPsSurface::dscBeginPageSetup' => ['void'], 'CairoPsSurface::dscBeginSetup' => ['void'], 'CairoPsSurface::dscComment' => ['void', 'comment'=>'string'], 'CairoPsSurface::getEps' => ['bool'], 'CairoPsSurface::getLevels' => ['array'], 'CairoPsSurface::levelToString' => ['string', 'level'=>'int'], 'CairoPsSurface::restrictToLevel' => ['void', 'level'=>'string'], 'CairoPsSurface::setEps' => ['void', 'level'=>'string'], 'CairoPsSurface::setSize' => ['void', 'width'=>'string', 'height'=>'string'], 'CairoRadialGradient::__construct' => ['void', 'x0'=>'float', 'y0'=>'float', 'r0'=>'float', 'x1'=>'float', 'y1'=>'float', 'r1'=>'float'], 'CairoRadialGradient::getCircles' => ['array'], 'CairoScaledFont::__construct' => ['void', 'font_face'=>'CairoFontFace', 'matrix'=>'CairoMatrix', 'ctm'=>'CairoMatrix', 'options'=>'CairoFontOptions'], 'CairoScaledFont::extents' => ['array'], 'CairoScaledFont::getCtm' => ['CairoMatrix'], 'CairoScaledFont::getFontFace' => ['', 'context'=>'cairocontext'], 'CairoScaledFont::getFontMatrix' => ['', 'context'=>'cairocontext'], 'CairoScaledFont::getFontOptions' => ['', 'context'=>'cairocontext'], 'CairoScaledFont::getScaleMatrix' => ['void'], 'CairoScaledFont::getType' => ['int'], 'CairoScaledFont::glyphExtents' => ['array', 'glyphs'=>'string'], 'CairoScaledFont::status' => ['int', 'context'=>'cairocontext'], 'CairoScaledFont::textExtents' => ['array', 'text'=>'string', 'context'=>'cairocontext'], 'CairoSolidPattern::__construct' => ['void', 'red'=>'float', 'green'=>'float', 'blue'=>'float', 'alpha='=>'float'], 'CairoSolidPattern::getRgba' => ['array'], 'CairoSurface::__construct' => ['void'], 'CairoSurface::copyPage' => ['', 'context'=>'cairocontext'], 'CairoSurface::createSimilar' => ['void', 'other'=>'cairosurface', 'content'=>'int', 'width'=>'string', 'height'=>'string'], 'CairoSurface::finish' => ['void'], 'CairoSurface::flush' => ['void'], 'CairoSurface::getContent' => ['int'], 'CairoSurface::getDeviceOffset' => ['array'], 'CairoSurface::getFontOptions' => ['', 'context'=>'cairocontext'], 'CairoSurface::getType' => ['int'], 'CairoSurface::markDirty' => ['void'], 'CairoSurface::markDirtyRectangle' => ['void', 'x'=>'string', 'y'=>'string', 'width'=>'string', 'height'=>'string'], 'CairoSurface::setDeviceOffset' => ['void', 'x'=>'string', 'y'=>'string'], 'CairoSurface::setFallbackResolution' => ['void', 'x'=>'string', 'y'=>'string'], 'CairoSurface::showPage' => ['', 'context'=>'cairocontext'], 'CairoSurface::status' => ['int', 'context'=>'cairocontext'], 'CairoSurface::writeToPng' => ['void', 'file'=>'string'], 'CairoSurfacePattern::__construct' => ['void', 'surface'=>'CairoSurface'], 'CairoSurfacePattern::getExtend' => ['int'], 'CairoSurfacePattern::getFilter' => ['int'], 'CairoSurfacePattern::getSurface' => ['void'], 'CairoSurfacePattern::setExtend' => ['void', 'extend'=>'int'], 'CairoSurfacePattern::setFilter' => ['void', 'filter'=>'string'], 'CairoSvgSurface::__construct' => ['void', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'CairoSvgSurface::getVersions' => ['array'], 'CairoSvgSurface::restrictToVersion' => ['void', 'version'=>'string'], 'CairoSvgSurface::versionToString' => ['string', 'version'=>'int'], 'cal_days_in_month' => ['int', 'calendar'=>'int', 'month'=>'int', 'year'=>'int'], 'cal_from_jd' => ['false|array{date:string,month:int,day:int,year:int,dow:int,abbrevdayname:string,dayname:string,abbrevmonth:string,monthname:string}', 'jd'=>'int', 'calendar'=>'int'], 'cal_info' => ['array', 'calendar='=>'int'], 'cal_to_jd' => ['int', 'calendar'=>'int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'calcul_hmac' => ['string', 'clent'=>'string', 'siretcode'=>'string', 'price'=>'string', 'reference'=>'string', 'validity'=>'string', 'taxation'=>'string', 'devise'=>'string', 'language'=>'string'], 'calculhmac' => ['string', 'clent'=>'string', 'data'=>'string'], 'call_user_func' => ['mixed|false', 'function'=>'callable', '...args='=>'mixed'], 'call_user_func_array' => ['mixed|false', 'function'=>'callable', 'args'=>'list'], 'call_user_method' => ['mixed', 'method_name'=>'string', 'object'=>'object', 'parameter='=>'mixed', '...args='=>'mixed'], 'call_user_method_array' => ['mixed', 'method_name'=>'string', 'object'=>'object', 'params'=>'list'], 'CallbackFilterIterator::__construct' => ['void', 'iterator'=>'Iterator', 'func'=>'callable(mixed):bool|callable(mixed,mixed):bool|callable(mixed,mixed,mixed):bool'], 'CallbackFilterIterator::accept' => ['bool'], 'CallbackFilterIterator::current' => ['mixed'], 'CallbackFilterIterator::getInnerIterator' => ['Iterator'], 'CallbackFilterIterator::key' => ['mixed'], 'CallbackFilterIterator::next' => ['void'], 'CallbackFilterIterator::rewind' => ['void'], 'CallbackFilterIterator::valid' => ['bool'], 'ceil' => ['float|int', 'number'=>'float'], 'chdb::__construct' => ['void', 'pathname'=>'string'], 'chdb::get' => ['string', 'key'=>'string'], 'chdb_create' => ['bool', 'pathname'=>'string', 'data'=>'array'], 'chdir' => ['bool', 'directory'=>'string'], 'checkdate' => ['bool', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'checkdnsrr' => ['bool', 'host'=>'string', 'type='=>'string'], 'chgrp' => ['bool', 'filename'=>'string', 'group'=>'string|int'], 'chmod' => ['bool', 'filename'=>'string', 'mode'=>'int'], 'chop' => ['string', 'string'=>'string', 'character_mask='=>'string'], 'chown' => ['bool', 'filename'=>'string', 'user'=>'string|int'], 'chr' => ['string', 'ascii'=>'int'], 'chroot' => ['bool', 'directory'=>'string'], 'chunk_split' => ['string', 'string'=>'string', 'chunklen='=>'int', 'ending='=>'string'], 'class_alias' => ['bool', 'user_class_name'=>'string', 'alias_name'=>'string', 'autoload='=>'bool'], 'class_exists' => ['bool', 'classname'=>'string', 'autoload='=>'bool'], 'class_implements' => ['array|false', 'what'=>'object|string', 'autoload='=>'bool'], 'class_parents' => ['array|false', 'instance'=>'object|string', 'autoload='=>'bool'], 'class_uses' => ['array|false', 'what'=>'object|string', 'autoload='=>'bool'], 'classkit_import' => ['array', 'filename'=>'string'], 'classkit_method_add' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'args'=>'string', 'code'=>'string', 'flags='=>'int'], 'classkit_method_copy' => ['bool', 'dclass'=>'string', 'dmethod'=>'string', 'sclass'=>'string', 'smethod='=>'string'], 'classkit_method_redefine' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'args'=>'string', 'code'=>'string', 'flags='=>'int'], 'classkit_method_remove' => ['bool', 'classname'=>'string', 'methodname'=>'string'], 'classkit_method_rename' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'newname'=>'string'], 'classObj::__construct' => ['void', 'layer'=>'layerObj', 'class'=>'classObj'], 'classObj::addLabel' => ['int', 'label'=>'labelObj'], 'classObj::convertToString' => ['string'], 'classObj::createLegendIcon' => ['imageObj', 'width'=>'int', 'height'=>'int'], 'classObj::deletestyle' => ['int', 'index'=>'int'], 'classObj::drawLegendIcon' => ['int', 'width'=>'int', 'height'=>'int', 'im'=>'imageObj', 'dstX'=>'int', 'dstY'=>'int'], 'classObj::free' => ['void'], 'classObj::getExpressionString' => ['string'], 'classObj::getLabel' => ['labelObj', 'index'=>'int'], 'classObj::getMetaData' => ['int', 'name'=>'string'], 'classObj::getStyle' => ['styleObj', 'index'=>'int'], 'classObj::getTextString' => ['string'], 'classObj::movestyledown' => ['int', 'index'=>'int'], 'classObj::movestyleup' => ['int', 'index'=>'int'], 'classObj::ms_newClassObj' => ['classObj', 'layer'=>'layerObj', 'class'=>'classObj'], 'classObj::removeLabel' => ['labelObj', 'index'=>'int'], 'classObj::removeMetaData' => ['int', 'name'=>'string'], 'classObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'classObj::setExpression' => ['int', 'expression'=>'string'], 'classObj::setMetaData' => ['int', 'name'=>'string', 'value'=>'string'], 'classObj::settext' => ['int', 'text'=>'string'], 'classObj::updateFromString' => ['int', 'snippet'=>'string'], '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'], 'ClosedGeneratorException::getLine' => ['int'], 'ClosedGeneratorException::getMessage' => ['string'], 'ClosedGeneratorException::getPrevious' => ['Throwable|ClosedGeneratorException|null'], 'ClosedGeneratorException::getTrace' => ['list>'], 'ClosedGeneratorException::getTraceAsString' => ['string'], 'closedir' => ['void', 'dir_handle='=>'resource'], 'closelog' => ['bool'], 'Closure::__construct' => ['void'], 'Closure::__invoke' => ['', '...args='=>''], 'Closure::bind' => ['Closure|false', 'old'=>'Closure', 'to'=>'?object', 'scope='=>'object|string'], 'Closure::bindTo' => ['Closure|false', 'new'=>'?object', 'newscope='=>'object|string'], 'Closure::call' => ['', 'to'=>'object', '...parameters='=>''], 'Closure::fromCallable' => ['Closure', 'callable'=>'callable'], 'clusterObj::convertToString' => ['string'], 'clusterObj::getFilterString' => ['string'], 'clusterObj::getGroupString' => ['string'], 'clusterObj::setFilter' => ['int', 'expression'=>'string'], 'clusterObj::setGroup' => ['int', 'expression'=>'string'], 'Collator::__construct' => ['void', 'locale'=>'string'], 'Collator::asort' => ['bool', '&rw_arr'=>'array', 'sort_flag='=>'int'], 'Collator::compare' => ['int|false', 'string1'=>'string', 'string2'=>'string'], 'Collator::create' => ['?Collator', 'locale'=>'string'], 'Collator::getAttribute' => ['int|false', 'attr'=>'int'], 'Collator::getErrorCode' => ['int'], 'Collator::getErrorMessage' => ['string'], 'Collator::getLocale' => ['string', 'type'=>'int'], 'Collator::getSortKey' => ['string|false', 'string'=>'string'], 'Collator::getStrength' => ['int|false'], 'Collator::setAttribute' => ['bool', 'attr'=>'int', 'value'=>'int'], 'Collator::setStrength' => ['bool', 'strength'=>'int'], 'Collator::sort' => ['bool', '&rw_arr'=>'array', 'sort_flags='=>'int'], 'Collator::sortWithSortKeys' => ['bool', '&rw_arr'=>'array'], 'collator_asort' => ['bool', 'coll'=>'collator', '&rw_arr'=>'array', 'sort_flag='=>'int'], 'collator_compare' => ['int', 'coll'=>'collator', 'string1'=>'string', 'string2'=>'string'], 'collator_create' => ['Collator', 'locale'=>'string'], 'collator_get_attribute' => ['int|false', 'coll'=>'collator', 'attr'=>'int'], 'collator_get_error_code' => ['int', 'coll'=>'collator'], 'collator_get_error_message' => ['string', 'coll'=>'collator'], 'collator_get_locale' => ['string', 'coll'=>'collator', 'type'=>'int'], 'collator_get_sort_key' => ['string', 'coll'=>'collator', 'string'=>'string'], 'collator_get_strength' => ['int|false', 'coll'=>'collator'], 'collator_set_attribute' => ['bool', 'coll'=>'collator', 'attr'=>'int', 'value'=>'int'], 'collator_set_strength' => ['bool', 'coll'=>'collator', 'strength'=>'int'], 'collator_sort' => ['bool', 'coll'=>'collator', '&rw_arr'=>'array', 'sort_flag='=>'int'], 'collator_sort_with_sort_keys' => ['bool', 'coll'=>'collator', '&rw_arr'=>'array'], 'Collectable::isGarbage' => ['bool'], 'Collectable::setGarbage' => ['void'], 'colorObj::setHex' => ['int', 'hex'=>'string'], 'colorObj::toHex' => ['string'], 'COM::__call' => ['', 'name'=>'', 'args'=>''], 'COM::__construct' => ['void', 'module_name'=>'string', 'server_name='=>'mixed', 'codepage='=>'int', 'typelib='=>'string'], 'COM::__get' => ['', 'name'=>''], 'COM::__set' => ['void', 'name'=>'', 'value'=>''], 'com_addref' => [''], 'com_create_guid' => ['string'], 'com_event_sink' => ['bool', 'comobject'=>'VARIANT', 'sinkobject'=>'object', 'sinkinterface='=>'mixed'], 'com_get_active_object' => ['VARIANT', 'progid'=>'string', 'code_page='=>'int'], 'com_isenum' => ['bool', 'com_module'=>'variant'], 'com_load_typelib' => ['bool', 'typelib_name'=>'string', 'case_insensitive='=>'int'], 'com_message_pump' => ['bool', 'timeoutms='=>'int'], 'com_print_typeinfo' => ['bool', 'comobject_or_typelib'=>'object', 'dispinterface='=>'string', 'wantsink='=>'bool'], 'commonmark\cql::__invoke' => ['', 'root'=>'CommonMark\Node', 'handler'=>'callable'], 'commonmark\interfaces\ivisitable::accept' => ['void', 'visitor'=>'CommonMark\Interfaces\IVisitor'], 'commonmark\interfaces\ivisitor::enter' => ['?int|IVisitable', 'visitable'=>'IVisitable'], 'commonmark\interfaces\ivisitor::leave' => ['?int|IVisitable', 'visitable'=>'IVisitable'], 'commonmark\node::accept' => ['void', 'visitor'=>'CommonMark\Interfaces\IVisitor'], 'commonmark\node::appendChild' => ['CommonMark\Node', 'child'=>'CommonMark\Node'], 'commonmark\node::insertAfter' => ['CommonMark\Node', 'sibling'=>'CommonMark\Node'], 'commonmark\node::insertBefore' => ['CommonMark\Node', 'sibling'=>'CommonMark\Node'], 'commonmark\node::prependChild' => ['CommonMark\Node', 'child'=>'CommonMark\Node'], 'commonmark\node::replace' => ['CommonMark\Node', 'target'=>'CommonMark\Node'], 'commonmark\node::unlink' => ['void'], 'commonmark\parse' => ['CommonMark\Node', 'content'=>'string', 'options='=>'int'], 'commonmark\parser::finish' => ['CommonMark\Node'], 'commonmark\parser::parse' => ['void', 'buffer'=>'string'], 'commonmark\render' => ['string', 'node'=>'CommonMark\Node', 'options='=>'int', 'width='=>'int'], 'commonmark\render\html' => ['string', 'node'=>'CommonMark\Node', 'options='=>'int'], 'commonmark\render\latex' => ['string', 'node'=>'CommonMark\Node', 'options='=>'int', 'width='=>'int'], 'commonmark\render\man' => ['string', 'node'=>'CommonMark\Node', 'options='=>'int', 'width='=>'int'], 'commonmark\render\xml' => ['string', 'node'=>'CommonMark\Node', 'options='=>'int'], 'compact' => ['array', 'var_name'=>'string|array', '...var_names='=>'string|array'], 'COMPersistHelper::__construct' => ['void', 'com_object'=>'object'], 'COMPersistHelper::GetCurFile' => ['string'], 'COMPersistHelper::GetCurFileName' => ['string'], 'COMPersistHelper::GetMaxStreamSize' => ['int'], 'COMPersistHelper::InitNew' => ['int'], 'COMPersistHelper::LoadFromFile' => ['bool', 'filename'=>'string', 'flags'=>'int'], 'COMPersistHelper::LoadFromStream' => ['', 'stream'=>''], 'COMPersistHelper::SaveToFile' => ['bool', 'filename'=>'string', 'remember'=>'bool'], 'COMPersistHelper::SaveToStream' => ['int', 'stream'=>''], 'componere\abstract\definition::addInterface' => ['Componere\Abstract\Definition', 'interface'=>'string'], 'componere\abstract\definition::addMethod' => ['Componere\Abstract\Definition', 'name'=>'string', 'method'=>'Componere\Method'], 'componere\abstract\definition::addTrait' => ['Componere\Abstract\Definition', 'trait'=>'string'], 'componere\abstract\definition::getReflector' => ['ReflectionClass'], 'componere\cast' => ['object', 'arg1'=>'string', 'object'=>'object'], 'componere\cast_by_ref' => ['object', 'arg1'=>'string', 'object'=>'object'], 'componere\definition::addConstant' => ['Componere\Definition', 'name'=>'string', 'value'=>'Componere\Value'], 'componere\definition::addProperty' => ['Componere\Definition', 'name'=>'string', 'value'=>'Componere\Value'], 'componere\definition::getClosure' => ['Closure', 'name'=>'string'], 'componere\definition::getClosures' => ['Closure[]'], 'componere\definition::isRegistered' => ['bool'], 'componere\definition::register' => ['void'], 'componere\method::getReflector' => ['ReflectionMethod'], 'componere\method::setPrivate' => ['Method'], 'componere\method::setProtected' => ['Method'], 'componere\method::setStatic' => ['Method'], 'componere\patch::apply' => ['void'], 'componere\patch::derive' => ['Componere\Patch', 'instance'=>'object'], 'componere\patch::getClosure' => ['Closure', 'name'=>'string'], 'componere\patch::getClosures' => ['Closure[]'], 'componere\patch::isApplied' => ['bool'], 'componere\patch::revert' => ['void'], 'componere\value::hasDefault' => ['bool'], 'componere\value::isPrivate' => ['bool'], 'componere\value::isProtected' => ['bool'], 'componere\value::isStatic' => ['bool'], 'componere\value::setPrivate' => ['Value'], 'componere\value::setProtected' => ['Value'], 'componere\value::setStatic' => ['Value'], 'Cond::broadcast' => ['bool', 'condition'=>'long'], 'Cond::create' => ['long'], 'Cond::destroy' => ['bool', 'condition'=>'long'], 'Cond::signal' => ['bool', 'condition'=>'long'], 'Cond::wait' => ['bool', 'condition'=>'long', 'mutex'=>'long', 'timeout='=>'long'], 'confirm_pdo_ibm_compiled' => [''], 'connection_aborted' => ['int'], 'connection_status' => ['int'], 'connection_timeout' => ['int'], 'constant' => ['mixed', 'const_name'=>'string'], 'convert_cyr_string' => ['string', 'string'=>'string', 'from'=>'string', 'to'=>'string'], 'convert_uudecode' => ['string', 'data'=>'string'], 'convert_uuencode' => ['string', 'data'=>'string'], 'copy' => ['bool', 'source_file'=>'string', 'destination_file'=>'string', 'context='=>'resource'], 'cos' => ['float', 'number'=>'float'], 'cosh' => ['float', 'number'=>'float'], 'Couchbase\AnalyticsQuery::__construct' => ['void'], 'Couchbase\AnalyticsQuery::fromString' => ['Couchbase\AnalyticsQuery', 'statement'=>'string'], 'Couchbase\basicDecoderV1' => ['mixed', 'bytes'=>'string', 'flags'=>'int', 'datatype'=>'int', 'options'=>'array'], 'Couchbase\basicEncoderV1' => ['array', 'value'=>'mixed', 'options'=>'array'], 'Couchbase\BooleanFieldSearchQuery::__construct' => ['void'], 'Couchbase\BooleanFieldSearchQuery::boost' => ['Couchbase\BooleanFieldSearchQuery', 'boost'=>'float'], 'Couchbase\BooleanFieldSearchQuery::field' => ['Couchbase\BooleanFieldSearchQuery', 'field'=>'string'], 'Couchbase\BooleanFieldSearchQuery::jsonSerialize' => ['array'], 'Couchbase\BooleanSearchQuery::__construct' => ['void'], 'Couchbase\BooleanSearchQuery::boost' => ['Couchbase\BooleanSearchQuery', 'boost'=>'float'], 'Couchbase\BooleanSearchQuery::jsonSerialize' => ['array'], 'Couchbase\BooleanSearchQuery::must' => ['Couchbase\BooleanSearchQuery', '...queries='=>'array'], 'Couchbase\BooleanSearchQuery::mustNot' => ['Couchbase\BooleanSearchQuery', '...queries='=>'array'], 'Couchbase\BooleanSearchQuery::should' => ['Couchbase\BooleanSearchQuery', '...queries='=>'array'], 'Couchbase\Bucket::__construct' => ['void'], 'Couchbase\Bucket::__get' => ['int', 'name'=>'string'], 'Couchbase\Bucket::__set' => ['int', 'name'=>'string', 'value'=>'int'], 'Couchbase\Bucket::append' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\Bucket::counter' => ['Couchbase\Document|array', 'ids'=>'array|string', 'delta='=>'int', 'options='=>'array'], 'Couchbase\Bucket::decryptFields' => ['array', 'document'=>'array', 'fieldOptions'=>'', 'prefix='=>'string'], 'Couchbase\Bucket::diag' => ['array', 'reportId='=>'string'], 'Couchbase\Bucket::encryptFields' => ['array', 'document'=>'array', 'fieldOptions'=>'', 'prefix='=>'string'], 'Couchbase\Bucket::get' => ['Couchbase\Document|array', 'ids'=>'array|string', 'options='=>'array'], 'Couchbase\Bucket::getAndLock' => ['Couchbase\Document|array', 'ids'=>'array|string', 'lockTime'=>'int', 'options='=>'array'], 'Couchbase\Bucket::getAndTouch' => ['Couchbase\Document|array', 'ids'=>'array|string', 'expiry'=>'int', 'options='=>'array'], 'Couchbase\Bucket::getFromReplica' => ['Couchbase\Document|array', 'ids'=>'array|string', 'options='=>'array'], 'Couchbase\Bucket::getName' => ['string'], 'Couchbase\Bucket::insert' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\Bucket::listExists' => ['bool', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::listGet' => ['mixed', 'id'=>'string', 'index'=>'int'], 'Couchbase\Bucket::listPush' => ['', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::listRemove' => ['', 'id'=>'string', 'index'=>'int'], 'Couchbase\Bucket::listSet' => ['', 'id'=>'string', 'index'=>'int', 'value'=>'mixed'], 'Couchbase\Bucket::listShift' => ['', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::listSize' => ['int', 'id'=>'string'], 'Couchbase\Bucket::lookupIn' => ['Couchbase\LookupInBuilder', 'id'=>'string'], 'Couchbase\Bucket::manager' => ['Couchbase\BucketManager'], 'Couchbase\Bucket::mapAdd' => ['', 'id'=>'string', 'key'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::mapGet' => ['mixed', 'id'=>'string', 'key'=>'string'], 'Couchbase\Bucket::mapRemove' => ['', 'id'=>'string', 'key'=>'string'], 'Couchbase\Bucket::mapSize' => ['int', 'id'=>'string'], 'Couchbase\Bucket::mutateIn' => ['Couchbase\MutateInBuilder', 'id'=>'string', 'cas'=>'string'], 'Couchbase\Bucket::ping' => ['array', 'services='=>'int', 'reportId='=>'string'], 'Couchbase\Bucket::prepend' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\Bucket::query' => ['object', 'query'=>'Couchbase\AnalyticsQuery|Couchbase\N1qlQuery|Couchbase\SearchQuery|Couchbase\SpatialViewQuery|Couchbase\ViewQuery', 'jsonAsArray='=>'bool'], 'Couchbase\Bucket::queueAdd' => ['', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::queueExists' => ['bool', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::queueRemove' => ['mixed', 'id'=>'string'], 'Couchbase\Bucket::queueSize' => ['int', 'id'=>'string'], 'Couchbase\Bucket::remove' => ['Couchbase\Document|array', 'ids'=>'array|string', 'options='=>'array'], 'Couchbase\Bucket::replace' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\Bucket::retrieveIn' => ['Couchbase\DocumentFragment', 'id'=>'string', '...paths='=>'array'], 'Couchbase\Bucket::setAdd' => ['', 'id'=>'string', 'value'=>'bool|float|int|string'], 'Couchbase\Bucket::setExists' => ['bool', 'id'=>'string', 'value'=>'bool|float|int|string'], 'Couchbase\Bucket::setRemove' => ['', 'id'=>'string', 'value'=>'bool|float|int|string'], 'Couchbase\Bucket::setSize' => ['int', 'id'=>'string'], 'Couchbase\Bucket::setTranscoder' => ['', 'encoder'=>'callable', 'decoder'=>'callable'], 'Couchbase\Bucket::touch' => ['Couchbase\Document|array', 'ids'=>'array|string', 'expiry'=>'int', 'options='=>'array'], 'Couchbase\Bucket::unlock' => ['Couchbase\Document|array', 'ids'=>'array|string', 'options='=>'array'], 'Couchbase\Bucket::upsert' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\BucketManager::__construct' => ['void'], 'Couchbase\BucketManager::createN1qlIndex' => ['', 'name'=>'string', 'fields'=>'array', 'whereClause='=>'string', 'ignoreIfExist='=>'bool', 'defer='=>'bool'], 'Couchbase\BucketManager::createN1qlPrimaryIndex' => ['', 'customName='=>'string', 'ignoreIfExist='=>'bool', 'defer='=>'bool'], 'Couchbase\BucketManager::dropN1qlIndex' => ['', 'name'=>'string', 'ignoreIfNotExist='=>'bool'], 'Couchbase\BucketManager::dropN1qlPrimaryIndex' => ['', 'customName='=>'string', 'ignoreIfNotExist='=>'bool'], 'Couchbase\BucketManager::flush' => [''], 'Couchbase\BucketManager::getDesignDocument' => ['array', 'name'=>'string'], 'Couchbase\BucketManager::info' => ['array'], 'Couchbase\BucketManager::insertDesignDocument' => ['', 'name'=>'string', 'document'=>'array'], 'Couchbase\BucketManager::listDesignDocuments' => ['array'], 'Couchbase\BucketManager::listN1qlIndexes' => ['array'], 'Couchbase\BucketManager::removeDesignDocument' => ['', 'name'=>'string'], 'Couchbase\BucketManager::upsertDesignDocument' => ['', 'name'=>'string', 'document'=>'array'], 'Couchbase\ClassicAuthenticator::bucket' => ['', 'name'=>'string', 'password'=>'string'], 'Couchbase\ClassicAuthenticator::cluster' => ['', 'username'=>'string', 'password'=>'string'], 'Couchbase\Cluster::__construct' => ['void', 'connstr'=>'string'], 'Couchbase\Cluster::authenticate' => ['null', 'authenticator'=>'Couchbase\Authenticator'], 'Couchbase\Cluster::authenticateAs' => ['null', 'username'=>'string', 'password'=>'string'], 'Couchbase\Cluster::manager' => ['Couchbase\ClusterManager', 'username='=>'string', 'password='=>'string'], 'Couchbase\Cluster::openBucket' => ['Couchbase\Bucket', 'name='=>'string', 'password='=>'string'], 'Couchbase\ClusterManager::__construct' => ['void'], 'Couchbase\ClusterManager::createBucket' => ['', 'name'=>'string', 'options='=>'array'], 'Couchbase\ClusterManager::getUser' => ['array', 'username'=>'string', 'domain='=>'int'], 'Couchbase\ClusterManager::info' => ['array'], 'Couchbase\ClusterManager::listBuckets' => ['array'], 'Couchbase\ClusterManager::listUsers' => ['array', 'domain='=>'int'], 'Couchbase\ClusterManager::removeBucket' => ['', 'name'=>'string'], 'Couchbase\ClusterManager::removeUser' => ['', 'name'=>'string', 'domain='=>'int'], 'Couchbase\ClusterManager::upsertUser' => ['', 'name'=>'string', 'settings'=>'Couchbase\UserSettings', 'domain='=>'int'], 'Couchbase\ConjunctionSearchQuery::__construct' => ['void'], 'Couchbase\ConjunctionSearchQuery::boost' => ['Couchbase\ConjunctionSearchQuery', 'boost'=>'float'], 'Couchbase\ConjunctionSearchQuery::every' => ['Couchbase\ConjunctionSearchQuery', '...queries='=>'array'], 'Couchbase\ConjunctionSearchQuery::jsonSerialize' => ['array'], 'Couchbase\DateRangeSearchFacet::__construct' => ['void'], 'Couchbase\DateRangeSearchFacet::addRange' => ['Couchbase\DateRangeSearchFacet', 'name'=>'string', 'start'=>'int|string', 'end'=>'int|string'], 'Couchbase\DateRangeSearchFacet::jsonSerialize' => ['array'], 'Couchbase\DateRangeSearchQuery::__construct' => ['void'], 'Couchbase\DateRangeSearchQuery::boost' => ['Couchbase\DateRangeSearchQuery', 'boost'=>'float'], 'Couchbase\DateRangeSearchQuery::dateTimeParser' => ['Couchbase\DateRangeSearchQuery', 'dateTimeParser'=>'string'], 'Couchbase\DateRangeSearchQuery::end' => ['Couchbase\DateRangeSearchQuery', 'end'=>'int|string', 'inclusive='=>'bool'], 'Couchbase\DateRangeSearchQuery::field' => ['Couchbase\DateRangeSearchQuery', 'field'=>'string'], 'Couchbase\DateRangeSearchQuery::jsonSerialize' => ['array'], 'Couchbase\DateRangeSearchQuery::start' => ['Couchbase\DateRangeSearchQuery', 'start'=>'int|string', 'inclusive='=>'bool'], 'Couchbase\defaultDecoder' => ['mixed', 'bytes'=>'string', 'flags'=>'int', 'datatype'=>'int'], 'Couchbase\defaultEncoder' => ['array', 'value'=>'mixed'], 'Couchbase\DisjunctionSearchQuery::__construct' => ['void'], 'Couchbase\DisjunctionSearchQuery::boost' => ['Couchbase\DisjunctionSearchQuery', 'boost'=>'float'], 'Couchbase\DisjunctionSearchQuery::either' => ['Couchbase\DisjunctionSearchQuery', '...queries='=>'array'], 'Couchbase\DisjunctionSearchQuery::jsonSerialize' => ['array'], 'Couchbase\DisjunctionSearchQuery::min' => ['Couchbase\DisjunctionSearchQuery', 'min'=>'int'], 'Couchbase\DocIdSearchQuery::__construct' => ['void'], 'Couchbase\DocIdSearchQuery::boost' => ['Couchbase\DocIdSearchQuery', 'boost'=>'float'], 'Couchbase\DocIdSearchQuery::docIds' => ['Couchbase\DocIdSearchQuery', '...documentIds='=>'array'], 'Couchbase\DocIdSearchQuery::field' => ['Couchbase\DocIdSearchQuery', 'field'=>'string'], 'Couchbase\DocIdSearchQuery::jsonSerialize' => ['array'], 'Couchbase\fastlzCompress' => ['string', 'data'=>'string'], 'Couchbase\fastlzDecompress' => ['string', 'data'=>'string'], 'Couchbase\GeoBoundingBoxSearchQuery::__construct' => ['void'], 'Couchbase\GeoBoundingBoxSearchQuery::boost' => ['Couchbase\GeoBoundingBoxSearchQuery', 'boost'=>'float'], 'Couchbase\GeoBoundingBoxSearchQuery::field' => ['Couchbase\GeoBoundingBoxSearchQuery', 'field'=>'string'], 'Couchbase\GeoBoundingBoxSearchQuery::jsonSerialize' => ['array'], 'Couchbase\GeoDistanceSearchQuery::__construct' => ['void'], 'Couchbase\GeoDistanceSearchQuery::boost' => ['Couchbase\GeoDistanceSearchQuery', 'boost'=>'float'], 'Couchbase\GeoDistanceSearchQuery::field' => ['Couchbase\GeoDistanceSearchQuery', 'field'=>'string'], 'Couchbase\GeoDistanceSearchQuery::jsonSerialize' => ['array'], 'Couchbase\LookupInBuilder::__construct' => ['void'], 'Couchbase\LookupInBuilder::execute' => ['Couchbase\DocumentFragment'], 'Couchbase\LookupInBuilder::exists' => ['Couchbase\LookupInBuilder', 'path'=>'string', 'options='=>'array'], 'Couchbase\LookupInBuilder::get' => ['Couchbase\LookupInBuilder', 'path'=>'string', 'options='=>'array'], 'Couchbase\LookupInBuilder::getCount' => ['Couchbase\LookupInBuilder', 'path'=>'string', 'options='=>'array'], 'Couchbase\MatchAllSearchQuery::__construct' => ['void'], 'Couchbase\MatchAllSearchQuery::boost' => ['Couchbase\MatchAllSearchQuery', 'boost'=>'float'], 'Couchbase\MatchAllSearchQuery::jsonSerialize' => ['array'], 'Couchbase\MatchNoneSearchQuery::__construct' => ['void'], 'Couchbase\MatchNoneSearchQuery::boost' => ['Couchbase\MatchNoneSearchQuery', 'boost'=>'float'], 'Couchbase\MatchNoneSearchQuery::jsonSerialize' => ['array'], 'Couchbase\MatchPhraseSearchQuery::__construct' => ['void'], 'Couchbase\MatchPhraseSearchQuery::analyzer' => ['Couchbase\MatchPhraseSearchQuery', 'analyzer'=>'string'], 'Couchbase\MatchPhraseSearchQuery::boost' => ['Couchbase\MatchPhraseSearchQuery', 'boost'=>'float'], 'Couchbase\MatchPhraseSearchQuery::field' => ['Couchbase\MatchPhraseSearchQuery', 'field'=>'string'], 'Couchbase\MatchPhraseSearchQuery::jsonSerialize' => ['array'], 'Couchbase\MatchSearchQuery::__construct' => ['void'], 'Couchbase\MatchSearchQuery::analyzer' => ['Couchbase\MatchSearchQuery', 'analyzer'=>'string'], 'Couchbase\MatchSearchQuery::boost' => ['Couchbase\MatchSearchQuery', 'boost'=>'float'], 'Couchbase\MatchSearchQuery::field' => ['Couchbase\MatchSearchQuery', 'field'=>'string'], 'Couchbase\MatchSearchQuery::fuzziness' => ['Couchbase\MatchSearchQuery', 'fuzziness'=>'int'], 'Couchbase\MatchSearchQuery::jsonSerialize' => ['array'], 'Couchbase\MatchSearchQuery::prefixLength' => ['Couchbase\MatchSearchQuery', 'prefixLength'=>'int'], 'Couchbase\MutateInBuilder::__construct' => ['void'], 'Couchbase\MutateInBuilder::arrayAddUnique' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::arrayAppend' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::arrayAppendAll' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'values'=>'array', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::arrayInsert' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\MutateInBuilder::arrayInsertAll' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'values'=>'array', 'options='=>'array'], 'Couchbase\MutateInBuilder::arrayPrepend' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::arrayPrependAll' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'values'=>'array', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::counter' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'delta'=>'int', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::execute' => ['Couchbase\DocumentFragment'], 'Couchbase\MutateInBuilder::insert' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::modeDocument' => ['', 'mode'=>'int'], 'Couchbase\MutateInBuilder::remove' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'options='=>'array'], 'Couchbase\MutateInBuilder::replace' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\MutateInBuilder::upsert' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::withExpiry' => ['Couchbase\MutateInBuilder', 'expiry'=>'Couchbase\expiry'], 'Couchbase\MutationState::__construct' => ['void'], 'Couchbase\MutationState::add' => ['', 'source'=>'Couchbase\Document|Couchbase\DocumentFragment|array'], 'Couchbase\MutationState::from' => ['Couchbase\MutationState', 'source'=>'Couchbase\Document|Couchbase\DocumentFragment|array'], 'Couchbase\MutationToken::__construct' => ['void'], 'Couchbase\MutationToken::bucketName' => ['string'], 'Couchbase\MutationToken::from' => ['', 'bucketName'=>'string', 'vbucketId'=>'int', 'vbucketUuid'=>'string', 'sequenceNumber'=>'string'], 'Couchbase\MutationToken::sequenceNumber' => ['string'], 'Couchbase\MutationToken::vbucketId' => ['int'], 'Couchbase\MutationToken::vbucketUuid' => ['string'], 'Couchbase\N1qlIndex::__construct' => ['void'], 'Couchbase\N1qlQuery::__construct' => ['void'], 'Couchbase\N1qlQuery::adhoc' => ['Couchbase\N1qlQuery', 'adhoc'=>'bool'], 'Couchbase\N1qlQuery::consistency' => ['Couchbase\N1qlQuery', 'consistency'=>'int'], 'Couchbase\N1qlQuery::consistentWith' => ['Couchbase\N1qlQuery', 'state'=>'Couchbase\MutationState'], 'Couchbase\N1qlQuery::crossBucket' => ['Couchbase\N1qlQuery', 'crossBucket'=>'bool'], 'Couchbase\N1qlQuery::fromString' => ['Couchbase\N1qlQuery', 'statement'=>'string'], 'Couchbase\N1qlQuery::maxParallelism' => ['Couchbase\N1qlQuery', 'maxParallelism'=>'int'], 'Couchbase\N1qlQuery::namedParams' => ['Couchbase\N1qlQuery', 'params'=>'array'], 'Couchbase\N1qlQuery::pipelineBatch' => ['Couchbase\N1qlQuery', 'pipelineBatch'=>'int'], 'Couchbase\N1qlQuery::pipelineCap' => ['Couchbase\N1qlQuery', 'pipelineCap'=>'int'], 'Couchbase\N1qlQuery::positionalParams' => ['Couchbase\N1qlQuery', 'params'=>'array'], 'Couchbase\N1qlQuery::profile' => ['', 'profileType'=>'string'], 'Couchbase\N1qlQuery::readonly' => ['Couchbase\N1qlQuery', 'readonly'=>'bool'], 'Couchbase\N1qlQuery::scanCap' => ['Couchbase\N1qlQuery', 'scanCap'=>'int'], 'Couchbase\NumericRangeSearchFacet::__construct' => ['void'], 'Couchbase\NumericRangeSearchFacet::addRange' => ['Couchbase\NumericRangeSearchFacet', 'name'=>'string', 'min'=>'float', 'max'=>'float'], 'Couchbase\NumericRangeSearchFacet::jsonSerialize' => ['array'], 'Couchbase\NumericRangeSearchQuery::__construct' => ['void'], 'Couchbase\NumericRangeSearchQuery::boost' => ['Couchbase\NumericRangeSearchQuery', 'boost'=>'float'], 'Couchbase\NumericRangeSearchQuery::field' => ['Couchbase\NumericRangeSearchQuery', 'field'=>'string'], 'Couchbase\NumericRangeSearchQuery::jsonSerialize' => ['array'], 'Couchbase\NumericRangeSearchQuery::max' => ['Couchbase\NumericRangeSearchQuery', 'max'=>'float', 'inclusive='=>'bool'], 'Couchbase\NumericRangeSearchQuery::min' => ['Couchbase\NumericRangeSearchQuery', 'min'=>'float', 'inclusive='=>'bool'], 'Couchbase\passthruDecoder' => ['string', 'bytes'=>'string', 'flags'=>'int', 'datatype'=>'int'], 'Couchbase\passthruEncoder' => ['array', 'value'=>'string'], 'Couchbase\PasswordAuthenticator::password' => ['Couchbase\PasswordAuthenticator', 'password'=>'string'], 'Couchbase\PasswordAuthenticator::username' => ['Couchbase\PasswordAuthenticator', 'username'=>'string'], 'Couchbase\PhraseSearchQuery::__construct' => ['void'], 'Couchbase\PhraseSearchQuery::boost' => ['Couchbase\PhraseSearchQuery', 'boost'=>'float'], 'Couchbase\PhraseSearchQuery::field' => ['Couchbase\PhraseSearchQuery', 'field'=>'string'], 'Couchbase\PhraseSearchQuery::jsonSerialize' => ['array'], 'Couchbase\PrefixSearchQuery::__construct' => ['void'], 'Couchbase\PrefixSearchQuery::boost' => ['Couchbase\PrefixSearchQuery', 'boost'=>'float'], 'Couchbase\PrefixSearchQuery::field' => ['Couchbase\PrefixSearchQuery', 'field'=>'string'], 'Couchbase\PrefixSearchQuery::jsonSerialize' => ['array'], 'Couchbase\QueryStringSearchQuery::__construct' => ['void'], 'Couchbase\QueryStringSearchQuery::boost' => ['Couchbase\QueryStringSearchQuery', 'boost'=>'float'], 'Couchbase\QueryStringSearchQuery::jsonSerialize' => ['array'], 'Couchbase\RegexpSearchQuery::__construct' => ['void'], 'Couchbase\RegexpSearchQuery::boost' => ['Couchbase\RegexpSearchQuery', 'boost'=>'float'], 'Couchbase\RegexpSearchQuery::field' => ['Couchbase\RegexpSearchQuery', 'field'=>'string'], 'Couchbase\RegexpSearchQuery::jsonSerialize' => ['array'], 'Couchbase\SearchQuery::__construct' => ['void', 'indexName'=>'string', 'queryPart'=>'Couchbase\SearchQueryPart'], 'Couchbase\SearchQuery::addFacet' => ['Couchbase\SearchQuery', 'name'=>'string', 'facet'=>'Couchbase\SearchFacet'], 'Couchbase\SearchQuery::boolean' => ['Couchbase\BooleanSearchQuery'], 'Couchbase\SearchQuery::booleanField' => ['Couchbase\BooleanFieldSearchQuery', 'value'=>'bool'], 'Couchbase\SearchQuery::conjuncts' => ['Couchbase\ConjunctionSearchQuery', '...queries='=>'array'], 'Couchbase\SearchQuery::consistentWith' => ['Couchbase\SearchQuery', 'state'=>'Couchbase\MutationState'], 'Couchbase\SearchQuery::dateRange' => ['Couchbase\DateRangeSearchQuery'], 'Couchbase\SearchQuery::dateRangeFacet' => ['Couchbase\DateRangeSearchFacet', 'field'=>'string', 'limit'=>'int'], 'Couchbase\SearchQuery::disjuncts' => ['Couchbase\DisjunctionSearchQuery', '...queries='=>'array'], 'Couchbase\SearchQuery::docId' => ['Couchbase\DocIdSearchQuery', '...documentIds='=>'array'], 'Couchbase\SearchQuery::explain' => ['Couchbase\SearchQuery', 'explain'=>'bool'], 'Couchbase\SearchQuery::fields' => ['Couchbase\SearchQuery', '...fields='=>'array'], 'Couchbase\SearchQuery::geoBoundingBox' => ['Couchbase\GeoBoundingBoxSearchQuery', 'topLeftLongitude'=>'float', 'topLeftLatitude'=>'float', 'bottomRightLongitude'=>'float', 'bottomRightLatitude'=>'float'], 'Couchbase\SearchQuery::geoDistance' => ['Couchbase\GeoDistanceSearchQuery', 'longitude'=>'float', 'latitude'=>'float', 'distance'=>'string'], 'Couchbase\SearchQuery::highlight' => ['Couchbase\SearchQuery', 'style'=>'string', '...fields='=>'array'], 'Couchbase\SearchQuery::jsonSerialize' => ['array'], 'Couchbase\SearchQuery::limit' => ['Couchbase\SearchQuery', 'limit'=>'int'], 'Couchbase\SearchQuery::match' => ['Couchbase\MatchSearchQuery', 'match'=>'string'], 'Couchbase\SearchQuery::matchAll' => ['Couchbase\MatchAllSearchQuery'], 'Couchbase\SearchQuery::matchNone' => ['Couchbase\MatchNoneSearchQuery'], 'Couchbase\SearchQuery::matchPhrase' => ['Couchbase\MatchPhraseSearchQuery', '...terms='=>'array'], 'Couchbase\SearchQuery::numericRange' => ['Couchbase\NumericRangeSearchQuery'], 'Couchbase\SearchQuery::numericRangeFacet' => ['Couchbase\NumericRangeSearchFacet', 'field'=>'string', 'limit'=>'int'], 'Couchbase\SearchQuery::prefix' => ['Couchbase\PrefixSearchQuery', 'prefix'=>'string'], 'Couchbase\SearchQuery::queryString' => ['Couchbase\QueryStringSearchQuery', 'queryString'=>'string'], 'Couchbase\SearchQuery::regexp' => ['Couchbase\RegexpSearchQuery', 'regexp'=>'string'], 'Couchbase\SearchQuery::serverSideTimeout' => ['Couchbase\SearchQuery', 'serverSideTimeout'=>'int'], 'Couchbase\SearchQuery::skip' => ['Couchbase\SearchQuery', 'skip'=>'int'], 'Couchbase\SearchQuery::sort' => ['Couchbase\SearchQuery', '...sort='=>'array'], 'Couchbase\SearchQuery::term' => ['Couchbase\TermSearchQuery', 'term'=>'string'], 'Couchbase\SearchQuery::termFacet' => ['Couchbase\TermSearchFacet', 'field'=>'string', 'limit'=>'int'], 'Couchbase\SearchQuery::termRange' => ['Couchbase\TermRangeSearchQuery'], 'Couchbase\SearchQuery::wildcard' => ['Couchbase\WildcardSearchQuery', 'wildcard'=>'string'], 'Couchbase\SearchSort::__construct' => ['void'], 'Couchbase\SearchSort::field' => ['Couchbase\SearchSortField', 'field'=>'string'], 'Couchbase\SearchSort::geoDistance' => ['Couchbase\SearchSortGeoDistance', 'field'=>'string', 'longitude'=>'float', 'latitude'=>'float'], 'Couchbase\SearchSort::id' => ['Couchbase\SearchSortId'], 'Couchbase\SearchSort::score' => ['Couchbase\SearchSortScore'], 'Couchbase\SearchSortField::__construct' => ['void'], 'Couchbase\SearchSortField::descending' => ['Couchbase\SearchSortField', 'descending'=>'bool'], 'Couchbase\SearchSortField::field' => ['Couchbase\SearchSortField', 'field'=>'string'], 'Couchbase\SearchSortField::geoDistance' => ['Couchbase\SearchSortGeoDistance', 'field'=>'string', 'longitude'=>'float', 'latitude'=>'float'], 'Couchbase\SearchSortField::id' => ['Couchbase\SearchSortId'], 'Couchbase\SearchSortField::jsonSerialize' => ['mixed'], 'Couchbase\SearchSortField::missing' => ['', 'missing'=>'string'], 'Couchbase\SearchSortField::mode' => ['', 'mode'=>'string'], 'Couchbase\SearchSortField::score' => ['Couchbase\SearchSortScore'], 'Couchbase\SearchSortField::type' => ['', 'type'=>'string'], 'Couchbase\SearchSortGeoDistance::__construct' => ['void'], 'Couchbase\SearchSortGeoDistance::descending' => ['Couchbase\SearchSortGeoDistance', 'descending'=>'bool'], 'Couchbase\SearchSortGeoDistance::field' => ['Couchbase\SearchSortField', 'field'=>'string'], 'Couchbase\SearchSortGeoDistance::geoDistance' => ['Couchbase\SearchSortGeoDistance', 'field'=>'string', 'longitude'=>'float', 'latitude'=>'float'], 'Couchbase\SearchSortGeoDistance::id' => ['Couchbase\SearchSortId'], 'Couchbase\SearchSortGeoDistance::jsonSerialize' => ['mixed'], 'Couchbase\SearchSortGeoDistance::score' => ['Couchbase\SearchSortScore'], 'Couchbase\SearchSortGeoDistance::unit' => ['Couchbase\SearchSortGeoDistance', 'unit'=>'string'], 'Couchbase\SearchSortId::__construct' => ['void'], 'Couchbase\SearchSortId::descending' => ['Couchbase\SearchSortId', 'descending'=>'bool'], 'Couchbase\SearchSortId::field' => ['Couchbase\SearchSortField', 'field'=>'string'], 'Couchbase\SearchSortId::geoDistance' => ['Couchbase\SearchSortGeoDistance', 'field'=>'string', 'longitude'=>'float', 'latitude'=>'float'], 'Couchbase\SearchSortId::id' => ['Couchbase\SearchSortId'], 'Couchbase\SearchSortId::jsonSerialize' => ['mixed'], 'Couchbase\SearchSortId::score' => ['Couchbase\SearchSortScore'], 'Couchbase\SearchSortScore::__construct' => ['void'], 'Couchbase\SearchSortScore::descending' => ['Couchbase\SearchSortScore', 'descending'=>'bool'], 'Couchbase\SearchSortScore::field' => ['Couchbase\SearchSortField', 'field'=>'string'], 'Couchbase\SearchSortScore::geoDistance' => ['Couchbase\SearchSortGeoDistance', 'field'=>'string', 'longitude'=>'float', 'latitude'=>'float'], 'Couchbase\SearchSortScore::id' => ['Couchbase\SearchSortId'], 'Couchbase\SearchSortScore::jsonSerialize' => ['mixed'], 'Couchbase\SearchSortScore::score' => ['Couchbase\SearchSortScore'], 'Couchbase\SpatialViewQuery::__construct' => ['void'], 'Couchbase\SpatialViewQuery::bbox' => ['Couchbase\SpatialViewQuery', 'bbox'=>'array'], 'Couchbase\SpatialViewQuery::consistency' => ['Couchbase\SpatialViewQuery', 'consistency'=>'int'], 'Couchbase\SpatialViewQuery::custom' => ['', 'customParameters'=>'array'], 'Couchbase\SpatialViewQuery::encode' => ['array'], 'Couchbase\SpatialViewQuery::endRange' => ['Couchbase\SpatialViewQuery', 'range'=>'array'], 'Couchbase\SpatialViewQuery::limit' => ['Couchbase\SpatialViewQuery', 'limit'=>'int'], 'Couchbase\SpatialViewQuery::order' => ['Couchbase\SpatialViewQuery', 'order'=>'int'], 'Couchbase\SpatialViewQuery::skip' => ['Couchbase\SpatialViewQuery', 'skip'=>'int'], 'Couchbase\SpatialViewQuery::startRange' => ['Couchbase\SpatialViewQuery', 'range'=>'array'], 'Couchbase\TermRangeSearchQuery::__construct' => ['void'], 'Couchbase\TermRangeSearchQuery::boost' => ['Couchbase\TermRangeSearchQuery', 'boost'=>'float'], 'Couchbase\TermRangeSearchQuery::field' => ['Couchbase\TermRangeSearchQuery', 'field'=>'string'], 'Couchbase\TermRangeSearchQuery::jsonSerialize' => ['array'], 'Couchbase\TermRangeSearchQuery::max' => ['Couchbase\TermRangeSearchQuery', 'max'=>'string', 'inclusive='=>'bool'], 'Couchbase\TermRangeSearchQuery::min' => ['Couchbase\TermRangeSearchQuery', 'min'=>'string', 'inclusive='=>'bool'], 'Couchbase\TermSearchFacet::__construct' => ['void'], 'Couchbase\TermSearchFacet::jsonSerialize' => ['array'], 'Couchbase\TermSearchQuery::__construct' => ['void'], 'Couchbase\TermSearchQuery::boost' => ['Couchbase\TermSearchQuery', 'boost'=>'float'], 'Couchbase\TermSearchQuery::field' => ['Couchbase\TermSearchQuery', 'field'=>'string'], 'Couchbase\TermSearchQuery::fuzziness' => ['Couchbase\TermSearchQuery', 'fuzziness'=>'int'], 'Couchbase\TermSearchQuery::jsonSerialize' => ['array'], 'Couchbase\TermSearchQuery::prefixLength' => ['Couchbase\TermSearchQuery', 'prefixLength'=>'int'], 'Couchbase\UserSettings::fullName' => ['Couchbase\UserSettings', 'fullName'=>'string'], 'Couchbase\UserSettings::password' => ['Couchbase\UserSettings', 'password'=>'string'], 'Couchbase\UserSettings::role' => ['Couchbase\UserSettings', 'role'=>'string', 'bucket='=>'string'], 'Couchbase\ViewQuery::__construct' => ['void'], 'Couchbase\ViewQuery::consistency' => ['Couchbase\ViewQuery', 'consistency'=>'int'], 'Couchbase\ViewQuery::custom' => ['Couchbase\ViewQuery', 'customParameters'=>'array'], 'Couchbase\ViewQuery::encode' => ['array'], 'Couchbase\ViewQuery::from' => ['Couchbase\ViewQuery', 'designDocumentName'=>'string', 'viewName'=>'string'], 'Couchbase\ViewQuery::fromSpatial' => ['Couchbase\SpatialViewQuery', 'designDocumentName'=>'string', 'viewName'=>'string'], 'Couchbase\ViewQuery::group' => ['Couchbase\ViewQuery', 'group'=>'bool'], 'Couchbase\ViewQuery::groupLevel' => ['Couchbase\ViewQuery', 'groupLevel'=>'int'], 'Couchbase\ViewQuery::idRange' => ['Couchbase\ViewQuery', 'startKeyDocumentId'=>'string', 'endKeyDocumentId'=>'string'], 'Couchbase\ViewQuery::key' => ['Couchbase\ViewQuery', 'key'=>'mixed'], 'Couchbase\ViewQuery::keys' => ['Couchbase\ViewQuery', 'keys'=>'array'], 'Couchbase\ViewQuery::limit' => ['Couchbase\ViewQuery', 'limit'=>'int'], 'Couchbase\ViewQuery::order' => ['Couchbase\ViewQuery', 'order'=>'int'], 'Couchbase\ViewQuery::range' => ['Couchbase\ViewQuery', 'startKey'=>'mixed', 'endKey'=>'mixed', 'inclusiveEnd='=>'bool'], 'Couchbase\ViewQuery::reduce' => ['Couchbase\ViewQuery', 'reduce'=>'bool'], 'Couchbase\ViewQuery::skip' => ['Couchbase\ViewQuery', 'skip'=>'int'], 'Couchbase\ViewQueryEncodable::encode' => ['array'], 'Couchbase\WildcardSearchQuery::__construct' => ['void'], 'Couchbase\WildcardSearchQuery::boost' => ['Couchbase\WildcardSearchQuery', 'boost'=>'float'], 'Couchbase\WildcardSearchQuery::field' => ['Couchbase\WildcardSearchQuery', 'field'=>'string'], 'Couchbase\WildcardSearchQuery::jsonSerialize' => ['array'], 'Couchbase\zlibCompress' => ['string', 'data'=>'string'], 'Couchbase\zlibDecompress' => ['string', 'data'=>'string'], 'count' => ['int', 'value'=>'Countable|array|SimpleXMLElement|ResourceBundle', 'mode='=>'int'], 'count_chars' => ['mixed', 'input'=>'string', 'mode='=>'int'], 'Countable::count' => ['int'], 'crack_check' => ['bool', 'dictionary'=>'', 'password'=>'string'], 'crack_closedict' => ['bool', 'dictionary='=>'resource'], 'crack_getlastmessage' => ['string'], 'crack_opendict' => ['resource|false', 'dictionary'=>'string'], 'crash' => [''], 'crc32' => ['int', 'string'=>'string'], 'create_function' => ['string', 'args'=>'string', 'code'=>'string'], 'crypt' => ['string', 'string'=>'string', 'salt='=>'string'], 'ctype_alnum' => ['bool', 'text'=>'string|int'], 'ctype_alpha' => ['bool', 'text'=>'string|int'], 'ctype_cntrl' => ['bool', 'text'=>'string|int'], 'ctype_digit' => ['bool', 'text'=>'string|int'], 'ctype_graph' => ['bool', 'text'=>'string|int'], 'ctype_lower' => ['bool', 'text'=>'string|int'], 'ctype_print' => ['bool', 'text'=>'string|int'], 'ctype_punct' => ['bool', 'text'=>'string|int'], 'ctype_space' => ['bool', 'text'=>'string|int'], 'ctype_upper' => ['bool', 'text'=>'string|int'], 'ctype_xdigit' => ['bool', 'text'=>'string|int'], 'cubrid_affected_rows' => ['int', 'req_identifier='=>''], 'cubrid_bind' => ['bool', 'req_identifier'=>'resource', 'bind_param'=>'int', 'bind_value'=>'mixed', 'bind_value_type='=>'string'], 'cubrid_client_encoding' => ['string', 'conn_identifier='=>''], 'cubrid_close' => ['bool', 'conn_identifier='=>''], 'cubrid_close_prepare' => ['bool', 'req_identifier'=>'resource'], 'cubrid_close_request' => ['bool', 'req_identifier'=>'resource'], 'cubrid_col_get' => ['array', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string'], 'cubrid_col_size' => ['int', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string'], 'cubrid_column_names' => ['array', 'req_identifier'=>'resource'], 'cubrid_column_types' => ['array', 'req_identifier'=>'resource'], 'cubrid_commit' => ['bool', 'conn_identifier'=>'resource'], 'cubrid_connect' => ['resource', 'host'=>'string', 'port'=>'int', 'dbname'=>'string', 'userid='=>'string', 'passwd='=>'string'], 'cubrid_connect_with_url' => ['resource', 'conn_url'=>'string', 'userid='=>'string', 'passwd='=>'string'], 'cubrid_current_oid' => ['string', 'req_identifier'=>'resource'], 'cubrid_data_seek' => ['bool', 'req_identifier'=>'', 'row_number'=>'int'], 'cubrid_db_name' => ['string', 'result'=>'array', 'index'=>'int'], 'cubrid_db_parameter' => ['array', 'conn_identifier'=>'resource'], 'cubrid_disconnect' => ['bool', 'conn_identifier'=>'resource'], 'cubrid_drop' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_errno' => ['int', 'conn_identifier='=>''], 'cubrid_error' => ['string', 'connection='=>''], 'cubrid_error_code' => ['int'], 'cubrid_error_code_facility' => ['int'], 'cubrid_error_msg' => ['string'], 'cubrid_execute' => ['bool', 'conn_identifier'=>'', 'sql'=>'string', 'option='=>'int', 'request_identifier='=>''], 'cubrid_fetch' => ['mixed', 'result'=>'resource', 'type='=>'int'], 'cubrid_fetch_array' => ['array', 'result'=>'resource', 'type='=>'int'], 'cubrid_fetch_assoc' => ['array', 'result'=>'resource'], 'cubrid_fetch_field' => ['object', 'result'=>'resource', 'field_offset='=>'int'], 'cubrid_fetch_lengths' => ['array', 'result'=>'resource'], 'cubrid_fetch_object' => ['object', 'result'=>'resource', 'class_name='=>'string', 'params='=>'array'], 'cubrid_fetch_row' => ['array', 'result'=>'resource'], 'cubrid_field_flags' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'cubrid_field_len' => ['int', 'result'=>'resource', 'field_offset'=>'int'], 'cubrid_field_name' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'cubrid_field_seek' => ['bool', 'result'=>'resource', 'field_offset='=>'int'], 'cubrid_field_table' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'cubrid_field_type' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'cubrid_free_result' => ['bool', 'req_identifier'=>'resource'], 'cubrid_get' => ['mixed', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr='=>'mixed'], 'cubrid_get_autocommit' => ['bool', 'conn_identifier'=>'resource'], 'cubrid_get_charset' => ['string', 'conn_identifier'=>'resource'], 'cubrid_get_class_name' => ['string', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_get_client_info' => ['string'], 'cubrid_get_db_parameter' => ['array', 'conn_identifier'=>'resource'], 'cubrid_get_query_timeout' => ['int', 'req_identifier'=>'resource'], 'cubrid_get_server_info' => ['string', 'conn_identifier'=>'resource'], 'cubrid_insert_id' => ['string', 'conn_identifier='=>'resource'], 'cubrid_is_instance' => ['int', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_list_dbs' => ['array', 'conn_identifier'=>'resource'], 'cubrid_load_from_glo' => ['int', 'conn_identifier'=>'', 'oid'=>'string', 'file_name'=>'string'], 'cubrid_lob2_bind' => ['bool', 'req_identifier'=>'resource', 'bind_index'=>'int', 'bind_value'=>'mixed', 'bind_value_type='=>'string'], 'cubrid_lob2_close' => ['bool', 'lob_identifier'=>'resource'], 'cubrid_lob2_export' => ['bool', 'lob_identifier'=>'resource', 'file_name'=>'string'], 'cubrid_lob2_import' => ['bool', 'lob_identifier'=>'resource', 'file_name'=>'string'], 'cubrid_lob2_new' => ['resource', 'conn_identifier='=>'resource', 'type='=>'string'], 'cubrid_lob2_read' => ['string', 'lob_identifier'=>'resource', 'length'=>'int'], 'cubrid_lob2_seek' => ['bool', 'lob_identifier'=>'resource', 'offset'=>'int', 'origin='=>'int'], 'cubrid_lob2_seek64' => ['bool', 'lob_identifier'=>'resource', 'offset'=>'string', 'origin='=>'int'], 'cubrid_lob2_size' => ['int', 'lob_identifier'=>'resource'], 'cubrid_lob2_size64' => ['string', 'lob_identifier'=>'resource'], 'cubrid_lob2_tell' => ['int', 'lob_identifier'=>'resource'], 'cubrid_lob2_tell64' => ['string', 'lob_identifier'=>'resource'], 'cubrid_lob2_write' => ['bool', 'lob_identifier'=>'resource', 'buf'=>'string'], 'cubrid_lob_close' => ['bool', 'lob_identifier_array'=>'array'], 'cubrid_lob_export' => ['bool', 'conn_identifier'=>'resource', 'lob_identifier'=>'resource', 'path_name'=>'string'], 'cubrid_lob_get' => ['array', 'conn_identifier'=>'resource', 'sql'=>'string'], 'cubrid_lob_send' => ['bool', 'conn_identifier'=>'resource', 'lob_identifier'=>'resource'], 'cubrid_lob_size' => ['string', 'lob_identifier'=>'resource'], 'cubrid_lock_read' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_lock_write' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_move_cursor' => ['int', 'req_identifier'=>'resource', 'offset'=>'int', 'origin='=>'int'], 'cubrid_new_glo' => ['string', 'conn_identifier'=>'', 'class_name'=>'string', 'file_name'=>'string'], 'cubrid_next_result' => ['bool', 'result'=>'resource'], 'cubrid_num_cols' => ['int', 'req_identifier'=>'resource'], 'cubrid_num_fields' => ['int', 'result'=>'resource'], 'cubrid_num_rows' => ['int', 'req_identifier'=>'resource'], 'cubrid_pconnect' => ['resource', 'host'=>'string', 'port'=>'int', 'dbname'=>'string', 'userid='=>'string', 'passwd='=>'string'], 'cubrid_pconnect_with_url' => ['resource', 'conn_url'=>'string', 'userid='=>'string', 'passwd='=>'string'], 'cubrid_ping' => ['bool', 'conn_identifier='=>''], 'cubrid_prepare' => ['resource', 'conn_identifier'=>'resource', 'prepare_stmt'=>'string', 'option='=>'int'], 'cubrid_put' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr='=>'string', 'value='=>'mixed'], 'cubrid_query' => ['resource', 'query'=>'string', 'conn_identifier='=>''], 'cubrid_real_escape_string' => ['string', 'unescaped_string'=>'string', 'conn_identifier='=>''], 'cubrid_result' => ['string', 'result'=>'resource', 'row'=>'int', 'field='=>''], 'cubrid_rollback' => ['bool', 'conn_identifier'=>'resource'], 'cubrid_save_to_glo' => ['int', 'conn_identifier'=>'', 'oid'=>'string', 'file_name'=>'string'], 'cubrid_schema' => ['array', 'conn_identifier'=>'resource', 'schema_type'=>'int', 'class_name='=>'string', 'attr_name='=>'string'], 'cubrid_send_glo' => ['int', 'conn_identifier'=>'', 'oid'=>'string'], 'cubrid_seq_add' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'seq_element'=>'string'], 'cubrid_seq_drop' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'index'=>'int'], 'cubrid_seq_insert' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'index'=>'int', 'seq_element'=>'string'], 'cubrid_seq_put' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'index'=>'int', 'seq_element'=>'string'], 'cubrid_set_add' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'set_element'=>'string'], 'cubrid_set_autocommit' => ['bool', 'conn_identifier'=>'resource', 'mode'=>'bool'], 'cubrid_set_db_parameter' => ['bool', 'conn_identifier'=>'resource', 'param_type'=>'int', 'param_value'=>'int'], 'cubrid_set_drop' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'set_element'=>'string'], 'cubrid_set_query_timeout' => ['bool', 'req_identifier'=>'resource', 'timeout'=>'int'], 'cubrid_unbuffered_query' => ['resource', 'query'=>'string', 'conn_identifier='=>''], 'cubrid_version' => ['string'], 'curl_close' => ['void', 'ch'=>'CurlHandle'], 'curl_copy_handle' => ['CurlHandle', 'ch'=>'CurlHandle'], 'curl_errno' => ['int', 'ch'=>'CurlHandle'], 'curl_error' => ['string', 'ch'=>'CurlHandle'], 'curl_escape' => ['string|false', 'ch'=>'CurlHandle', 'string'=>'string'], 'curl_exec' => ['bool|string', 'ch'=>'CurlHandle'], 'curl_file_create' => ['CURLFile', 'filename'=>'string', 'mimetype='=>'string', 'postfilename='=>'string'], 'curl_getinfo' => ['mixed', 'ch'=>'CurlHandle', 'option='=>'int'], 'curl_init' => ['CurlHandle|false', 'url='=>'string'], 'curl_multi_add_handle' => ['int', 'mh'=>'CurlMultiHandle', 'ch'=>'CurlHandle'], 'curl_multi_close' => ['void', 'mh'=>'CurlMultiHandle'], 'curl_multi_errno' => ['int', 'mh'=>'CurlMultiHandle'], 'curl_multi_exec' => ['int', 'mh'=>'CurlMultiHandle', '&w_still_running'=>'int'], 'curl_multi_getcontent' => ['string', 'ch'=>'CurlMultiHandle'], 'curl_multi_info_read' => ['array|false', 'mh'=>'CurlMultiHandle', '&w_msgs_in_queue='=>'int'], 'curl_multi_init' => ['CurlMultiHandle|false'], 'curl_multi_remove_handle' => ['int', 'mh'=>'CurlMultiHandle', 'ch'=>'CurlHandle'], 'curl_multi_select' => ['int', 'mh'=>'CurlMultiHandle', 'timeout='=>'float'], 'curl_multi_setopt' => ['bool', 'mh'=>'CurlMultiHandle', 'option'=>'int', 'value'=>'mixed'], 'curl_multi_strerror' => ['?string', 'code'=>'int'], 'curl_pause' => ['int', 'ch'=>'CurlHandle', 'bitmask'=>'int'], 'curl_reset' => ['void', 'ch'=>'CurlHandle'], 'curl_setopt' => ['bool', 'ch'=>'CurlHandle', 'option'=>'int', 'value'=>'callable|mixed'], 'curl_setopt_array' => ['bool', 'ch'=>'CurlHandle', 'options'=>'array'], 'curl_share_close' => ['void', 'sh'=>'CurlShareHandle'], 'curl_share_errno' => ['int', 'sh'=>'CurlShareHandle'], 'curl_share_init' => ['CurlShareHandle'], 'curl_share_setopt' => ['bool', 'sh'=>'CurlShareHandle', 'option'=>'int', 'value'=>'mixed'], 'curl_share_strerror' => ['string', 'code'=>'int'], 'curl_strerror' => ['?string', 'code'=>'int'], 'curl_unescape' => ['string|false', 'ch'=>'CurlShareHandle', 'string'=>'string'], 'curl_version' => ['array', 'version='=>'int'], 'CURLFile::__construct' => ['void', 'filename'=>'string', 'mimetype='=>'string', 'postfilename='=>'string'], 'CURLFile::__wakeup' => ['void'], 'CURLFile::getFilename' => ['string'], 'CURLFile::getMimeType' => ['string'], 'CURLFile::getPostFilename' => ['string'], 'CURLFile::setMimeType' => ['void', 'mime'=>'string'], 'CURLFile::setPostFilename' => ['void', 'name'=>'string'], 'current' => ['mixed|false', 'array'=>'array|object'], 'cyrus_authenticate' => ['void', 'connection'=>'resource', 'mechlist='=>'string', 'service='=>'string', 'user='=>'string', 'minssf='=>'int', 'maxssf='=>'int', 'authname='=>'string', 'password='=>'string'], 'cyrus_bind' => ['bool', 'connection'=>'resource', 'callbacks'=>'array'], 'cyrus_close' => ['bool', 'connection'=>'resource'], 'cyrus_connect' => ['resource', 'host='=>'string', 'port='=>'string', 'flags='=>'int'], 'cyrus_query' => ['array', 'connection'=>'resource', 'query'=>'string'], 'cyrus_unbind' => ['bool', 'connection'=>'resource', 'trigger_name'=>'string'], 'date' => ['string|false', 'format'=>'string', 'timestamp='=>'int'], 'date_add' => ['DateTime|false', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_create' => ['DateTime|false', 'time='=>'string', 'timezone='=>'?DateTimeZone'], 'date_create_from_format' => ['DateTime|false', 'format'=>'string', 'time'=>'string', 'timezone='=>'?\DateTimeZone'], 'date_create_immutable' => ['DateTimeImmutable|false', 'time='=>'string', 'timezone='=>'?DateTimeZone'], 'date_create_immutable_from_format' => ['DateTimeImmutable|false', 'format'=>'string', 'time'=>'string', 'timezone='=>'?DateTimeZone'], 'date_date_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'month'=>'int', 'day'=>'int'], 'date_default_timezone_get' => ['string'], 'date_default_timezone_set' => ['bool', 'timezone_identifier'=>'string'], 'date_diff' => ['DateInterval|false', 'obj1'=>'DateTimeInterface', 'obj2'=>'DateTimeInterface', 'absolute='=>'bool'], 'date_format' => ['string|false', 'object'=>'DateTimeInterface', 'format'=>'string'], 'date_get_last_errors' => ['array{warning_count:int,warnings:array,error_count:int,errors:array}'], 'date_interval_create_from_date_string' => ['DateInterval', 'time'=>'string'], 'date_interval_format' => ['string', 'object'=>'DateInterval', 'format'=>'string'], 'date_isodate_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'day='=>'int|mixed'], 'date_modify' => ['DateTime|false', 'object'=>'DateTime', 'modify'=>'string'], 'date_offset_get' => ['int|false', 'object'=>'DateTimeInterface'], 'date_parse' => ['array|false', 'date'=>'string'], 'date_parse_from_format' => ['array', 'format'=>'string', 'date'=>'string'], 'date_sub' => ['DateTime|false', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_sun_info' => ['array|false', 'time'=>'int', 'latitude'=>'float', 'longitude'=>'float'], 'date_sunrise' => ['mixed', 'time'=>'int', 'format='=>'int', 'latitude='=>'float', 'longitude='=>'float', 'zenith='=>'float', 'gmt_offset='=>'float'], 'date_sunset' => ['mixed', 'time'=>'int', 'format='=>'int', 'latitude='=>'float', 'longitude='=>'float', 'zenith='=>'float', 'gmt_offset='=>'float'], 'date_time_set' => ['DateTime|false', 'object'=>'', 'hour'=>'', 'minute'=>'', 'second='=>'', 'microseconds='=>''], 'date_timestamp_get' => ['int', 'object'=>'DateTimeInterface'], 'date_timestamp_set' => ['DateTime|false', 'object'=>'DateTime', 'unixtimestamp'=>'int'], 'date_timezone_get' => ['DateTimeZone|false', 'object'=>'DateTimeInterface'], 'date_timezone_set' => ['DateTime|false', 'object'=>'DateTime', 'timezone'=>'DateTimeZone'], 'datefmt_create' => ['IntlDateFormatter|false', 'locale'=>'?string', 'datetype'=>'?int', 'timetype'=>'?int', 'timezone='=>'string|DateTimeZone|IntlTimeZone|null', 'calendar='=>'int|IntlCalendar|null', 'pattern='=>'string'], 'datefmt_format' => ['string|false', 'fmt'=>'IntlDateFormatter', 'value'=>'DateTime|IntlCalendar|array|int'], 'datefmt_format_object' => ['string|false', 'object'=>'object', 'format='=>'mixed', 'locale='=>'string'], 'datefmt_get_calendar' => ['int', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_calendar_object' => ['IntlCalendar', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_datetype' => ['int', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_error_code' => ['int', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_error_message' => ['string', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_locale' => ['string|false', 'fmt'=>'IntlDateFormatter', 'which='=>'int'], 'datefmt_get_pattern' => ['string', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_timetype' => ['int', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_timezone' => ['IntlTimeZone|false'], 'datefmt_get_timezone_id' => ['string', 'fmt'=>'IntlDateFormatter'], 'datefmt_is_lenient' => ['bool', 'fmt'=>'IntlDateFormatter'], 'datefmt_localtime' => ['array|false', 'fmt'=>'IntlDateFormatter', 'text_to_parse='=>'string', '&rw_parse_pos='=>'int'], 'datefmt_parse' => ['int|false', 'fmt'=>'IntlDateFormatter', 'text_to_parse='=>'string', '&rw_parse_pos='=>'int'], 'datefmt_set_calendar' => ['bool', 'fmt'=>'IntlDateFormatter', 'which'=>'int'], 'datefmt_set_lenient' => ['?bool', 'fmt'=>'IntlDateFormatter', 'lenient'=>'bool'], 'datefmt_set_pattern' => ['bool', 'fmt'=>'IntlDateFormatter', 'pattern'=>'string'], 'datefmt_set_timezone' => ['bool', 'zone'=>'mixed'], 'datefmt_set_timezone_id' => ['bool', 'fmt'=>'IntlDateFormatter', 'zone'=>'string'], 'DateInterval::__construct' => ['void', 'spec'=>'string'], 'DateInterval::__set_state' => ['DateInterval', 'array'=>'array'], 'DateInterval::__wakeup' => ['void'], 'DateInterval::createFromDateString' => ['DateInterval', 'time'=>'string'], 'DateInterval::format' => ['string', 'format'=>'string'], 'DatePeriod::__construct' => ['void', 'start'=>'DateTimeInterface', 'interval'=>'DateInterval', 'recur'=>'int', 'options='=>'int'], 'DatePeriod::__construct\'1' => ['void', 'start'=>'DateTimeInterface', 'interval'=>'DateInterval', 'end'=>'DateTimeInterface', 'options='=>'int'], 'DatePeriod::__construct\'2' => ['void', 'iso'=>'string', 'options='=>'int'], 'DatePeriod::__wakeup' => ['void'], 'DatePeriod::getDateInterval' => ['DateInterval'], 'DatePeriod::getEndDate' => ['?DateTimeInterface'], 'DatePeriod::getStartDate' => ['DateTimeInterface'], 'DateTime::__construct' => ['void', 'time='=>'string'], 'DateTime::__construct\'1' => ['void', 'time'=>'?string', 'timezone'=>'?DateTimeZone'], 'DateTime::__set_state' => ['static', 'array'=>'array'], 'DateTime::__wakeup' => ['void'], 'DateTime::add' => ['static', 'interval'=>'DateInterval'], 'DateTime::createFromFormat' => ['static|false', 'format'=>'string', 'time'=>'string', 'timezone='=>'?DateTimeZone'], 'DateTime::createFromImmutable' => ['static', 'datetTimeImmutable'=>'DateTimeImmutable'], 'DateTime::diff' => ['DateInterval|false', 'datetime2'=>'DateTimeInterface', 'absolute='=>'bool'], 'DateTime::format' => ['string|false', 'format'=>'string'], 'DateTime::getLastErrors' => ['array{warning_count:int,warnings:array,error_count:int,errors:array}'], 'DateTime::getOffset' => ['int'], 'DateTime::getTimestamp' => ['int|false'], 'DateTime::getTimezone' => ['DateTimeZone'], 'DateTime::modify' => ['static|false', 'modify'=>'string'], 'DateTime::setDate' => ['static', 'year'=>'int', 'month'=>'int', 'day'=>'int'], 'DateTime::setISODate' => ['static', 'year'=>'int', 'week'=>'int', 'day='=>'int'], 'DateTime::setTime' => ['static|false', 'hour'=>'int', 'minute'=>'int', 'second='=>'int', 'microseconds='=>'int'], 'DateTime::setTimestamp' => ['static', 'unixtimestamp'=>'int'], 'DateTime::setTimezone' => ['static', 'timezone'=>'DateTimeZone'], 'DateTime::sub' => ['static', 'interval'=>'DateInterval'], 'DateTimeImmutable::__construct' => ['void', 'time='=>'string'], 'DateTimeImmutable::__construct\'1' => ['void', 'time'=>'?string', 'timezone'=>'?DateTimeZone'], 'DateTimeImmutable::__set_state' => ['static', 'array'=>'array'], 'DateTimeImmutable::__wakeup' => ['void'], 'DateTimeImmutable::add' => ['static', 'interval'=>'DateInterval'], 'DateTimeImmutable::createFromFormat' => ['static|false', 'format'=>'string', 'time'=>'string', 'timezone='=>'?DateTimeZone'], 'DateTimeImmutable::createFromMutable' => ['static', 'datetime'=>'DateTime'], 'DateTimeImmutable::diff' => ['DateInterval', 'datetime2'=>'DateTimeInterface', 'absolute='=>'bool'], 'DateTimeImmutable::format' => ['string|false', 'format'=>'string'], 'DateTimeImmutable::getLastErrors' => ['array{warning_count:int,warnings:array,error_count:int,errors:array}'], 'DateTimeImmutable::getOffset' => ['int'], 'DateTimeImmutable::getTimestamp' => ['int|false'], 'DateTimeImmutable::getTimezone' => ['DateTimeZone'], 'DateTimeImmutable::modify' => ['static', 'modify'=>'string'], 'DateTimeImmutable::setDate' => ['static|false', 'year'=>'int', 'month'=>'int', 'day'=>'int'], 'DateTimeImmutable::setISODate' => ['static|false', 'year'=>'int', 'week'=>'int', 'day='=>'int'], 'DateTimeImmutable::setTime' => ['static|false', 'hour'=>'int', 'minute'=>'int', 'second='=>'int', 'microseconds='=>'int'], 'DateTimeImmutable::setTimestamp' => ['static|false', 'unixtimestamp'=>'int'], 'DateTimeImmutable::setTimezone' => ['static|false', 'timezone'=>'DateTimeZone'], 'DateTimeImmutable::sub' => ['static|false', 'interval'=>'DateInterval'], 'DateTimeInterface::diff' => ['DateInterval', 'datetime2'=>'DateTimeInterface', 'absolute='=>'bool'], 'DateTimeInterface::format' => ['string', 'format'=>'string'], 'DateTimeInterface::getOffset' => ['int'], 'DateTimeInterface::getTimestamp' => ['int|false'], 'DateTimeInterface::getTimezone' => ['DateTimeZone'], 'DateTimeZone::__construct' => ['void', 'timezone'=>'string'], 'DateTimeZone::__set_state' => ['DateTimeZone', 'array'=>'array'], 'DateTimeZone::__wakeup' => ['void'], 'DateTimeZone::getLocation' => ['array|false'], 'DateTimeZone::getName' => ['string'], 'DateTimeZone::getOffset' => ['int|false', 'datetime'=>'DateTimeInterface'], 'DateTimeZone::getTransitions' => ['array|false', 'timestamp_begin='=>'int', 'timestamp_end='=>'int'], 'DateTimeZone::listAbbreviations' => ['array|false'], 'DateTimeZone::listIdentifiers' => ['array|false', 'what='=>'int', 'country='=>'string'], 'db2_autocommit' => ['mixed', 'connection'=>'resource', 'value='=>'int'], 'db2_bind_param' => ['bool', 'stmt'=>'resource', 'parameter_number'=>'int', 'variable_name'=>'string', 'parameter_type='=>'int', 'data_type='=>'int', 'precision='=>'int', 'scale='=>'int'], 'db2_client_info' => ['object|false', 'connection'=>'resource'], 'db2_close' => ['bool', 'connection'=>'resource'], 'db2_column_privileges' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'string', 'schema='=>'string', 'table_name='=>'string', 'column_name='=>'string'], 'db2_columns' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'string', 'schema='=>'string', 'table_name='=>'string', 'column_name='=>'string'], 'db2_commit' => ['bool', 'connection'=>'resource'], 'db2_conn_error' => ['string', 'connection='=>'resource'], 'db2_conn_errormsg' => ['string', 'connection='=>'resource'], 'db2_connect' => ['resource|false', 'database'=>'string', 'username'=>'string', 'password'=>'string', 'options='=>'array'], 'db2_cursor_type' => ['int', 'stmt'=>'resource'], 'db2_escape_string' => ['string', 'string_literal'=>'string'], 'db2_exec' => ['resource|false', 'connection'=>'resource', 'statement'=>'string', 'options='=>'array'], 'db2_execute' => ['bool', 'stmt'=>'resource', 'parameters='=>'array'], 'db2_fetch_array' => ['array|false', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_fetch_assoc' => ['array|false', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_fetch_both' => ['array|false', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_fetch_object' => ['object|false', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_fetch_row' => ['bool', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_field_display_size' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_name' => ['string|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_num' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_precision' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_scale' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_type' => ['string|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_width' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_foreign_keys' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'table_name'=>'string'], 'db2_free_result' => ['bool', 'stmt'=>'resource'], 'db2_free_stmt' => ['bool', 'stmt'=>'resource'], 'db2_get_option' => ['string|false', 'resource'=>'resource', 'option'=>'string'], 'db2_last_insert_id' => ['string', 'resource'=>'resource'], 'db2_lob_read' => ['string|false', 'stmt'=>'resource', 'colnum'=>'int', 'length'=>'int'], 'db2_next_result' => ['resource|false', 'stmt'=>'resource'], 'db2_num_fields' => ['int|false', 'stmt'=>'resource'], 'db2_num_rows' => ['int', 'stmt'=>'resource'], 'db2_pclose' => ['bool', 'resource'=>'resource'], 'db2_pconnect' => ['resource|false', 'database'=>'string', 'username'=>'string', 'password'=>'string', 'options='=>'array'], 'db2_prepare' => ['resource|false', 'connection'=>'resource', 'statement'=>'string', 'options='=>'array'], 'db2_primary_keys' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'table_name'=>'string'], 'db2_primarykeys' => [''], 'db2_procedure_columns' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'procedure'=>'string', 'parameter'=>'string'], 'db2_procedurecolumns' => [''], 'db2_procedures' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'procedure'=>'string'], 'db2_result' => ['mixed', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_rollback' => ['bool', 'connection'=>'resource'], 'db2_server_info' => ['object|false', 'connection'=>'resource'], 'db2_set_option' => ['bool', 'resource'=>'resource', 'options'=>'array', 'type'=>'int'], 'db2_setoption' => [''], 'db2_special_columns' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'table_name'=>'string', 'scope'=>'int'], 'db2_specialcolumns' => [''], 'db2_statistics' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'table_name'=>'string', 'unique'=>'bool'], 'db2_stmt_error' => ['string', 'stmt='=>'resource'], 'db2_stmt_errormsg' => ['string', 'stmt='=>'resource'], 'db2_table_privileges' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'string', 'schema='=>'string', 'table_name='=>'string'], 'db2_tableprivileges' => [''], 'db2_tables' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'string', 'schema='=>'string', 'table_name='=>'string', 'table_type='=>'string'], 'dba_close' => ['void', 'handle'=>'resource'], 'dba_delete' => ['bool', 'key'=>'string', 'handle'=>'resource'], 'dba_exists' => ['bool', 'key'=>'string', 'handle'=>'resource'], 'dba_fetch' => ['string|false', 'key'=>'string', 'skip'=>'int', 'handle'=>'resource'], 'dba_fetch\'1' => ['string|false', 'key'=>'string', 'handle'=>'resource'], 'dba_firstkey' => ['string', 'handle'=>'resource'], 'dba_handlers' => ['array', 'full_info='=>'bool'], 'dba_insert' => ['bool', 'key'=>'string', 'value'=>'string', 'handle'=>'resource'], 'dba_key_split' => ['array|false', 'key'=>'string'], 'dba_list' => ['array'], 'dba_nextkey' => ['string', 'handle'=>'resource'], 'dba_open' => ['resource', 'path'=>'string', 'mode'=>'string', 'handlername='=>'string', '...args='=>'string'], 'dba_optimize' => ['bool', 'handle'=>'resource'], 'dba_popen' => ['resource', 'path'=>'string', 'mode'=>'string', 'handlername='=>'string', '...args='=>'string'], 'dba_replace' => ['bool', 'key'=>'string', 'value'=>'string', 'handle'=>'resource'], 'dba_sync' => ['bool', 'handle'=>'resource'], 'dbase_add_record' => ['bool', 'dbase_identifier'=>'resource', 'record'=>'array'], 'dbase_close' => ['bool', 'dbase_identifier'=>'resource'], 'dbase_create' => ['resource|false', 'filename'=>'string', 'fields'=>'array'], 'dbase_delete_record' => ['bool', 'dbase_identifier'=>'resource', 'record_number'=>'int'], 'dbase_get_header_info' => ['array', 'dbase_identifier'=>'resource'], 'dbase_get_record' => ['array', 'dbase_identifier'=>'resource', 'record_number'=>'int'], 'dbase_get_record_with_names' => ['array', 'dbase_identifier'=>'resource', 'record_number'=>'int'], 'dbase_numfields' => ['int', 'dbase_identifier'=>'resource'], 'dbase_numrecords' => ['int', 'dbase_identifier'=>'resource'], 'dbase_open' => ['resource|false', 'filename'=>'string', 'mode'=>'int'], 'dbase_pack' => ['bool', 'dbase_identifier'=>'resource'], 'dbase_replace_record' => ['bool', 'dbase_identifier'=>'resource', 'record'=>'array', 'record_number'=>'int'], 'dbplus_add' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_aql' => ['resource', 'query'=>'string', 'server='=>'string', 'dbpath='=>'string'], 'dbplus_chdir' => ['string', 'newdir='=>'string'], 'dbplus_close' => ['mixed', 'relation'=>'resource'], 'dbplus_curr' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_errcode' => ['string', 'errno='=>'int'], 'dbplus_errno' => ['int'], 'dbplus_find' => ['int', 'relation'=>'resource', 'constraints'=>'array', 'tuple'=>'mixed'], 'dbplus_first' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_flush' => ['int', 'relation'=>'resource'], 'dbplus_freealllocks' => ['int'], 'dbplus_freelock' => ['int', 'relation'=>'resource', 'tuple'=>'string'], 'dbplus_freerlocks' => ['int', 'relation'=>'resource'], 'dbplus_getlock' => ['int', 'relation'=>'resource', 'tuple'=>'string'], 'dbplus_getunique' => ['int', 'relation'=>'resource', 'uniqueid'=>'int'], 'dbplus_info' => ['int', 'relation'=>'resource', 'key'=>'string', 'result'=>'array'], 'dbplus_last' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_lockrel' => ['int', 'relation'=>'resource'], 'dbplus_next' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_open' => ['resource', 'name'=>'string'], 'dbplus_prev' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_rchperm' => ['int', 'relation'=>'resource', 'mask'=>'int', 'user'=>'string', 'group'=>'string'], 'dbplus_rcreate' => ['resource', 'name'=>'string', 'domlist'=>'mixed', 'overwrite='=>'bool'], 'dbplus_rcrtexact' => ['mixed', 'name'=>'string', 'relation'=>'resource', 'overwrite='=>'bool'], 'dbplus_rcrtlike' => ['mixed', 'name'=>'string', 'relation'=>'resource', 'overwrite='=>'int'], 'dbplus_resolve' => ['array', 'relation_name'=>'string'], 'dbplus_restorepos' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_rkeys' => ['mixed', 'relation'=>'resource', 'domlist'=>'mixed'], 'dbplus_ropen' => ['resource', 'name'=>'string'], 'dbplus_rquery' => ['resource', 'query'=>'string', 'dbpath='=>'string'], 'dbplus_rrename' => ['int', 'relation'=>'resource', 'name'=>'string'], 'dbplus_rsecindex' => ['mixed', 'relation'=>'resource', 'domlist'=>'mixed', 'type'=>'int'], 'dbplus_runlink' => ['int', 'relation'=>'resource'], 'dbplus_rzap' => ['int', 'relation'=>'resource'], 'dbplus_savepos' => ['int', 'relation'=>'resource'], 'dbplus_setindex' => ['int', 'relation'=>'resource', 'idx_name'=>'string'], 'dbplus_setindexbynumber' => ['int', 'relation'=>'resource', 'idx_number'=>'int'], 'dbplus_sql' => ['resource', 'query'=>'string', 'server='=>'string', 'dbpath='=>'string'], 'dbplus_tcl' => ['string', 'sid'=>'int', 'script'=>'string'], 'dbplus_tremove' => ['int', 'relation'=>'resource', 'tuple'=>'array', 'current='=>'array'], 'dbplus_undo' => ['int', 'relation'=>'resource'], 'dbplus_undoprepare' => ['int', 'relation'=>'resource'], 'dbplus_unlockrel' => ['int', 'relation'=>'resource'], 'dbplus_unselect' => ['int', 'relation'=>'resource'], 'dbplus_update' => ['int', 'relation'=>'resource', 'old'=>'array', 'new'=>'array'], 'dbplus_xlockrel' => ['int', 'relation'=>'resource'], 'dbplus_xunlockrel' => ['int', 'relation'=>'resource'], 'dbx_close' => ['int', 'link_identifier'=>'object'], 'dbx_compare' => ['int', 'row_a'=>'array', 'row_b'=>'array', 'column_key'=>'string', 'flags='=>'int'], 'dbx_connect' => ['object', 'module'=>'mixed', 'host'=>'string', 'database'=>'string', 'username'=>'string', 'password'=>'string', 'persistent='=>'int'], 'dbx_error' => ['string', 'link_identifier'=>'object'], 'dbx_escape_string' => ['string', 'link_identifier'=>'object', 'text'=>'string'], 'dbx_fetch_row' => ['mixed', 'result_identifier'=>'object'], 'dbx_query' => ['mixed', 'link_identifier'=>'object', 'sql_statement'=>'string', 'flags='=>'int'], 'dbx_sort' => ['bool', 'result'=>'object', 'user_compare_function'=>'string'], 'dcgettext' => ['string', 'domain_name'=>'string', 'msgid'=>'string', 'category'=>'int'], 'dcngettext' => ['string', 'domain'=>'string', 'msgid1'=>'string', 'msgid2'=>'string', 'n'=>'int', 'category'=>'int'], 'deaggregate' => ['', 'object'=>'object', 'class_name='=>'string'], 'debug_backtrace' => ['list', 'options='=>'int|bool', 'limit='=>'int'], 'debug_print_backtrace' => ['void', 'options='=>'int|bool', 'limit='=>'int'], 'debug_zval_dump' => ['void', '...var'=>'mixed'], 'debugger_connect' => [''], 'debugger_connector_pid' => [''], 'debugger_get_server_start_time' => [''], 'debugger_print' => [''], 'debugger_start_debug' => [''], 'decbin' => ['string', 'number'=>'int'], 'dechex' => ['string', 'number'=>'int'], 'decoct' => ['string', 'number'=>'int'], 'define' => ['bool', 'constant_name'=>'string', 'value'=>'mixed', 'case_insensitive='=>'bool'], 'define_syslog_variables' => ['void'], 'defined' => ['bool', 'name'=>'string'], 'deflate_add' => ['string|false', 'context'=>'resource', 'data'=>'string', 'flush_mode='=>'int'], 'deflate_init' => ['resource|false', 'encoding'=>'int', 'options='=>'array'], 'deg2rad' => ['float', 'number'=>'float'], 'dgettext' => ['string', 'domain_name'=>'string', 'msgid'=>'string'], 'dio_close' => ['void', 'fd'=>'resource'], 'dio_fcntl' => ['mixed', 'fd'=>'resource', 'cmd'=>'int', 'args='=>'mixed'], 'dio_open' => ['resource|false', 'filename'=>'string', 'flags'=>'int', 'mode='=>'int'], 'dio_read' => ['string', 'fd'=>'resource', 'length='=>'int'], 'dio_seek' => ['int', 'fd'=>'resource', 'pos'=>'int', 'whence='=>'int'], 'dio_stat' => ['?array', 'fd'=>'resource'], 'dio_tcsetattr' => ['bool', 'fd'=>'resource', 'options'=>'array'], 'dio_truncate' => ['bool', 'fd'=>'resource', 'offset'=>'int'], 'dio_write' => ['int', 'fd'=>'resource', 'data'=>'string', 'length='=>'int'], 'dir' => ['Directory|false|null', 'directory'=>'string', 'context='=>'resource'], 'Directory::close' => ['void', 'dir_handle='=>'resource'], 'Directory::read' => ['string|false', 'dir_handle='=>'resource'], 'Directory::rewind' => ['void', 'dir_handle='=>'resource'], 'DirectoryIterator::__construct' => ['void', 'path'=>'string'], 'DirectoryIterator::__toString' => ['string'], 'DirectoryIterator::current' => ['DirectoryIterator'], 'DirectoryIterator::getATime' => ['int'], 'DirectoryIterator::getBasename' => ['string', 'suffix='=>'string'], 'DirectoryIterator::getCTime' => ['int'], 'DirectoryIterator::getExtension' => ['string'], 'DirectoryIterator::getFileInfo' => ['SplFileInfo', 'class_name='=>'string'], 'DirectoryIterator::getFilename' => ['string'], 'DirectoryIterator::getGroup' => ['int'], 'DirectoryIterator::getInode' => ['int'], 'DirectoryIterator::getLinkTarget' => ['string'], 'DirectoryIterator::getMTime' => ['int'], 'DirectoryIterator::getOwner' => ['int'], 'DirectoryIterator::getPath' => ['string'], 'DirectoryIterator::getPathInfo' => ['SplFileInfo', 'class_name='=>'string'], 'DirectoryIterator::getPathname' => ['string'], 'DirectoryIterator::getPerms' => ['int'], 'DirectoryIterator::getRealPath' => ['string'], 'DirectoryIterator::getSize' => ['int'], 'DirectoryIterator::getType' => ['string'], 'DirectoryIterator::isDir' => ['bool'], 'DirectoryIterator::isDot' => ['bool'], 'DirectoryIterator::isExecutable' => ['bool'], 'DirectoryIterator::isFile' => ['bool'], 'DirectoryIterator::isLink' => ['bool'], 'DirectoryIterator::isReadable' => ['bool'], 'DirectoryIterator::isWritable' => ['bool'], 'DirectoryIterator::key' => ['string'], 'DirectoryIterator::next' => ['void'], 'DirectoryIterator::openFile' => ['SplFileObject', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'DirectoryIterator::rewind' => ['void'], 'DirectoryIterator::seek' => ['void', 'position'=>'int'], 'DirectoryIterator::setFileClass' => ['void', 'class_name='=>'string'], 'DirectoryIterator::setInfoClass' => ['void', 'class_name='=>'string'], 'DirectoryIterator::valid' => ['bool'], 'dirname' => ['string', 'path'=>'string', 'levels='=>'int'], 'disk_free_space' => ['float|false', 'path'=>'string'], 'disk_total_space' => ['float|false', 'path'=>'string'], 'diskfreespace' => ['float|false', 'path'=>'string'], 'display_disabled_function' => [''], 'dl' => ['bool', 'extension_filename'=>'string'], 'dngettext' => ['string', 'domain'=>'string', 'msgid1'=>'string', 'msgid2'=>'string', 'count'=>'int'], 'dns_check_record' => ['bool', 'host'=>'string', 'type='=>'string'], 'dns_get_mx' => ['bool', 'hostname'=>'string', '&w_mxhosts'=>'array', '&w_weight'=>'array'], 'dns_get_record' => ['list|false', 'hostname'=>'string', 'type='=>'int', '&w_authns='=>'array', '&w_addtl='=>'array', 'raw='=>'bool'], 'dom_document_relaxNG_validate_file' => ['bool', 'filename'=>'string'], 'dom_document_relaxNG_validate_xml' => ['bool', 'source'=>'string'], 'dom_document_schema_validate' => ['bool', 'source'=>'string', 'flags'=>'int'], 'dom_document_schema_validate_file' => ['bool', 'filename'=>'string', 'flags'=>'int'], 'dom_document_xinclude' => ['int', 'options'=>'int'], 'dom_import_simplexml' => ['DOMElement|false', 'node'=>'SimpleXMLElement'], 'dom_xpath_evaluate' => ['', 'expr'=>'string', 'context'=>'DOMNode', 'registernodens'=>'bool'], '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'], 'DomainException::__toString' => ['string'], 'DomainException::__wakeup' => ['void'], 'DomainException::getCode' => ['int'], 'DomainException::getFile' => ['string'], 'DomainException::getLine' => ['int'], 'DomainException::getMessage' => ['string'], 'DomainException::getPrevious' => ['Throwable|DomainException|null'], 'DomainException::getTrace' => ['list>'], 'DomainException::getTraceAsString' => ['string'], 'DOMAttr::__construct' => ['void', 'name'=>'string', 'value='=>'string'], 'DOMAttr::getLineNo' => ['int'], 'DOMAttr::getNodePath' => ['?string'], 'DOMAttr::hasAttributes' => ['bool'], 'DOMAttr::hasChildNodes' => ['bool'], 'DOMAttr::insertBefore' => ['DOMNode', 'newnode'=>'DOMNode', 'refnode='=>'DOMNode'], 'DOMAttr::isDefaultNamespace' => ['bool', 'namespaceuri'=>'string'], 'DOMAttr::isId' => ['bool'], 'DOMAttr::isSameNode' => ['bool', 'node'=>'DOMNode'], 'DOMAttr::isSupported' => ['bool', 'feature'=>'string', 'version'=>'string'], 'DOMAttr::lookupNamespaceUri' => ['string', 'prefix'=>'string'], 'DOMAttr::lookupPrefix' => ['string', 'namespaceuri'=>'string'], 'DOMAttr::normalize' => ['void'], 'DOMAttr::removeChild' => ['DOMNode', 'oldnode'=>'DOMNode'], 'DOMAttr::replaceChild' => ['DOMNode', 'newnode'=>'DOMNode', 'oldnode'=>'DOMNode'], 'DomAttribute::name' => ['string'], 'DomAttribute::set_value' => ['bool', 'content'=>'string'], 'DomAttribute::specified' => ['bool'], 'DomAttribute::value' => ['string'], 'DOMCdataSection::__construct' => ['void', 'value'=>'string'], 'DOMCharacterData::appendData' => ['void', 'data'=>'string'], 'DOMCharacterData::deleteData' => ['void', 'offset'=>'int', 'count'=>'int'], 'DOMCharacterData::insertData' => ['void', 'offset'=>'int', 'data'=>'string'], 'DOMCharacterData::replaceData' => ['void', 'offset'=>'int', 'count'=>'int', 'data'=>'string'], 'DOMCharacterData::substringData' => ['string', 'offset'=>'int', 'count'=>'int'], 'DOMComment::__construct' => ['void', 'value='=>'string'], 'DOMDocument::__construct' => ['void', 'version='=>'string', 'encoding='=>'string'], 'DOMDocument::createAttribute' => ['DOMAttr|false', 'name'=>'string'], 'DOMDocument::createAttributeNS' => ['DOMAttr|false', 'namespaceuri'=>'string', 'qualifiedname'=>'string'], 'DOMDocument::createCDATASection' => ['DOMCDATASection|false', 'data'=>'string'], 'DOMDocument::createComment' => ['DOMComment|false', 'data'=>'string'], 'DOMDocument::createDocumentFragment' => ['DOMDocumentFragment|false'], 'DOMDocument::createElement' => ['DOMElement|false', 'name'=>'string', 'value='=>'string'], 'DOMDocument::createElementNS' => ['DOMElement|false', 'namespaceuri'=>'string', 'qualifiedname'=>'string', 'value='=>'string'], 'DOMDocument::createEntityReference' => ['DOMEntityReference|false', 'name'=>'string'], 'DOMDocument::createProcessingInstruction' => ['DOMProcessingInstruction|false', 'target'=>'string', 'data='=>'string'], 'DOMDocument::createTextNode' => ['DOMText|false', 'content'=>'string'], 'DOMDocument::getElementById' => ['?DOMElement', 'elementid'=>'string'], 'DOMDocument::getElementsByTagName' => ['DOMNodeList', 'name'=>'string'], 'DOMDocument::getElementsByTagNameNS' => ['DOMNodeList', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMDocument::importNode' => ['DOMNode|false', 'importednode'=>'DOMNode', 'deep='=>'bool'], 'DOMDocument::load' => ['DOMDocument|bool', 'filename'=>'string', 'options='=>'int'], 'DOMDocument::loadHTML' => ['bool', 'source'=>'string', 'options='=>'int'], 'DOMDocument::loadHTMLFile' => ['bool', 'filename'=>'string', 'options='=>'int'], 'DOMDocument::loadXML' => ['DOMDocument|bool', 'source'=>'string', 'options='=>'int'], 'DOMDocument::normalizeDocument' => ['void'], 'DOMDocument::registerNodeClass' => ['bool', 'baseclass'=>'string', 'extendedclass'=>'string'], 'DOMDocument::relaxNGValidate' => ['bool', 'filename'=>'string'], 'DOMDocument::relaxNGValidateSource' => ['bool', 'source'=>'string'], 'DOMDocument::save' => ['int|false', 'filename'=>'string', 'options='=>'int'], 'DOMDocument::saveHTML' => ['string|false', 'node='=>'?DOMNode'], 'DOMDocument::saveHTMLFile' => ['int|false', 'filename'=>'string'], 'DOMDocument::saveXML' => ['string|false', 'node='=>'?DOMNode', 'options='=>'int'], 'DOMDocument::schemaValidate' => ['bool', 'filename'=>'string', 'flags='=>'int'], 'DOMDocument::schemaValidateSource' => ['bool', 'source'=>'string', 'flags='=>'int'], 'DOMDocument::validate' => ['bool'], 'DOMDocument::xinclude' => ['int', 'options='=>'int'], 'DOMDocumentFragment::__construct' => ['void'], 'DOMDocumentFragment::appendXML' => ['bool', 'data'=>'string'], 'DomDocumentType::entities' => ['array'], 'DomDocumentType::internal_subset' => ['bool'], 'DomDocumentType::name' => ['string'], 'DomDocumentType::notations' => ['array'], 'DomDocumentType::public_id' => ['string'], 'DomDocumentType::system_id' => ['string'], 'DOMElement::__construct' => ['void', 'name'=>'string', 'value='=>'string', 'uri='=>'string'], 'DOMElement::get_attribute' => ['string', 'name'=>'string'], 'DOMElement::get_attribute_node' => ['DomAttribute', 'name'=>'string'], 'DOMElement::get_elements_by_tagname' => ['array', 'name'=>'string'], 'DOMElement::getAttribute' => ['string', 'name'=>'string'], 'DOMElement::getAttributeNode' => ['DOMAttr', 'name'=>'string'], 'DOMElement::getAttributeNodeNS' => ['DOMAttr', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::getAttributeNS' => ['string', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::getElementsByTagName' => ['DOMNodeList', 'name'=>'string'], 'DOMElement::getElementsByTagNameNS' => ['DOMNodeList', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::has_attribute' => ['bool', 'name'=>'string'], 'DOMElement::hasAttribute' => ['bool', 'name'=>'string'], 'DOMElement::hasAttributeNS' => ['bool', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::remove_attribute' => ['bool', 'name'=>'string'], 'DOMElement::removeAttribute' => ['bool', 'name'=>'string'], 'DOMElement::removeAttributeNode' => ['bool', 'oldnode'=>'DOMAttr'], 'DOMElement::removeAttributeNS' => ['bool', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::set_attribute' => ['DomAttribute', 'name'=>'string', 'value'=>'string'], 'DOMElement::set_attribute_node' => ['DomNode', 'attr'=>'DOMNode'], 'DOMElement::setAttribute' => ['DOMAttr|false', 'name'=>'string', 'value'=>'string'], 'DOMElement::setAttributeNode' => ['?DOMAttr', 'attr'=>'DOMAttr'], 'DOMElement::setAttributeNodeNS' => ['DOMAttr', 'attr'=>'DOMAttr'], 'DOMElement::setAttributeNS' => ['void', 'namespaceuri'=>'string', 'qualifiedname'=>'string', 'value'=>'string'], 'DOMElement::setIdAttribute' => ['void', 'name'=>'string', 'isid'=>'bool'], 'DOMElement::setIdAttributeNode' => ['void', 'attr'=>'DOMAttr', 'isid'=>'bool'], 'DOMElement::setIdAttributeNS' => ['void', 'namespaceuri'=>'string', 'localname'=>'string', 'isid'=>'bool'], 'DOMElement::tagname' => ['string'], 'DOMEntityReference::__construct' => ['void', 'name'=>'string'], 'DOMImplementation::__construct' => ['void'], 'DOMImplementation::createDocument' => ['DOMDocument', 'namespaceuri='=>'string', 'qualifiedname='=>'string', 'doctype='=>'DOMDocumentType'], 'DOMImplementation::createDocumentType' => ['DOMDocumentType', 'qualifiedname='=>'string', 'publicid='=>'string', 'systemid='=>'string'], 'DOMImplementation::hasFeature' => ['bool', 'feature'=>'string', 'version'=>'string'], 'DOMNamedNodeMap::count' => ['int'], 'DOMNamedNodeMap::getNamedItem' => ['?DOMNode', 'name'=>'string'], 'DOMNamedNodeMap::getNamedItemNS' => ['?DOMNode', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMNamedNodeMap::item' => ['?DOMNode', 'index'=>'int'], 'DomNode::add_namespace' => ['bool', 'uri'=>'string', 'prefix'=>'string'], 'DomNode::append_child' => ['DOMNode', 'newnode'=>'DOMNode'], 'DOMNode::appendChild' => ['DOMNode', 'newnode'=>'DOMNode'], 'DOMNode::C14N' => ['string', 'exclusive='=>'bool', 'with_comments='=>'bool', 'xpath='=>'array', 'ns_prefixes='=>'array'], 'DOMNode::C14NFile' => ['int|false', 'uri='=>'string', 'exclusive='=>'bool', 'with_comments='=>'bool', 'xpath='=>'array', 'ns_prefixes='=>'array'], 'DOMNode::cloneNode' => ['DOMNode', 'deep='=>'bool'], 'DOMNode::getLineNo' => ['int'], 'DOMNode::getNodePath' => ['?string'], 'DOMNode::hasAttributes' => ['bool'], 'DOMNode::hasChildNodes' => ['bool'], 'DOMNode::insertBefore' => ['DOMNode', 'newnode'=>'DOMNode', 'refnode='=>'DOMNode|null'], 'DOMNode::isDefaultNamespace' => ['bool', 'namespaceuri'=>'string'], 'DOMNode::isSameNode' => ['bool', 'node'=>'DOMNode'], 'DOMNode::isSupported' => ['bool', 'feature'=>'string', 'version'=>'string'], 'DOMNode::lookupNamespaceURI' => ['string', 'prefix'=>'string'], 'DOMNode::lookupPrefix' => ['string', 'namespaceuri'=>'string'], 'DOMNode::normalize' => ['void'], 'DOMNode::removeChild' => ['DOMNode', 'oldnode'=>'DOMNode'], 'DOMNode::replaceChild' => ['DOMNode|false', 'newnode'=>'DOMNode', 'oldnode'=>'DOMNode'], 'DOMNodeList::count' => ['int'], 'DOMNodeList::item' => ['?DOMNode', 'index'=>'int'], 'DOMProcessingInstruction::__construct' => ['void', 'name'=>'string', 'value'=>'string'], 'DomProcessingInstruction::data' => ['string'], 'DomProcessingInstruction::target' => ['string'], 'DOMText::__construct' => ['void', 'value='=>'string'], 'DOMText::isElementContentWhitespace' => ['bool'], 'DOMText::isWhitespaceInElementContent' => ['bool'], 'DOMText::splitText' => ['DOMText', 'offset'=>'int'], 'domxml_new_doc' => ['DomDocument', 'version'=>'string'], 'domxml_open_file' => ['DomDocument', 'filename'=>'string', 'mode='=>'int', 'error='=>'array'], 'domxml_open_mem' => ['DomDocument', 'string'=>'string', 'mode='=>'int', 'error='=>'array'], 'domxml_version' => ['string'], 'domxml_xmltree' => ['DomDocument', 'string'=>'string'], 'domxml_xslt_stylesheet' => ['DomXsltStylesheet', 'xsl_buf'=>'string'], 'domxml_xslt_stylesheet_doc' => ['DomXsltStylesheet', 'xsl_doc'=>'DOMDocument'], 'domxml_xslt_stylesheet_file' => ['DomXsltStylesheet', 'xsl_file'=>'string'], 'domxml_xslt_version' => ['int'], 'DOMXPath::__construct' => ['void', 'doc'=>'DOMDocument'], 'DOMXPath::evaluate' => ['mixed', 'expression'=>'string', 'contextnode='=>'?DOMNode', 'registernodens='=>'bool'], 'DOMXPath::query' => ['DOMNodeList|false', 'expression'=>'string', 'contextnode='=>'DOMNode|null', 'registernodens='=>'bool'], 'DOMXPath::registerNamespace' => ['bool', 'prefix'=>'string', 'namespaceuri'=>'string'], 'DOMXPath::registerPhpFunctions' => ['void', 'restrict='=>'mixed'], 'DomXsltStylesheet::process' => ['DomDocument', 'xml_doc'=>'DOMDocument', 'xslt_params='=>'array', 'is_xpath_param='=>'bool', 'profile_filename='=>'string'], 'DomXsltStylesheet::result_dump_file' => ['string', 'xmldoc'=>'DOMDocument', 'filename'=>'string'], 'DomXsltStylesheet::result_dump_mem' => ['string', 'xmldoc'=>'DOMDocument'], 'DOTNET::__call' => ['mixed', 'name'=>'string', 'args'=>''], 'DOTNET::__construct' => ['void', 'assembly_name'=>'string', 'class_name'=>'string', 'codepage='=>'int'], 'DOTNET::__get' => ['mixed', 'name'=>'string'], 'DOTNET::__set' => ['void', 'name'=>'string', 'value'=>''], 'dotnet_load' => ['int', 'assembly_name'=>'string', 'datatype_name='=>'string', 'codepage='=>'int'], 'doubleval' => ['float', 'value'=>'mixed'], 'Ds\Collection::clear' => ['void'], 'Ds\Collection::copy' => ['Ds\Collection'], 'Ds\Collection::isEmpty' => ['bool'], 'Ds\Collection::toArray' => ['array'], 'Ds\Deque::__construct' => ['void', 'values='=>'mixed'], 'Ds\Deque::allocate' => ['void', 'capacity'=>'int'], 'Ds\Deque::apply' => ['void', 'callback'=>'callable'], 'Ds\Deque::capacity' => ['int'], 'Ds\Deque::clear' => ['void'], 'Ds\Deque::contains' => ['bool', '...values='=>'mixed'], 'Ds\Deque::copy' => ['Ds\Deque'], 'Ds\Deque::count' => ['int'], 'Ds\Deque::filter' => ['Ds\Deque', 'callback='=>'callable'], 'Ds\Deque::find' => ['mixed', 'value'=>'mixed'], 'Ds\Deque::first' => ['mixed'], 'Ds\Deque::get' => ['void', 'index'=>'int'], 'Ds\Deque::insert' => ['void', 'index'=>'int', '...values='=>'mixed'], 'Ds\Deque::isEmpty' => ['bool'], 'Ds\Deque::join' => ['string', 'glue='=>'string'], 'Ds\Deque::jsonSerialize' => ['array'], 'Ds\Deque::last' => ['mixed'], 'Ds\Deque::map' => ['Ds\Deque', 'callback'=>'callable'], 'Ds\Deque::merge' => ['Ds\Deque', 'values'=>'mixed'], 'Ds\Deque::pop' => ['mixed'], 'Ds\Deque::push' => ['void', '...values='=>'mixed'], 'Ds\Deque::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Deque::remove' => ['mixed', 'index'=>'int'], 'Ds\Deque::reverse' => ['void'], 'Ds\Deque::reversed' => ['Ds\Deque'], 'Ds\Deque::rotate' => ['void', 'rotations'=>'int'], 'Ds\Deque::set' => ['void', 'index'=>'int', 'value'=>'mixed'], 'Ds\Deque::shift' => ['mixed'], 'Ds\Deque::slice' => ['Ds\Deque', 'index'=>'int', 'length='=>'?int'], 'Ds\Deque::sort' => ['void', 'comparator='=>'callable'], 'Ds\Deque::sorted' => ['Ds\Deque', 'comparator='=>'callable'], 'Ds\Deque::sum' => ['int|float'], 'Ds\Deque::toArray' => ['array'], 'Ds\Deque::unshift' => ['void', '...values='=>'mixed'], 'Ds\Hashable::equals' => ['bool', 'object'=>'mixed'], 'Ds\Hashable::hash' => ['mixed'], 'Ds\Map::__construct' => ['void', 'values='=>'mixed'], 'Ds\Map::allocate' => ['void', 'capacity'=>'int'], 'Ds\Map::apply' => ['void', 'callback'=>'callable'], 'Ds\Map::capacity' => ['int'], 'Ds\Map::clear' => ['void'], 'Ds\Map::copy' => ['Ds\Map'], 'Ds\Map::count' => ['int'], 'Ds\Map::diff' => ['Ds\Map', 'map'=>'Ds\Map'], 'Ds\Map::filter' => ['Ds\Map', 'callback='=>'callable'], 'Ds\Map::first' => ['Ds\Pair'], 'Ds\Map::get' => ['mixed', 'key'=>'mixed', 'default='=>'mixed'], 'Ds\Map::hasKey' => ['bool', 'key'=>'mixed'], 'Ds\Map::hasValue' => ['bool', 'value'=>'mixed'], 'Ds\Map::intersect' => ['Ds\Map', 'map'=>'Ds\Map'], 'Ds\Map::isEmpty' => ['bool'], 'Ds\Map::jsonSerialize' => ['array'], 'Ds\Map::keys' => ['Ds\Set'], 'Ds\Map::ksort' => ['void', 'comparator='=>'callable'], 'Ds\Map::ksorted' => ['Ds\Map', 'comparator='=>'callable'], 'Ds\Map::last' => ['Ds\Pair'], 'Ds\Map::map' => ['Ds\Map', 'callback'=>'callable'], 'Ds\Map::merge' => ['Ds\Map', 'values'=>'mixed'], 'Ds\Map::pairs' => ['Ds\Sequence'], 'Ds\Map::put' => ['void', 'key'=>'mixed', 'value'=>'mixed'], 'Ds\Map::putAll' => ['void', 'values'=>'mixed'], 'Ds\Map::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Map::remove' => ['mixed', 'key'=>'mixed', 'default='=>'mixed'], 'Ds\Map::reverse' => ['void'], 'Ds\Map::reversed' => ['Ds\Map'], 'Ds\Map::skip' => ['Ds\Pair', 'position'=>'int'], 'Ds\Map::slice' => ['Ds\Map', 'index'=>'int', 'length='=>'?int'], 'Ds\Map::sort' => ['void', 'comparator='=>'callable'], 'Ds\Map::sorted' => ['Ds\Map', 'comparator='=>'callable'], 'Ds\Map::sum' => ['int|float'], 'Ds\Map::toArray' => ['array'], 'Ds\Map::union' => ['Ds\Map', 'map'=>'Ds\Map'], 'Ds\Map::values' => ['Ds\Sequence'], 'Ds\Map::xor' => ['Ds\Map', 'map'=>'Ds\Map'], 'Ds\Pair::__construct' => ['void', 'key='=>'mixed', 'value='=>'mixed'], 'Ds\Pair::clear' => ['void'], 'Ds\Pair::copy' => ['Ds\Pair'], 'Ds\Pair::isEmpty' => ['bool'], 'Ds\Pair::jsonSerialize' => ['array'], 'Ds\Pair::toArray' => ['array'], 'Ds\PriorityQueue::__construct' => ['void'], 'Ds\PriorityQueue::allocate' => ['void', 'capacity'=>'int'], 'Ds\PriorityQueue::capacity' => ['int'], 'Ds\PriorityQueue::clear' => ['void'], 'Ds\PriorityQueue::copy' => ['Ds\PriorityQueue'], 'Ds\PriorityQueue::count' => ['int'], 'Ds\PriorityQueue::isEmpty' => ['bool'], 'Ds\PriorityQueue::jsonSerialize' => ['array'], 'Ds\PriorityQueue::peek' => ['mixed'], 'Ds\PriorityQueue::pop' => ['mixed'], 'Ds\PriorityQueue::push' => ['void', 'value'=>'mixed', 'priority'=>'int'], 'Ds\PriorityQueue::toArray' => ['array'], 'Ds\Queue::__construct' => ['void', 'values='=>'mixed'], 'Ds\Queue::allocate' => ['void', 'capacity'=>'int'], 'Ds\Queue::capacity' => ['int'], 'Ds\Queue::clear' => ['void'], 'Ds\Queue::copy' => ['Ds\Queue'], 'Ds\Queue::count' => ['int'], 'Ds\Queue::isEmpty' => ['bool'], 'Ds\Queue::jsonSerialize' => ['array'], 'Ds\Queue::peek' => ['mixed'], 'Ds\Queue::pop' => ['mixed'], 'Ds\Queue::push' => ['void', '...values='=>'mixed'], 'Ds\Queue::toArray' => ['array'], 'Ds\Sequence::allocate' => ['void', 'capacity'=>'int'], 'Ds\Sequence::apply' => ['void', 'callback'=>'callable'], 'Ds\Sequence::capacity' => ['int'], 'Ds\Sequence::contains' => ['bool', '...values='=>'mixed'], 'Ds\Sequence::filter' => ['Ds\Sequence', 'callback='=>'callable'], 'Ds\Sequence::find' => ['mixed', 'value'=>'mixed'], 'Ds\Sequence::first' => ['mixed'], 'Ds\Sequence::get' => ['mixed', 'index'=>'int'], 'Ds\Sequence::insert' => ['void', 'index'=>'int', '...values='=>'mixed'], 'Ds\Sequence::join' => ['string', 'glue='=>'string'], 'Ds\Sequence::last' => ['void'], 'Ds\Sequence::map' => ['Ds\Sequence', 'callback'=>'callable'], 'Ds\Sequence::merge' => ['Ds\Sequence', 'values'=>'mixed'], 'Ds\Sequence::pop' => ['mixed'], 'Ds\Sequence::push' => ['void', '...values='=>'mixed'], 'Ds\Sequence::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Sequence::remove' => ['mixed', 'index'=>'int'], 'Ds\Sequence::reverse' => ['void'], 'Ds\Sequence::reversed' => ['Ds\Sequence'], 'Ds\Sequence::rotate' => ['void', 'rotations'=>'int'], 'Ds\Sequence::set' => ['void', 'index'=>'int', 'value'=>'mixed'], 'Ds\Sequence::shift' => ['mixed'], 'Ds\Sequence::slice' => ['Ds\Sequence', 'index'=>'int', 'length='=>'?int'], 'Ds\Sequence::sort' => ['void', 'comparator='=>'callable'], 'Ds\Sequence::sorted' => ['Ds\Sequence', 'comparator='=>'callable'], 'Ds\Sequence::sum' => ['int|float'], 'Ds\Sequence::unshift' => ['void', '...values='=>'mixed'], 'Ds\Set::__construct' => ['void', 'values='=>'mixed'], 'Ds\Set::add' => ['void', '...values='=>'mixed'], 'Ds\Set::allocate' => ['void', 'capacity'=>'int'], 'Ds\Set::capacity' => ['int'], 'Ds\Set::clear' => ['void'], 'Ds\Set::contains' => ['bool', '...values='=>'mixed'], 'Ds\Set::copy' => ['Ds\Set'], 'Ds\Set::count' => ['int'], 'Ds\Set::diff' => ['Ds\Set', 'set'=>'Ds\Set'], 'Ds\Set::filter' => ['Ds\Set', 'callback='=>'callable'], 'Ds\Set::first' => ['mixed'], 'Ds\Set::get' => ['mixed', 'index'=>'int'], 'Ds\Set::intersect' => ['Ds\Set', 'set'=>'Ds\Set'], 'Ds\Set::isEmpty' => ['bool'], 'Ds\Set::join' => ['string', 'glue='=>'string'], 'Ds\Set::jsonSerialize' => ['array'], 'Ds\Set::last' => ['mixed'], 'Ds\Set::merge' => ['Ds\Set', 'values'=>'mixed'], 'Ds\Set::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Set::remove' => ['void', '...values='=>'mixed'], 'Ds\Set::reverse' => ['void'], 'Ds\Set::reversed' => ['Ds\Set'], 'Ds\Set::slice' => ['Ds\Set', 'index'=>'int', 'length='=>'?int'], 'Ds\Set::sort' => ['void', 'comparator='=>'callable'], 'Ds\Set::sorted' => ['Ds\Set', 'comparator='=>'callable'], 'Ds\Set::sum' => ['int|float'], 'Ds\Set::toArray' => ['array'], 'Ds\Set::union' => ['Ds\Set', 'set'=>'Ds\Set'], 'Ds\Set::xor' => ['Ds\Set', 'set'=>'Ds\Set'], 'Ds\Stack::__construct' => ['void', 'values='=>'mixed'], 'Ds\Stack::allocate' => ['void', 'capacity'=>'int'], 'Ds\Stack::capacity' => ['int'], 'Ds\Stack::clear' => ['void'], 'Ds\Stack::copy' => ['Ds\Stack'], 'Ds\Stack::count' => ['int'], 'Ds\Stack::isEmpty' => ['bool'], 'Ds\Stack::jsonSerialize' => ['array'], 'Ds\Stack::peek' => ['mixed'], 'Ds\Stack::pop' => ['mixed'], 'Ds\Stack::push' => ['void', '...values='=>'mixed'], 'Ds\Stack::toArray' => ['array'], 'Ds\Vector::__construct' => ['void', 'values='=>'mixed'], 'Ds\Vector::allocate' => ['void', 'capacity'=>'int'], 'Ds\Vector::apply' => ['void', 'callback'=>'callable'], 'Ds\Vector::capacity' => ['int'], 'Ds\Vector::clear' => ['void'], 'Ds\Vector::contains' => ['bool', '...values='=>'mixed'], 'Ds\Vector::copy' => ['Ds\Vector'], 'Ds\Vector::count' => ['int'], 'Ds\Vector::filter' => ['Ds\Vector', 'callback='=>'callable'], 'Ds\Vector::find' => ['mixed', 'value'=>'mixed'], 'Ds\Vector::first' => ['mixed'], 'Ds\Vector::get' => ['mixed', 'index'=>'int'], 'Ds\Vector::insert' => ['void', 'index'=>'int', '...values='=>'mixed'], 'Ds\Vector::isEmpty' => ['bool'], 'Ds\Vector::join' => ['string', 'glue='=>'string'], 'Ds\Vector::jsonSerialize' => ['array'], 'Ds\Vector::last' => ['mixed'], 'Ds\Vector::map' => ['Ds\Vector', 'callback'=>'callable'], 'Ds\Vector::merge' => ['Ds\Vector', 'values'=>'mixed'], 'Ds\Vector::pop' => ['mixed'], 'Ds\Vector::push' => ['void', '...values='=>'mixed'], 'Ds\Vector::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Vector::remove' => ['mixed', 'index'=>'int'], 'Ds\Vector::reverse' => ['void'], 'Ds\Vector::reversed' => ['Ds\Vector'], 'Ds\Vector::rotate' => ['void', 'rotations'=>'int'], 'Ds\Vector::set' => ['void', 'index'=>'int', 'value'=>'mixed'], 'Ds\Vector::shift' => ['mixed'], 'Ds\Vector::slice' => ['Ds\Vector', 'index'=>'int', 'length='=>'?int'], 'Ds\Vector::sort' => ['void', 'comparator='=>'callable'], 'Ds\Vector::sorted' => ['Ds\Vector', 'comparator='=>'callable'], 'Ds\Vector::sum' => ['int|float'], 'Ds\Vector::toArray' => ['array'], 'Ds\Vector::unshift' => ['void', '...values='=>'mixed'], 'each' => ['array{0:int|string,key:int|string,1:mixed,value:mixed}', '&r_arr'=>'array'], 'easter_date' => ['int', 'year='=>'int'], 'easter_days' => ['int', 'year='=>'int', 'method='=>'int'], 'echo' => ['void', 'arg1'=>'string', '...args='=>'string'], 'eio_busy' => ['resource', 'delay'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_cancel' => ['void', 'req'=>'resource'], 'eio_chmod' => ['resource', 'path'=>'string', 'mode'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_chown' => ['resource', 'path'=>'string', 'uid'=>'int', 'gid='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_close' => ['resource', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_custom' => ['resource', 'execute'=>'callable', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_dup2' => ['resource', 'fd'=>'mixed', 'fd2'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_event_loop' => ['bool'], 'eio_fallocate' => ['resource', 'fd'=>'mixed', 'mode'=>'int', 'offset'=>'int', 'length'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fchmod' => ['resource', 'fd'=>'mixed', 'mode'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fchown' => ['resource', 'fd'=>'mixed', 'uid'=>'int', 'gid='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fdatasync' => ['resource', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fstat' => ['resource', 'fd'=>'mixed', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_fstatvfs' => ['resource', 'fd'=>'mixed', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_fsync' => ['resource', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_ftruncate' => ['resource', 'fd'=>'mixed', 'offset='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_futime' => ['resource', 'fd'=>'mixed', 'atime'=>'float', 'mtime'=>'float', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_get_event_stream' => ['mixed'], 'eio_get_last_error' => ['string', 'req'=>'resource'], 'eio_grp' => ['resource', 'callback'=>'callable', 'data='=>'string'], 'eio_grp_add' => ['void', 'grp'=>'resource', 'req'=>'resource'], 'eio_grp_cancel' => ['void', 'grp'=>'resource'], 'eio_grp_limit' => ['void', 'grp'=>'resource', 'limit'=>'int'], 'eio_init' => ['void'], 'eio_link' => ['resource', 'path'=>'string', 'new_path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_lstat' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_mkdir' => ['resource', 'path'=>'string', 'mode'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_mknod' => ['resource', 'path'=>'string', 'mode'=>'int', 'dev'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_nop' => ['resource', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_npending' => ['int'], 'eio_nready' => ['int'], 'eio_nreqs' => ['int'], 'eio_nthreads' => ['int'], 'eio_open' => ['resource', 'path'=>'string', 'flags'=>'int', 'mode'=>'int', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_poll' => ['int'], 'eio_read' => ['resource', 'fd'=>'mixed', 'length'=>'int', 'offset'=>'int', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_readahead' => ['resource', 'fd'=>'mixed', 'offset'=>'int', 'length'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_readdir' => ['resource', 'path'=>'string', 'flags'=>'int', 'pri'=>'int', 'callback'=>'callable', 'data='=>'string'], 'eio_readlink' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'string'], 'eio_realpath' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'string'], 'eio_rename' => ['resource', 'path'=>'string', 'new_path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_rmdir' => ['resource', 'path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_seek' => ['resource', 'fd'=>'mixed', 'offset'=>'int', 'whence'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_sendfile' => ['resource', 'out_fd'=>'mixed', 'in_fd'=>'mixed', 'offset'=>'int', 'length'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'string'], 'eio_set_max_idle' => ['void', 'nthreads'=>'int'], 'eio_set_max_parallel' => ['void', 'nthreads'=>'int'], 'eio_set_max_poll_reqs' => ['void', 'nreqs'=>'int'], 'eio_set_max_poll_time' => ['void', 'nseconds'=>'float'], 'eio_set_min_parallel' => ['void', 'nthreads'=>'string'], 'eio_stat' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_statvfs' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_symlink' => ['resource', 'path'=>'string', 'new_path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_sync' => ['resource', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_sync_file_range' => ['resource', 'fd'=>'mixed', 'offset'=>'int', 'nbytes'=>'int', 'flags'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_syncfs' => ['resource', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_truncate' => ['resource', 'path'=>'string', 'offset='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_unlink' => ['resource', 'path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_utime' => ['resource', 'path'=>'string', 'atime'=>'float', 'mtime'=>'float', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_write' => ['resource', 'fd'=>'mixed', 'string'=>'string', 'length='=>'int', 'offset='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'empty' => ['bool', 'value'=>'mixed'], 'EmptyIterator::current' => ['mixed'], 'EmptyIterator::key' => ['mixed'], 'EmptyIterator::next' => ['void'], 'EmptyIterator::rewind' => ['void'], 'EmptyIterator::valid' => ['bool'], 'enchant_broker_describe' => ['array', 'broker'=>'resource'], 'enchant_broker_dict_exists' => ['bool', 'broker'=>'resource', 'tag'=>'string'], 'enchant_broker_free' => ['bool', 'broker'=>'resource'], 'enchant_broker_free_dict' => ['bool', 'dict'=>'resource'], 'enchant_broker_get_dict_path' => ['string', 'broker'=>'resource', 'dict_type'=>'int'], 'enchant_broker_get_error' => ['string|false', 'broker'=>'resource'], 'enchant_broker_init' => ['resource|false'], 'enchant_broker_list_dicts' => ['array|false', 'broker'=>'resource'], 'enchant_broker_request_dict' => ['resource|false', 'broker'=>'resource', 'tag'=>'string'], 'enchant_broker_request_pwl_dict' => ['resource|false', 'broker'=>'resource', 'filename'=>'string'], 'enchant_broker_set_dict_path' => ['bool', 'broker'=>'resource', 'dict_type'=>'int', 'value'=>'string'], 'enchant_broker_set_ordering' => ['bool', 'broker'=>'resource', 'tag'=>'string', 'ordering'=>'string'], 'enchant_dict_add_to_personal' => ['void', 'dict'=>'resource', 'word'=>'string'], 'enchant_dict_add_to_session' => ['void', 'dict'=>'resource', 'word'=>'string'], 'enchant_dict_check' => ['bool', 'dict'=>'resource', 'word'=>'string'], 'enchant_dict_describe' => ['array', 'dict'=>'resource'], 'enchant_dict_get_error' => ['string', 'dict'=>'resource'], 'enchant_dict_is_in_session' => ['bool', 'dict'=>'resource', 'word'=>'string'], 'enchant_dict_quick_check' => ['bool', 'dict'=>'resource', 'word'=>'string', '&w_suggestions='=>'array'], 'enchant_dict_store_replacement' => ['void', 'dict'=>'resource', 'mis'=>'string', 'cor'=>'string'], 'enchant_dict_suggest' => ['array', 'dict'=>'resource', 'word'=>'string'], 'end' => ['mixed|false', '&r_array'=>'array|object'], 'Error::__clone' => ['void'], 'Error::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?Error'], 'Error::__toString' => ['string'], 'Error::getCode' => ['int'], 'Error::getFile' => ['string'], 'Error::getLine' => ['int'], 'Error::getMessage' => ['string'], 'Error::getPrevious' => ['Throwable|Error|null'], 'Error::getTrace' => ['list>'], 'Error::getTraceAsString' => ['string'], 'error_clear_last' => ['void'], 'error_get_last' => ['?array{type:int,message:string,file:string,line:int}'], 'error_log' => ['bool', 'message'=>'string', 'message_type='=>'int', 'destination='=>'string', 'extra_headers='=>'string'], 'error_reporting' => ['int', 'new_error_level='=>'int'], 'ErrorException::__clone' => ['void'], 'ErrorException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'severity='=>'int', 'filename='=>'string', 'lineno='=>'int', 'previous='=>'?Throwable|?ErrorException'], 'ErrorException::__toString' => ['string'], 'ErrorException::getCode' => ['int'], 'ErrorException::getFile' => ['string'], 'ErrorException::getLine' => ['int'], 'ErrorException::getMessage' => ['string'], 'ErrorException::getPrevious' => ['Throwable|ErrorException|null'], 'ErrorException::getSeverity' => ['int'], 'ErrorException::getTrace' => ['list>'], 'ErrorException::getTraceAsString' => ['string'], 'escapeshellarg' => ['string', 'arg'=>'string'], 'escapeshellcmd' => ['string', 'command'=>'string'], 'Ev::backend' => ['int'], 'Ev::depth' => ['int'], 'Ev::embeddableBackends' => ['int'], 'Ev::feedSignal' => ['void', 'signum'=>'int'], 'Ev::feedSignalEvent' => ['void', 'signum'=>'int'], 'Ev::iteration' => ['int'], 'Ev::now' => ['float'], 'Ev::nowUpdate' => ['void'], 'Ev::recommendedBackends' => ['int'], 'Ev::resume' => ['void'], 'Ev::run' => ['void', 'flags='=>'int'], 'Ev::sleep' => ['void', 'seconds'=>'float'], 'Ev::stop' => ['void', 'how='=>'int'], 'Ev::supportedBackends' => ['int'], 'Ev::suspend' => ['void'], 'Ev::time' => ['float'], 'Ev::verify' => ['void'], 'eval' => ['mixed', 'code_str'=>'string'], 'EvCheck::__construct' => ['void', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvCheck::clear' => ['int'], 'EvCheck::createStopped' => ['EvCheck', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvCheck::feed' => ['void', 'events'=>'int'], 'EvCheck::getLoop' => ['EvLoop'], 'EvCheck::invoke' => ['void', 'events'=>'int'], 'EvCheck::keepAlive' => ['void', 'value'=>'bool'], 'EvCheck::setCallback' => ['void', 'callback'=>'callable'], 'EvCheck::start' => ['void'], 'EvCheck::stop' => ['void'], 'EvChild::__construct' => ['void', 'pid'=>'int', 'trace'=>'bool', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvChild::clear' => ['int'], 'EvChild::createStopped' => ['EvChild', 'pid'=>'int', 'trace'=>'bool', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvChild::feed' => ['void', 'events'=>'int'], 'EvChild::getLoop' => ['EvLoop'], 'EvChild::invoke' => ['void', 'events'=>'int'], 'EvChild::keepAlive' => ['void', 'value'=>'bool'], 'EvChild::set' => ['void', 'pid'=>'int', 'trace'=>'bool'], 'EvChild::setCallback' => ['void', 'callback'=>'callable'], 'EvChild::start' => ['void'], 'EvChild::stop' => ['void'], 'EvEmbed::__construct' => ['void', 'other'=>'object', 'callback='=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvEmbed::clear' => ['int'], 'EvEmbed::createStopped' => ['EvEmbed', 'other'=>'object', 'callback='=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvEmbed::feed' => ['void', 'events'=>'int'], 'EvEmbed::getLoop' => ['EvLoop'], 'EvEmbed::invoke' => ['void', 'events'=>'int'], 'EvEmbed::keepAlive' => ['void', 'value'=>'bool'], 'EvEmbed::set' => ['void', 'other'=>'object'], 'EvEmbed::setCallback' => ['void', 'callback'=>'callable'], 'EvEmbed::start' => ['void'], 'EvEmbed::stop' => ['void'], 'EvEmbed::sweep' => ['void'], 'Event::__construct' => ['void', 'base'=>'EventBase', 'fd'=>'mixed', 'what'=>'int', 'cb'=>'callable', 'arg='=>'mixed'], 'Event::add' => ['bool', 'timeout='=>'float'], 'Event::addSignal' => ['bool', 'timeout='=>'float'], 'Event::addTimer' => ['bool', 'timeout='=>'float'], 'Event::del' => ['bool'], 'Event::delSignal' => ['bool'], 'Event::delTimer' => ['bool'], 'Event::free' => ['void'], 'Event::getSupportedMethods' => ['array'], 'Event::pending' => ['bool', 'flags'=>'int'], 'Event::set' => ['bool', 'base'=>'EventBase', 'fd'=>'mixed', 'what='=>'int', 'cb='=>'callable', 'arg='=>'mixed'], 'Event::setPriority' => ['bool', 'priority'=>'int'], 'Event::setTimer' => ['bool', 'base'=>'EventBase', 'cb'=>'callable', 'arg='=>'mixed'], 'Event::signal' => ['Event', 'base'=>'EventBase', 'signum'=>'int', 'cb'=>'callable', 'arg='=>'mixed'], 'Event::timer' => ['Event', 'base'=>'EventBase', 'cb'=>'callable', 'arg='=>'mixed'], 'event_add' => ['bool', 'event'=>'resource', 'timeout='=>'int'], 'event_base_free' => ['void', 'event_base'=>'resource'], 'event_base_loop' => ['int', 'event_base'=>'resource', 'flags='=>'int'], 'event_base_loopbreak' => ['bool', 'event_base'=>'resource'], 'event_base_loopexit' => ['bool', 'event_base'=>'resource', 'timeout='=>'int'], 'event_base_new' => ['resource|false'], 'event_base_priority_init' => ['bool', 'event_base'=>'resource', 'npriorities'=>'int'], 'event_base_reinit' => ['bool', 'event_base'=>'resource'], 'event_base_set' => ['bool', 'event'=>'resource', 'event_base'=>'resource'], 'event_buffer_base_set' => ['bool', 'bevent'=>'resource', 'event_base'=>'resource'], 'event_buffer_disable' => ['bool', 'bevent'=>'resource', 'events'=>'int'], 'event_buffer_enable' => ['bool', 'bevent'=>'resource', 'events'=>'int'], 'event_buffer_fd_set' => ['void', 'bevent'=>'resource', 'fd'=>'resource'], 'event_buffer_free' => ['void', 'bevent'=>'resource'], 'event_buffer_new' => ['resource|false', 'stream'=>'resource', 'readcb'=>'callable|null', 'writecb'=>'callable|null', 'errorcb'=>'callable', 'arg='=>'mixed'], 'event_buffer_priority_set' => ['bool', 'bevent'=>'resource', 'priority'=>'int'], 'event_buffer_read' => ['string', 'bevent'=>'resource', 'data_size'=>'int'], 'event_buffer_set_callback' => ['bool', 'event'=>'resource', 'readcb'=>'mixed', 'writecb'=>'mixed', 'errorcb'=>'mixed', 'arg='=>'mixed'], 'event_buffer_timeout_set' => ['void', 'bevent'=>'resource', 'read_timeout'=>'int', 'write_timeout'=>'int'], 'event_buffer_watermark_set' => ['void', 'bevent'=>'resource', 'events'=>'int', 'lowmark'=>'int', 'highmark'=>'int'], 'event_buffer_write' => ['bool', 'bevent'=>'resource', 'data'=>'string', 'data_size='=>'int'], 'event_del' => ['bool', 'event'=>'resource'], 'event_free' => ['void', 'event'=>'resource'], 'event_new' => ['resource|false'], 'event_priority_set' => ['bool', 'event'=>'resource', 'priority'=>'int'], 'event_set' => ['bool', 'event'=>'resource', 'fd'=>'int|resource', 'events'=>'int', 'callback'=>'callable', 'arg='=>'mixed'], 'event_timer_add' => ['bool', 'event'=>'resource', 'timeout='=>'int'], 'event_timer_del' => ['bool', 'event'=>'resource'], 'event_timer_new' => ['resource|false'], 'event_timer_pending' => ['bool', 'event'=>'resource', 'timeout='=>'int'], 'event_timer_set' => ['bool', 'event'=>'resource', 'callback'=>'callable', 'arg='=>'mixed'], 'EventBase::__construct' => ['void', 'cfg='=>'EventConfig'], 'EventBase::dispatch' => ['void'], 'EventBase::exit' => ['bool', 'timeout='=>'float'], 'EventBase::free' => ['void'], 'EventBase::getFeatures' => ['int'], 'EventBase::getMethod' => ['string', 'cfg='=>'EventConfig'], 'EventBase::getTimeOfDayCached' => ['float'], 'EventBase::gotExit' => ['bool'], 'EventBase::gotStop' => ['bool'], 'EventBase::loop' => ['bool', 'flags='=>'int'], 'EventBase::priorityInit' => ['bool', 'n_priorities'=>'int'], 'EventBase::reInit' => ['bool'], 'EventBase::stop' => ['bool'], 'EventBuffer::__construct' => ['void'], 'EventBuffer::add' => ['bool', 'data'=>'string'], 'EventBuffer::addBuffer' => ['bool', 'buf'=>'EventBuffer'], 'EventBuffer::appendFrom' => ['int', 'buf'=>'EventBuffer', 'length'=>'int'], 'EventBuffer::copyout' => ['int', '&w_data'=>'string', 'max_bytes'=>'int'], 'EventBuffer::drain' => ['bool', 'length'=>'int'], 'EventBuffer::enableLocking' => ['void'], 'EventBuffer::expand' => ['bool', 'length'=>'int'], 'EventBuffer::freeze' => ['bool', 'at_front'=>'bool'], 'EventBuffer::lock' => ['void'], 'EventBuffer::prepend' => ['bool', 'data'=>'string'], 'EventBuffer::prependBuffer' => ['bool', 'buf'=>'EventBuffer'], 'EventBuffer::pullup' => ['string', 'size'=>'int'], 'EventBuffer::read' => ['string', 'max_bytes'=>'int'], 'EventBuffer::readFrom' => ['int', 'fd'=>'mixed', 'howmuch'=>'int'], 'EventBuffer::readLine' => ['string', 'eol_style'=>'int'], 'EventBuffer::search' => ['mixed', 'what'=>'string', 'start='=>'int', 'end='=>'int'], 'EventBuffer::searchEol' => ['mixed', 'start='=>'int', 'eol_style='=>'int'], 'EventBuffer::substr' => ['string', 'start'=>'int', 'length='=>'int'], 'EventBuffer::unfreeze' => ['bool', 'at_front'=>'bool'], 'EventBuffer::unlock' => ['bool'], 'EventBuffer::write' => ['int', 'fd'=>'mixed', 'howmuch='=>'int'], 'EventBufferEvent::__construct' => ['void', 'base'=>'EventBase', 'socket='=>'mixed', 'options='=>'int', 'readcb='=>'callable', 'writecb='=>'callable', 'eventcb='=>'callable'], 'EventBufferEvent::close' => ['void'], 'EventBufferEvent::connect' => ['bool', 'addr'=>'string'], 'EventBufferEvent::connectHost' => ['bool', 'dns_base'=>'EventDnsBase', 'hostname'=>'string', 'port'=>'int', 'family='=>'int'], 'EventBufferEvent::createPair' => ['array', 'base'=>'EventBase', 'options='=>'int'], 'EventBufferEvent::disable' => ['bool', 'events'=>'int'], 'EventBufferEvent::enable' => ['bool', 'events'=>'int'], 'EventBufferEvent::free' => ['void'], 'EventBufferEvent::getDnsErrorString' => ['string'], 'EventBufferEvent::getEnabled' => ['int'], 'EventBufferEvent::getInput' => ['EventBuffer'], 'EventBufferEvent::getOutput' => ['EventBuffer'], 'EventBufferEvent::read' => ['string', 'size'=>'int'], 'EventBufferEvent::readBuffer' => ['bool', 'buf'=>'EventBuffer'], 'EventBufferEvent::setCallbacks' => ['void', 'readcb'=>'callable', 'writecb'=>'callable', 'eventcb'=>'callable', 'arg='=>'string'], 'EventBufferEvent::setPriority' => ['bool', 'priority'=>'int'], 'EventBufferEvent::setTimeouts' => ['bool', 'timeout_read'=>'float', 'timeout_write'=>'float'], 'EventBufferEvent::setWatermark' => ['void', 'events'=>'int', 'lowmark'=>'int', 'highmark'=>'int'], 'EventBufferEvent::sslError' => ['string'], 'EventBufferEvent::sslFilter' => ['EventBufferEvent', 'base'=>'EventBase', 'underlying'=>'EventBufferEvent', 'ctx'=>'EventSslContext', 'state'=>'int', 'options='=>'int'], 'EventBufferEvent::sslGetCipherInfo' => ['string'], 'EventBufferEvent::sslGetCipherName' => ['string'], 'EventBufferEvent::sslGetCipherVersion' => ['string'], 'EventBufferEvent::sslGetProtocol' => ['string'], 'EventBufferEvent::sslRenegotiate' => ['void'], 'EventBufferEvent::sslSocket' => ['EventBufferEvent', 'base'=>'EventBase', 'socket'=>'mixed', 'ctx'=>'EventSslContext', 'state'=>'int', 'options='=>'int'], 'EventBufferEvent::write' => ['bool', 'data'=>'string'], 'EventBufferEvent::writeBuffer' => ['bool', 'buf'=>'EventBuffer'], 'EventConfig::__construct' => ['void'], 'EventConfig::avoidMethod' => ['bool', 'method'=>'string'], 'EventConfig::requireFeatures' => ['bool', 'feature'=>'int'], 'EventConfig::setMaxDispatchInterval' => ['void', 'max_interval'=>'int', 'max_callbacks'=>'int', 'min_priority'=>'int'], 'EventDnsBase::__construct' => ['void', 'base'=>'EventBase', 'initialize'=>'bool'], 'EventDnsBase::addNameserverIp' => ['bool', 'ip'=>'string'], 'EventDnsBase::addSearch' => ['void', 'domain'=>'string'], 'EventDnsBase::clearSearch' => ['void'], 'EventDnsBase::countNameservers' => ['int'], 'EventDnsBase::loadHosts' => ['bool', 'hosts'=>'string'], 'EventDnsBase::parseResolvConf' => ['bool', 'flags'=>'int', 'filename'=>'string'], 'EventDnsBase::setOption' => ['bool', 'option'=>'string', 'value'=>'string'], 'EventDnsBase::setSearchNdots' => ['bool', 'ndots'=>'int'], 'EventHttp::__construct' => ['void', 'base'=>'EventBase', 'ctx='=>'EventSslContext'], 'EventHttp::accept' => ['bool', 'socket'=>'mixed'], 'EventHttp::addServerAlias' => ['bool', 'alias'=>'string'], 'EventHttp::bind' => ['void', 'address'=>'string', 'port'=>'int'], 'EventHttp::removeServerAlias' => ['bool', 'alias'=>'string'], 'EventHttp::setAllowedMethods' => ['void', 'methods'=>'int'], 'EventHttp::setCallback' => ['void', 'path'=>'string', 'cb'=>'string', 'arg='=>'string'], 'EventHttp::setDefaultCallback' => ['void', 'cb'=>'string', 'arg='=>'string'], 'EventHttp::setMaxBodySize' => ['void', 'value'=>'int'], 'EventHttp::setMaxHeadersSize' => ['void', 'value'=>'int'], 'EventHttp::setTimeout' => ['void', 'value'=>'int'], 'EventHttpConnection::__construct' => ['void', 'base'=>'EventBase', 'dns_base'=>'EventDnsBase', 'address'=>'string', 'port'=>'int', 'ctx='=>'EventSslContext'], 'EventHttpConnection::getBase' => ['EventBase'], 'EventHttpConnection::getPeer' => ['void', '&w_address'=>'string', '&w_port'=>'int'], 'EventHttpConnection::makeRequest' => ['bool', 'req'=>'EventHttpRequest', 'type'=>'int', 'uri'=>'string'], 'EventHttpConnection::setCloseCallback' => ['void', 'callback'=>'callable', 'data='=>'mixed'], 'EventHttpConnection::setLocalAddress' => ['void', 'address'=>'string'], 'EventHttpConnection::setLocalPort' => ['void', 'port'=>'int'], 'EventHttpConnection::setMaxBodySize' => ['void', 'max_size'=>'string'], 'EventHttpConnection::setMaxHeadersSize' => ['void', 'max_size'=>'string'], 'EventHttpConnection::setRetries' => ['void', 'retries'=>'int'], 'EventHttpConnection::setTimeout' => ['void', 'timeout'=>'int'], 'EventHttpRequest::__construct' => ['void', 'callback'=>'callable', 'data='=>'mixed'], 'EventHttpRequest::addHeader' => ['bool', 'key'=>'string', 'value'=>'string', 'type'=>'int'], 'EventHttpRequest::cancel' => ['void'], 'EventHttpRequest::clearHeaders' => ['void'], 'EventHttpRequest::closeConnection' => ['void'], 'EventHttpRequest::findHeader' => ['void', 'key'=>'string', 'type'=>'string'], 'EventHttpRequest::free' => ['void'], 'EventHttpRequest::getBufferEvent' => ['EventBufferEvent'], 'EventHttpRequest::getCommand' => ['void'], 'EventHttpRequest::getConnection' => ['EventHttpConnection'], 'EventHttpRequest::getHost' => ['string'], 'EventHttpRequest::getInputBuffer' => ['EventBuffer'], 'EventHttpRequest::getInputHeaders' => ['array'], 'EventHttpRequest::getOutputBuffer' => ['EventBuffer'], 'EventHttpRequest::getOutputHeaders' => ['void'], 'EventHttpRequest::getResponseCode' => ['int'], 'EventHttpRequest::getUri' => ['string'], 'EventHttpRequest::removeHeader' => ['void', 'key'=>'string', 'type'=>'string'], 'EventHttpRequest::sendError' => ['void', 'error'=>'int', 'reason='=>'string'], 'EventHttpRequest::sendReply' => ['void', 'code'=>'int', 'reason'=>'string', 'buf='=>'EventBuffer'], 'EventHttpRequest::sendReplyChunk' => ['void', 'buf'=>'EventBuffer'], 'EventHttpRequest::sendReplyEnd' => ['void'], 'EventHttpRequest::sendReplyStart' => ['void', 'code'=>'int', 'reason'=>'string'], 'EventListener::__construct' => ['void', 'base'=>'EventBase', 'cb'=>'callable', 'data'=>'mixed', 'flags'=>'int', 'backlog'=>'int', 'target'=>'mixed'], 'EventListener::disable' => ['bool'], 'EventListener::enable' => ['bool'], 'EventListener::getBase' => ['void'], 'EventListener::getSocketName' => ['bool', '&w_address'=>'string', '&w_port='=>'mixed'], 'EventListener::setCallback' => ['void', 'cb'=>'callable', 'arg='=>'mixed'], 'EventListener::setErrorCallback' => ['void', 'cb'=>'string'], 'EventSslContext::__construct' => ['void', 'method'=>'string', 'options'=>'string'], 'EventUtil::__construct' => ['void'], 'EventUtil::getLastSocketErrno' => ['int', 'socket='=>'mixed'], 'EventUtil::getLastSocketError' => ['string', 'socket='=>'mixed'], 'EventUtil::getSocketFd' => ['int', 'socket'=>'mixed'], 'EventUtil::getSocketName' => ['bool', 'socket'=>'mixed', '&w_address'=>'string', '&w_port='=>'mixed'], 'EventUtil::setSocketOption' => ['bool', 'socket'=>'mixed', 'level'=>'int', 'optname'=>'int', 'optval'=>'mixed'], 'EventUtil::sslRandPoll' => ['void'], 'EvFork::__construct' => ['void', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvFork::clear' => ['int'], 'EvFork::createStopped' => ['EvFork', 'callback'=>'callable', 'data='=>'string', 'priority='=>'string'], 'EvFork::feed' => ['void', 'events'=>'int'], 'EvFork::getLoop' => ['EvLoop'], 'EvFork::invoke' => ['void', 'events'=>'int'], 'EvFork::keepAlive' => ['void', 'value'=>'bool'], 'EvFork::setCallback' => ['void', 'callback'=>'callable'], 'EvFork::start' => ['void'], 'EvFork::stop' => ['void'], 'EvIdle::__construct' => ['void', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvIdle::clear' => ['int'], 'EvIdle::createStopped' => ['EvIdle', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvIdle::feed' => ['void', 'events'=>'int'], 'EvIdle::getLoop' => ['EvLoop'], 'EvIdle::invoke' => ['void', 'events'=>'int'], 'EvIdle::keepAlive' => ['void', 'value'=>'bool'], 'EvIdle::setCallback' => ['void', 'callback'=>'callable'], 'EvIdle::start' => ['void'], 'EvIdle::stop' => ['void'], 'EvIo::__construct' => ['void', 'fd'=>'mixed', 'events'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvIo::clear' => ['int'], 'EvIo::createStopped' => ['EvIo', 'fd'=>'resource', 'events'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvIo::feed' => ['void', 'events'=>'int'], 'EvIo::getLoop' => ['EvLoop'], 'EvIo::invoke' => ['void', 'events'=>'int'], 'EvIo::keepAlive' => ['void', 'value'=>'bool'], 'EvIo::set' => ['void', 'fd'=>'resource', 'events'=>'int'], 'EvIo::setCallback' => ['void', 'callback'=>'callable'], 'EvIo::start' => ['void'], 'EvIo::stop' => ['void'], 'EvLoop::__construct' => ['void', 'flags='=>'int', 'data='=>'mixed', 'io_interval='=>'float', 'timeout_interval='=>'float'], 'EvLoop::backend' => ['int'], 'EvLoop::check' => ['EvCheck', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::child' => ['EvChild', 'pid'=>'int', 'trace'=>'bool', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::defaultLoop' => ['EvLoop', 'flags='=>'int', 'data='=>'mixed', 'io_interval='=>'float', 'timeout_interval='=>'float'], 'EvLoop::embed' => ['EvEmbed', 'other'=>'EvLoop', 'callback='=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::fork' => ['EvFork', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::idle' => ['EvIdle', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::invokePending' => ['void'], 'EvLoop::io' => ['EvIo', 'fd'=>'resource', 'events'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::loopFork' => ['void'], 'EvLoop::now' => ['float'], 'EvLoop::nowUpdate' => ['void'], 'EvLoop::periodic' => ['EvPeriodic', 'offset'=>'float', 'interval'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::prepare' => ['EvPrepare', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::resume' => ['void'], 'EvLoop::run' => ['void', 'flags='=>'int'], 'EvLoop::signal' => ['EvSignal', 'signum'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::stat' => ['EvStat', 'path'=>'string', 'interval'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::stop' => ['void', 'how='=>'int'], 'EvLoop::suspend' => ['void'], 'EvLoop::timer' => ['EvTimer', 'after'=>'float', 'repeat'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::verify' => ['void'], 'EvPeriodic::__construct' => ['void', 'offset'=>'float', 'interval'=>'string', 'reschedule_cb'=>'callable', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvPeriodic::again' => ['void'], 'EvPeriodic::at' => ['float'], 'EvPeriodic::clear' => ['int'], 'EvPeriodic::createStopped' => ['EvPeriodic', 'offset'=>'float', 'interval'=>'float', 'reschedule_cb'=>'callable', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvPeriodic::feed' => ['void', 'events'=>'int'], 'EvPeriodic::getLoop' => ['EvLoop'], 'EvPeriodic::invoke' => ['void', 'events'=>'int'], 'EvPeriodic::keepAlive' => ['void', 'value'=>'bool'], 'EvPeriodic::set' => ['void', 'offset'=>'float', 'interval'=>'float'], 'EvPeriodic::setCallback' => ['void', 'callback'=>'callable'], 'EvPeriodic::start' => ['void'], 'EvPeriodic::stop' => ['void'], 'EvPrepare::__construct' => ['void', 'callback'=>'string', 'data='=>'string', 'priority='=>'string'], 'EvPrepare::clear' => ['int'], 'EvPrepare::createStopped' => ['EvPrepare', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvPrepare::feed' => ['void', 'events'=>'int'], 'EvPrepare::getLoop' => ['EvLoop'], 'EvPrepare::invoke' => ['void', 'events'=>'int'], 'EvPrepare::keepAlive' => ['void', 'value'=>'bool'], 'EvPrepare::setCallback' => ['void', 'callback'=>'callable'], 'EvPrepare::start' => ['void'], 'EvPrepare::stop' => ['void'], 'EvSignal::__construct' => ['void', 'signum'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvSignal::clear' => ['int'], 'EvSignal::createStopped' => ['EvSignal', 'signum'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvSignal::feed' => ['void', 'events'=>'int'], 'EvSignal::getLoop' => ['EvLoop'], 'EvSignal::invoke' => ['void', 'events'=>'int'], 'EvSignal::keepAlive' => ['void', 'value'=>'bool'], 'EvSignal::set' => ['void', 'signum'=>'int'], 'EvSignal::setCallback' => ['void', 'callback'=>'callable'], 'EvSignal::start' => ['void'], 'EvSignal::stop' => ['void'], 'EvStat::__construct' => ['void', 'path'=>'string', 'interval'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvStat::attr' => ['array'], 'EvStat::clear' => ['int'], 'EvStat::createStopped' => ['EvStat', 'path'=>'string', 'interval'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvStat::feed' => ['void', 'events'=>'int'], 'EvStat::getLoop' => ['EvLoop'], 'EvStat::invoke' => ['void', 'events'=>'int'], 'EvStat::keepAlive' => ['void', 'value'=>'bool'], 'EvStat::prev' => ['array'], 'EvStat::set' => ['void', 'path'=>'string', 'interval'=>'float'], 'EvStat::setCallback' => ['void', 'callback'=>'callable'], 'EvStat::start' => ['void'], 'EvStat::stat' => ['bool'], 'EvStat::stop' => ['void'], 'EvTimer::__construct' => ['void', 'after'=>'float', 'repeat'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvTimer::again' => ['void'], 'EvTimer::clear' => ['int'], 'EvTimer::createStopped' => ['EvTimer', 'after'=>'float', 'repeat'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvTimer::feed' => ['void', 'events'=>'int'], 'EvTimer::getLoop' => ['EvLoop'], 'EvTimer::invoke' => ['void', 'events'=>'int'], 'EvTimer::keepAlive' => ['void', 'value'=>'bool'], 'EvTimer::set' => ['void', 'after'=>'float', 'repeat'=>'float'], 'EvTimer::setCallback' => ['void', 'callback'=>'callable'], 'EvTimer::start' => ['void'], 'EvTimer::stop' => ['void'], 'EvWatcher::__construct' => ['void'], 'EvWatcher::clear' => ['int'], 'EvWatcher::feed' => ['void', 'revents'=>'int'], 'EvWatcher::getLoop' => ['EvLoop'], 'EvWatcher::invoke' => ['void', 'revents'=>'int'], 'EvWatcher::keepalive' => ['bool', 'value='=>'bool'], 'EvWatcher::setCallback' => ['void', 'callback'=>'callable'], 'EvWatcher::start' => ['void'], 'EvWatcher::stop' => ['void'], 'Exception::__clone' => ['void'], 'Exception::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?Exception'], 'Exception::__toString' => ['string'], 'Exception::getCode' => ['int|string'], 'Exception::getFile' => ['string'], 'Exception::getLine' => ['int'], 'Exception::getMessage' => ['string'], 'Exception::getPrevious' => ['?Throwable|?Exception'], 'Exception::getTrace' => ['list>'], 'Exception::getTraceAsString' => ['string'], 'exec' => ['string', 'command'=>'string', '&w_output='=>'array', '&w_return_value='=>'int'], 'exif_imagetype' => ['int|false', 'imagefile'=>'string'], 'exif_read_data' => ['array|false', 'filename'=>'string|resource', 'sections_needed='=>'string', 'sub_arrays='=>'bool', 'read_thumbnail='=>'bool'], 'exif_tagname' => ['string|false', 'index'=>'int'], 'exif_thumbnail' => ['string|false', 'filename'=>'string', '&w_width='=>'int', '&w_height='=>'int', '&w_imagetype='=>'int'], 'exit' => ['', 'status'=>'string|int'], 'exp' => ['float', 'number'=>'float'], 'expect_expectl' => ['int', 'expect'=>'resource', 'cases'=>'array', 'match='=>'array'], 'expect_popen' => ['resource|false', 'command'=>'string'], 'explode' => ['list|false', 'separator'=>'string', 'str'=>'string', 'limit='=>'int'], 'expm1' => ['float', 'number'=>'float'], 'extension_loaded' => ['bool', 'extension_name'=>'string'], 'extract' => ['int', '&rw_var_array'=>'array', 'extract_type='=>'int', 'prefix='=>'?string'], 'ezmlm_hash' => ['int', 'addr'=>'string'], 'fam_cancel_monitor' => ['bool', 'fam'=>'resource', 'fam_monitor'=>'resource'], 'fam_close' => ['void', 'fam'=>'resource'], 'fam_monitor_collection' => ['resource', 'fam'=>'resource', 'dirname'=>'string', 'depth'=>'int', 'mask'=>'string'], 'fam_monitor_directory' => ['resource', 'fam'=>'resource', 'dirname'=>'string'], 'fam_monitor_file' => ['resource', 'fam'=>'resource', 'filename'=>'string'], 'fam_next_event' => ['array', 'fam'=>'resource'], 'fam_open' => ['resource|false', 'appname='=>'string'], 'fam_pending' => ['int', 'fam'=>'resource'], 'fam_resume_monitor' => ['bool', 'fam'=>'resource', 'fam_monitor'=>'resource'], 'fam_suspend_monitor' => ['bool', 'fam'=>'resource', 'fam_monitor'=>'resource'], 'fann_cascadetrain_on_data' => ['bool', 'ann'=>'resource', 'data'=>'resource', 'max_neurons'=>'int', 'neurons_between_reports'=>'int', 'desired_error'=>'float'], 'fann_cascadetrain_on_file' => ['bool', 'ann'=>'resource', 'filename'=>'string', 'max_neurons'=>'int', 'neurons_between_reports'=>'int', 'desired_error'=>'float'], 'fann_clear_scaling_params' => ['bool', 'ann'=>'resource'], 'fann_copy' => ['resource|false', 'ann'=>'resource'], 'fann_create_from_file' => ['resource', 'configuration_file'=>'string'], 'fann_create_shortcut' => ['resource|false', 'num_layers'=>'int', 'num_neurons1'=>'int', 'num_neurons2'=>'int', '...args='=>'int'], 'fann_create_shortcut_array' => ['resource|false', 'num_layers'=>'int', 'layers'=>'array'], 'fann_create_sparse' => ['resource|false', 'connection_rate'=>'float', 'num_layers'=>'int', 'num_neurons1'=>'int', 'num_neurons2'=>'int', '...args='=>'int'], 'fann_create_sparse_array' => ['resource|false', 'connection_rate'=>'float', 'num_layers'=>'int', 'layers'=>'array'], 'fann_create_standard' => ['resource|false', 'num_layers'=>'int', 'num_neurons1'=>'int', 'num_neurons2'=>'int', '...args='=>'int'], 'fann_create_standard_array' => ['resource|false', 'num_layers'=>'int', 'layers'=>'array'], 'fann_create_train' => ['resource', 'num_data'=>'int', 'num_input'=>'int', 'num_output'=>'int'], 'fann_create_train_from_callback' => ['resource', 'num_data'=>'int', 'num_input'=>'int', 'num_output'=>'int', 'user_function'=>'callable'], 'fann_descale_input' => ['bool', 'ann'=>'resource', 'input_vector'=>'array'], 'fann_descale_output' => ['bool', 'ann'=>'resource', 'output_vector'=>'array'], 'fann_descale_train' => ['bool', 'ann'=>'resource', 'train_data'=>'resource'], 'fann_destroy' => ['bool', 'ann'=>'resource'], 'fann_destroy_train' => ['bool', 'train_data'=>'resource'], 'fann_duplicate_train_data' => ['resource', 'data'=>'resource'], 'fann_get_activation_function' => ['int|false', 'ann'=>'resource', 'layer'=>'int', 'neuron'=>'int'], 'fann_get_activation_steepness' => ['float|false', 'ann'=>'resource', 'layer'=>'int', 'neuron'=>'int'], 'fann_get_bias_array' => ['array', 'ann'=>'resource'], 'fann_get_bit_fail' => ['int|false', 'ann'=>'resource'], 'fann_get_bit_fail_limit' => ['float|false', 'ann'=>'resource'], 'fann_get_cascade_activation_functions' => ['array|false', 'ann'=>'resource'], 'fann_get_cascade_activation_functions_count' => ['int|false', 'ann'=>'resource'], 'fann_get_cascade_activation_steepnesses' => ['array|false', 'ann'=>'resource'], 'fann_get_cascade_activation_steepnesses_count' => ['int|false', 'ann'=>'resource'], 'fann_get_cascade_candidate_change_fraction' => ['float|false', 'ann'=>'resource'], 'fann_get_cascade_candidate_limit' => ['float|false', 'ann'=>'resource'], 'fann_get_cascade_candidate_stagnation_epochs' => ['float|false', 'ann'=>'resource'], 'fann_get_cascade_max_cand_epochs' => ['int|false', 'ann'=>'resource'], 'fann_get_cascade_max_out_epochs' => ['int|false', 'ann'=>'resource'], 'fann_get_cascade_min_cand_epochs' => ['int|false', 'ann'=>'resource'], 'fann_get_cascade_min_out_epochs' => ['int|false', 'ann'=>'resource'], 'fann_get_cascade_num_candidate_groups' => ['int|false', 'ann'=>'resource'], 'fann_get_cascade_num_candidates' => ['int|false', 'ann'=>'resource'], 'fann_get_cascade_output_change_fraction' => ['float|false', 'ann'=>'resource'], 'fann_get_cascade_output_stagnation_epochs' => ['int|false', 'ann'=>'resource'], 'fann_get_cascade_weight_multiplier' => ['float|false', 'ann'=>'resource'], 'fann_get_connection_array' => ['array', 'ann'=>'resource'], 'fann_get_connection_rate' => ['float|false', 'ann'=>'resource'], 'fann_get_errno' => ['int|false', 'errdat'=>'resource'], 'fann_get_errstr' => ['string|false', 'errdat'=>'resource'], 'fann_get_layer_array' => ['array', 'ann'=>'resource'], 'fann_get_learning_momentum' => ['float|false', 'ann'=>'resource'], 'fann_get_learning_rate' => ['float|false', 'ann'=>'resource'], 'fann_get_MSE' => ['float|false', 'ann'=>'resource'], 'fann_get_network_type' => ['int|false', 'ann'=>'resource'], 'fann_get_num_input' => ['int|false', 'ann'=>'resource'], 'fann_get_num_layers' => ['int|false', 'ann'=>'resource'], 'fann_get_num_output' => ['int|false', 'ann'=>'resource'], 'fann_get_quickprop_decay' => ['float|false', 'ann'=>'resource'], 'fann_get_quickprop_mu' => ['float|false', 'ann'=>'resource'], 'fann_get_rprop_decrease_factor' => ['float|false', 'ann'=>'resource'], 'fann_get_rprop_delta_max' => ['float|false', 'ann'=>'resource'], 'fann_get_rprop_delta_min' => ['float|false', 'ann'=>'resource'], 'fann_get_rprop_delta_zero' => ['float|false', 'ann'=>'resource'], 'fann_get_rprop_increase_factor' => ['float|false', 'ann'=>'resource'], 'fann_get_sarprop_step_error_shift' => ['float|false', 'ann'=>'resource'], 'fann_get_sarprop_step_error_threshold_factor' => ['float|false', 'ann'=>'resource'], 'fann_get_sarprop_temperature' => ['float|false', 'ann'=>'resource'], 'fann_get_sarprop_weight_decay_shift' => ['float|false', 'ann'=>'resource'], 'fann_get_total_connections' => ['int|false', 'ann'=>'resource'], 'fann_get_total_neurons' => ['int|false', 'ann'=>'resource'], 'fann_get_train_error_function' => ['int|false', 'ann'=>'resource'], 'fann_get_train_stop_function' => ['int|false', 'ann'=>'resource'], 'fann_get_training_algorithm' => ['int|false', 'ann'=>'resource'], 'fann_init_weights' => ['bool', 'ann'=>'resource', 'train_data'=>'resource'], 'fann_length_train_data' => ['int|false', 'data'=>'resource'], 'fann_merge_train_data' => ['resource|false', 'data1'=>'resource', 'data2'=>'resource'], 'fann_num_input_train_data' => ['int|false', 'data'=>'resource'], 'fann_num_output_train_data' => ['int|false', 'data'=>'resource'], 'fann_print_error' => ['void', 'errdat'=>'string'], 'fann_randomize_weights' => ['bool', 'ann'=>'resource', 'min_weight'=>'float', 'max_weight'=>'float'], 'fann_read_train_from_file' => ['resource', 'filename'=>'string'], 'fann_reset_errno' => ['void', 'errdat'=>'resource'], 'fann_reset_errstr' => ['void', 'errdat'=>'resource'], 'fann_reset_MSE' => ['bool', 'ann'=>'string'], 'fann_run' => ['array|false', 'ann'=>'resource', 'input'=>'array'], 'fann_save' => ['bool', 'ann'=>'resource', 'configuration_file'=>'string'], 'fann_save_train' => ['bool', 'data'=>'resource', 'file_name'=>'string'], 'fann_scale_input' => ['bool', 'ann'=>'resource', 'input_vector'=>'array'], 'fann_scale_input_train_data' => ['bool', 'train_data'=>'resource', 'new_min'=>'float', 'new_max'=>'float'], 'fann_scale_output' => ['bool', 'ann'=>'resource', 'output_vector'=>'array'], 'fann_scale_output_train_data' => ['bool', 'train_data'=>'resource', 'new_min'=>'float', 'new_max'=>'float'], 'fann_scale_train' => ['bool', 'ann'=>'resource', 'train_data'=>'resource'], 'fann_scale_train_data' => ['bool', 'train_data'=>'resource', 'new_min'=>'float', 'new_max'=>'float'], 'fann_set_activation_function' => ['bool', 'ann'=>'resource', 'activation_function'=>'int', 'layer'=>'int', 'neuron'=>'int'], 'fann_set_activation_function_hidden' => ['bool', 'ann'=>'resource', 'activation_function'=>'int'], 'fann_set_activation_function_layer' => ['bool', 'ann'=>'resource', 'activation_function'=>'int', 'layer'=>'int'], 'fann_set_activation_function_output' => ['bool', 'ann'=>'resource', 'activation_function'=>'int'], 'fann_set_activation_steepness' => ['bool', 'ann'=>'resource', 'activation_steepness'=>'float', 'layer'=>'int', 'neuron'=>'int'], 'fann_set_activation_steepness_hidden' => ['bool', 'ann'=>'resource', 'activation_steepness'=>'float'], 'fann_set_activation_steepness_layer' => ['bool', 'ann'=>'resource', 'activation_steepness'=>'float', 'layer'=>'int'], 'fann_set_activation_steepness_output' => ['bool', 'ann'=>'resource', 'activation_steepness'=>'float'], 'fann_set_bit_fail_limit' => ['bool', 'ann'=>'resource', 'bit_fail_limit'=>'float'], 'fann_set_callback' => ['bool', 'ann'=>'resource', 'callback'=>'callable'], 'fann_set_cascade_activation_functions' => ['bool', 'ann'=>'resource', 'cascade_activation_functions'=>'array'], 'fann_set_cascade_activation_steepnesses' => ['bool', 'ann'=>'resource', 'cascade_activation_steepnesses_count'=>'array'], 'fann_set_cascade_candidate_change_fraction' => ['bool', 'ann'=>'resource', 'cascade_candidate_change_fraction'=>'float'], 'fann_set_cascade_candidate_limit' => ['bool', 'ann'=>'resource', 'cascade_candidate_limit'=>'float'], 'fann_set_cascade_candidate_stagnation_epochs' => ['bool', 'ann'=>'resource', 'cascade_candidate_stagnation_epochs'=>'int'], 'fann_set_cascade_max_cand_epochs' => ['bool', 'ann'=>'resource', 'cascade_max_cand_epochs'=>'int'], 'fann_set_cascade_max_out_epochs' => ['bool', 'ann'=>'resource', 'cascade_max_out_epochs'=>'int'], 'fann_set_cascade_min_cand_epochs' => ['bool', 'ann'=>'resource', 'cascade_min_cand_epochs'=>'int'], 'fann_set_cascade_min_out_epochs' => ['bool', 'ann'=>'resource', 'cascade_min_out_epochs'=>'int'], 'fann_set_cascade_num_candidate_groups' => ['bool', 'ann'=>'resource', 'cascade_num_candidate_groups'=>'int'], 'fann_set_cascade_output_change_fraction' => ['bool', 'ann'=>'resource', 'cascade_output_change_fraction'=>'float'], 'fann_set_cascade_output_stagnation_epochs' => ['bool', 'ann'=>'resource', 'cascade_output_stagnation_epochs'=>'int'], 'fann_set_cascade_weight_multiplier' => ['bool', 'ann'=>'resource', 'cascade_weight_multiplier'=>'float'], 'fann_set_error_log' => ['void', 'errdat'=>'resource', 'log_file'=>'string'], 'fann_set_input_scaling_params' => ['bool', 'ann'=>'resource', 'train_data'=>'resource', 'new_input_min'=>'float', 'new_input_max'=>'float'], 'fann_set_learning_momentum' => ['bool', 'ann'=>'resource', 'learning_momentum'=>'float'], 'fann_set_learning_rate' => ['bool', 'ann'=>'resource', 'learning_rate'=>'float'], 'fann_set_output_scaling_params' => ['bool', 'ann'=>'resource', 'train_data'=>'resource', 'new_output_min'=>'float', 'new_output_max'=>'float'], 'fann_set_quickprop_decay' => ['bool', 'ann'=>'resource', 'quickprop_decay'=>'float'], 'fann_set_quickprop_mu' => ['bool', 'ann'=>'resource', 'quickprop_mu'=>'float'], 'fann_set_rprop_decrease_factor' => ['bool', 'ann'=>'resource', 'rprop_decrease_factor'=>'float'], 'fann_set_rprop_delta_max' => ['bool', 'ann'=>'resource', 'rprop_delta_max'=>'float'], 'fann_set_rprop_delta_min' => ['bool', 'ann'=>'resource', 'rprop_delta_min'=>'float'], 'fann_set_rprop_delta_zero' => ['bool', 'ann'=>'resource', 'rprop_delta_zero'=>'float'], 'fann_set_rprop_increase_factor' => ['bool', 'ann'=>'resource', 'rprop_increase_factor'=>'float'], 'fann_set_sarprop_step_error_shift' => ['bool', 'ann'=>'resource', 'sarprop_step_error_shift'=>'float'], 'fann_set_sarprop_step_error_threshold_factor' => ['bool', 'ann'=>'resource', 'sarprop_step_error_threshold_factor'=>'float'], 'fann_set_sarprop_temperature' => ['bool', 'ann'=>'resource', 'sarprop_temperature'=>'float'], 'fann_set_sarprop_weight_decay_shift' => ['bool', 'ann'=>'resource', 'sarprop_weight_decay_shift'=>'float'], 'fann_set_scaling_params' => ['bool', 'ann'=>'resource', 'train_data'=>'resource', 'new_input_min'=>'float', 'new_input_max'=>'float', 'new_output_min'=>'float', 'new_output_max'=>'float'], 'fann_set_train_error_function' => ['bool', 'ann'=>'resource', 'error_function'=>'int'], 'fann_set_train_stop_function' => ['bool', 'ann'=>'resource', 'stop_function'=>'int'], 'fann_set_training_algorithm' => ['bool', 'ann'=>'resource', 'training_algorithm'=>'int'], 'fann_set_weight' => ['bool', 'ann'=>'resource', 'from_neuron'=>'int', 'to_neuron'=>'int', 'weight'=>'float'], 'fann_set_weight_array' => ['bool', 'ann'=>'resource', 'connections'=>'array'], 'fann_shuffle_train_data' => ['bool', 'train_data'=>'resource'], 'fann_subset_train_data' => ['resource', 'data'=>'resource', 'pos'=>'int', 'length'=>'int'], 'fann_test' => ['bool', 'ann'=>'resource', 'input'=>'array', 'desired_output'=>'array'], 'fann_test_data' => ['float|false', 'ann'=>'resource', 'data'=>'resource'], 'fann_train' => ['bool', 'ann'=>'resource', 'input'=>'array', 'desired_output'=>'array'], 'fann_train_epoch' => ['float|false', 'ann'=>'resource', 'data'=>'resource'], 'fann_train_on_data' => ['bool', 'ann'=>'resource', 'data'=>'resource', 'max_epochs'=>'int', 'epochs_between_reports'=>'int', 'desired_error'=>'float'], 'fann_train_on_file' => ['bool', 'ann'=>'resource', 'filename'=>'string', 'max_epochs'=>'int', 'epochs_between_reports'=>'int', 'desired_error'=>'float'], 'FANNConnection::__construct' => ['void', 'from_neuron'=>'int', 'to_neuron'=>'int', 'weight'=>'float'], 'FANNConnection::getFromNeuron' => ['int'], 'FANNConnection::getToNeuron' => ['int'], 'FANNConnection::getWeight' => ['void'], 'FANNConnection::setWeight' => ['bool', 'weight'=>'float'], 'fastcgi_finish_request' => ['bool'], 'fbsql_affected_rows' => ['int', 'link_identifier='=>'?resource'], 'fbsql_autocommit' => ['bool', 'link_identifier'=>'resource', 'onoff='=>'bool'], 'fbsql_blob_size' => ['int', 'blob_handle'=>'string', 'link_identifier='=>'?resource'], 'fbsql_change_user' => ['bool', 'user'=>'string', 'password'=>'string', 'database='=>'string', 'link_identifier='=>'?resource'], 'fbsql_clob_size' => ['int', 'clob_handle'=>'string', 'link_identifier='=>'?resource'], 'fbsql_close' => ['bool', 'link_identifier='=>'?resource'], 'fbsql_commit' => ['bool', 'link_identifier='=>'?resource'], 'fbsql_connect' => ['resource', 'hostname='=>'string', 'username='=>'string', 'password='=>'string'], 'fbsql_create_blob' => ['string', 'blob_data'=>'string', 'link_identifier='=>'?resource'], 'fbsql_create_clob' => ['string', 'clob_data'=>'string', 'link_identifier='=>'?resource'], 'fbsql_create_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource', 'database_options='=>'string'], 'fbsql_data_seek' => ['bool', 'result'=>'resource', 'row_number'=>'int'], 'fbsql_database' => ['string', 'link_identifier'=>'resource', 'database='=>'string'], 'fbsql_database_password' => ['string', 'link_identifier'=>'resource', 'database_password='=>'string'], 'fbsql_db_query' => ['resource', 'database'=>'string', 'query'=>'string', 'link_identifier='=>'?resource'], 'fbsql_db_status' => ['int', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'fbsql_drop_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'fbsql_errno' => ['int', 'link_identifier='=>'?resource'], 'fbsql_error' => ['string', 'link_identifier='=>'?resource'], 'fbsql_fetch_array' => ['array', 'result'=>'resource', 'result_type='=>'int'], 'fbsql_fetch_assoc' => ['array', 'result'=>'resource'], 'fbsql_fetch_field' => ['object', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_fetch_lengths' => ['array', 'result'=>'resource'], 'fbsql_fetch_object' => ['object', 'result'=>'resource'], 'fbsql_fetch_row' => ['array', 'result'=>'resource'], 'fbsql_field_flags' => ['string', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_field_len' => ['int', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_field_name' => ['string', 'result'=>'resource', 'field_index='=>'int'], 'fbsql_field_seek' => ['bool', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_field_table' => ['string', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_field_type' => ['string', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_free_result' => ['bool', 'result'=>'resource'], 'fbsql_get_autostart_info' => ['array', 'link_identifier='=>'?resource'], 'fbsql_hostname' => ['string', 'link_identifier'=>'resource', 'host_name='=>'string'], 'fbsql_insert_id' => ['int', 'link_identifier='=>'?resource'], 'fbsql_list_dbs' => ['resource', 'link_identifier='=>'?resource'], 'fbsql_list_fields' => ['resource', 'database_name'=>'string', 'table_name'=>'string', 'link_identifier='=>'?resource'], 'fbsql_list_tables' => ['resource', 'database'=>'string', 'link_identifier='=>'?resource'], 'fbsql_next_result' => ['bool', 'result'=>'resource'], 'fbsql_num_fields' => ['int', 'result'=>'resource'], 'fbsql_num_rows' => ['int', 'result'=>'resource'], 'fbsql_password' => ['string', 'link_identifier'=>'resource', 'password='=>'string'], 'fbsql_pconnect' => ['resource', 'hostname='=>'string', 'username='=>'string', 'password='=>'string'], 'fbsql_query' => ['resource', 'query'=>'string', 'link_identifier='=>'?resource', 'batch_size='=>'int'], 'fbsql_read_blob' => ['string', 'blob_handle'=>'string', 'link_identifier='=>'?resource'], 'fbsql_read_clob' => ['string', 'clob_handle'=>'string', 'link_identifier='=>'?resource'], 'fbsql_result' => ['mixed', 'result'=>'resource', 'row='=>'int', 'field='=>'mixed'], 'fbsql_rollback' => ['bool', 'link_identifier='=>'?resource'], 'fbsql_rows_fetched' => ['int', 'result'=>'resource'], 'fbsql_select_db' => ['bool', 'database_name='=>'string', 'link_identifier='=>'?resource'], 'fbsql_set_characterset' => ['void', 'link_identifier'=>'resource', 'characterset'=>'int', 'in_out_both='=>'int'], 'fbsql_set_lob_mode' => ['bool', 'result'=>'resource', 'lob_mode'=>'int'], 'fbsql_set_password' => ['bool', 'link_identifier'=>'resource', 'user'=>'string', 'password'=>'string', 'old_password'=>'string'], 'fbsql_set_transaction' => ['void', 'link_identifier'=>'resource', 'locking'=>'int', 'isolation'=>'int'], 'fbsql_start_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource', 'database_options='=>'string'], 'fbsql_stop_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'fbsql_table_name' => ['string', 'result'=>'resource', 'index'=>'int'], 'fbsql_username' => ['string', 'link_identifier'=>'resource', 'username='=>'string'], 'fbsql_warnings' => ['bool', 'onoff='=>'bool'], 'fclose' => ['bool', 'fp'=>'resource'], 'fdf_add_doc_javascript' => ['bool', 'fdf_document'=>'resource', 'script_name'=>'string', 'script_code'=>'string'], 'fdf_add_template' => ['bool', 'fdf_document'=>'resource', 'newpage'=>'int', 'filename'=>'string', 'template'=>'string', 'rename'=>'int'], 'fdf_close' => ['void', 'fdf_document'=>'resource'], 'fdf_create' => ['resource'], 'fdf_enum_values' => ['bool', 'fdf_document'=>'resource', 'function'=>'callable', 'userdata='=>'mixed'], 'fdf_errno' => ['int'], 'fdf_error' => ['string', 'error_code='=>'int'], 'fdf_get_ap' => ['bool', 'fdf_document'=>'resource', 'field'=>'string', 'face'=>'int', 'filename'=>'string'], 'fdf_get_attachment' => ['array', 'fdf_document'=>'resource', 'fieldname'=>'string', 'savepath'=>'string'], 'fdf_get_encoding' => ['string', 'fdf_document'=>'resource'], 'fdf_get_file' => ['string', 'fdf_document'=>'resource'], 'fdf_get_flags' => ['int', 'fdf_document'=>'resource', 'fieldname'=>'string', 'whichflags'=>'int'], 'fdf_get_opt' => ['mixed', 'fdf_document'=>'resource', 'fieldname'=>'string', 'element='=>'int'], 'fdf_get_status' => ['string', 'fdf_document'=>'resource'], 'fdf_get_value' => ['mixed', 'fdf_document'=>'resource', 'fieldname'=>'string', 'which='=>'int'], 'fdf_get_version' => ['string', 'fdf_document='=>'resource'], 'fdf_header' => ['void'], 'fdf_next_field_name' => ['string', 'fdf_document'=>'resource', 'fieldname='=>'string'], 'fdf_open' => ['resource|false', 'filename'=>'string'], 'fdf_open_string' => ['resource', 'fdf_data'=>'string'], 'fdf_remove_item' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'item'=>'int'], 'fdf_save' => ['bool', 'fdf_document'=>'resource', 'filename='=>'string'], 'fdf_save_string' => ['string', 'fdf_document'=>'resource'], 'fdf_set_ap' => ['bool', 'fdf_document'=>'resource', 'field_name'=>'string', 'face'=>'int', 'filename'=>'string', 'page_number'=>'int'], 'fdf_set_encoding' => ['bool', 'fdf_document'=>'resource', 'encoding'=>'string'], 'fdf_set_file' => ['bool', 'fdf_document'=>'resource', 'url'=>'string', 'target_frame='=>'string'], 'fdf_set_flags' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'whichflags'=>'int', 'newflags'=>'int'], 'fdf_set_javascript_action' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'trigger'=>'int', 'script'=>'string'], 'fdf_set_on_import_javascript' => ['bool', 'fdf_document'=>'resource', 'script'=>'string', 'before_data_import'=>'bool'], 'fdf_set_opt' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'element'=>'int', 'string1'=>'string', 'string2'=>'string'], 'fdf_set_status' => ['bool', 'fdf_document'=>'resource', 'status'=>'string'], 'fdf_set_submit_form_action' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'trigger'=>'int', 'script'=>'string', 'flags'=>'int'], 'fdf_set_target_frame' => ['bool', 'fdf_document'=>'resource', 'frame_name'=>'string'], 'fdf_set_value' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'value'=>'mixed', 'isname='=>'int'], 'fdf_set_version' => ['bool', 'fdf_document'=>'resource', 'version'=>'string'], 'feof' => ['bool', 'fp'=>'resource'], 'fflush' => ['bool', 'fp'=>'resource'], 'ffmpeg_animated_gif::__construct' => ['void', 'output_file_path'=>'string', 'width'=>'int', 'height'=>'int', 'frame_rate'=>'int', 'loop_count='=>'int'], 'ffmpeg_animated_gif::addFrame' => ['', 'frame_to_add'=>'ffmpeg_frame'], 'ffmpeg_frame::__construct' => ['void', 'gd_image'=>'resource'], 'ffmpeg_frame::crop' => ['', 'crop_top'=>'int', 'crop_bottom='=>'int', 'crop_left='=>'int', 'crop_right='=>'int'], 'ffmpeg_frame::getHeight' => ['int'], 'ffmpeg_frame::getPresentationTimestamp' => ['int'], 'ffmpeg_frame::getPTS' => ['int'], 'ffmpeg_frame::getWidth' => ['int'], 'ffmpeg_frame::resize' => ['', 'width'=>'int', 'height'=>'int', 'crop_top='=>'int', 'crop_bottom='=>'int', 'crop_left='=>'int', 'crop_right='=>'int'], 'ffmpeg_frame::toGDImage' => ['resource'], 'ffmpeg_movie::__construct' => ['void', 'path_to_media'=>'string', 'persistent'=>'bool'], 'ffmpeg_movie::getArtist' => ['string'], 'ffmpeg_movie::getAudioBitRate' => ['int'], 'ffmpeg_movie::getAudioChannels' => ['int'], 'ffmpeg_movie::getAudioCodec' => ['string'], 'ffmpeg_movie::getAudioSampleRate' => ['int'], 'ffmpeg_movie::getAuthor' => ['string'], 'ffmpeg_movie::getBitRate' => ['int'], 'ffmpeg_movie::getComment' => ['string'], 'ffmpeg_movie::getCopyright' => ['string'], 'ffmpeg_movie::getDuration' => ['int'], 'ffmpeg_movie::getFilename' => ['string'], 'ffmpeg_movie::getFrame' => ['ffmpeg_frame|false', 'framenumber'=>'int'], 'ffmpeg_movie::getFrameCount' => ['int'], 'ffmpeg_movie::getFrameHeight' => ['int'], 'ffmpeg_movie::getFrameNumber' => ['int'], 'ffmpeg_movie::getFrameRate' => ['int'], 'ffmpeg_movie::getFrameWidth' => ['int'], 'ffmpeg_movie::getGenre' => ['string'], 'ffmpeg_movie::getNextKeyFrame' => ['ffmpeg_frame|false'], 'ffmpeg_movie::getPixelFormat' => [''], 'ffmpeg_movie::getTitle' => ['string'], 'ffmpeg_movie::getTrackNumber' => ['int|string'], 'ffmpeg_movie::getVideoBitRate' => ['int'], 'ffmpeg_movie::getVideoCodec' => ['string'], 'ffmpeg_movie::getYear' => ['int|string'], 'ffmpeg_movie::hasAudio' => ['bool'], 'ffmpeg_movie::hasVideo' => ['bool'], 'fgetc' => ['string|false', 'fp'=>'resource'], 'fgetcsv' => ['list|array{0: null}|false|null', 'fp'=>'resource', 'length='=>'int', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'fgets' => ['string|false', 'fp'=>'resource', 'length='=>'int'], 'fgetss' => ['string|false', 'fp'=>'resource', 'length='=>'int', 'allowable_tags='=>'string'], 'file' => ['list|false', 'filename'=>'string', 'flags='=>'int', 'context='=>'resource'], 'file_exists' => ['bool', 'filename'=>'string'], 'file_get_contents' => ['string|false', 'filename'=>'string', 'use_include_path='=>'bool', 'context='=>'?resource', 'offset='=>'int', 'maxlen='=>'int'], 'file_put_contents' => ['int|false', 'file'=>'string', 'data'=>'mixed', 'flags='=>'int', 'context='=>'resource'], 'fileatime' => ['int|false', 'filename'=>'string'], 'filectime' => ['int|false', 'filename'=>'string'], 'filegroup' => ['int|false', 'filename'=>'string'], 'fileinode' => ['int|false', 'filename'=>'string'], 'filemtime' => ['int|false', 'filename'=>'string'], 'fileowner' => ['int|false', 'filename'=>'string'], 'fileperms' => ['int|false', 'filename'=>'string'], 'filepro' => ['bool', 'directory'=>'string'], 'filepro_fieldcount' => ['int'], 'filepro_fieldname' => ['string', 'field_number'=>'int'], 'filepro_fieldtype' => ['string', 'field_number'=>'int'], 'filepro_fieldwidth' => ['int', 'field_number'=>'int'], 'filepro_retrieve' => ['string', 'row_number'=>'int', 'field_number'=>'int'], 'filepro_rowcount' => ['int'], 'filesize' => ['int|false', 'filename'=>'string'], 'FilesystemIterator::__construct' => ['void', 'path'=>'string', 'flags='=>'int'], 'FilesystemIterator::__toString' => ['string'], 'FilesystemIterator::_bad_state_ex' => [''], 'FilesystemIterator::current' => ['mixed'], 'FilesystemIterator::getATime' => ['int'], 'FilesystemIterator::getBasename' => ['string', 'suffix='=>'string'], 'FilesystemIterator::getCTime' => ['int'], 'FilesystemIterator::getExtension' => ['string'], 'FilesystemIterator::getFileInfo' => ['SplFileInfo', 'class_name='=>'string'], 'FilesystemIterator::getFilename' => ['string'], 'FilesystemIterator::getFlags' => ['int'], 'FilesystemIterator::getGroup' => ['int'], 'FilesystemIterator::getInode' => ['int'], 'FilesystemIterator::getLinkTarget' => ['string'], 'FilesystemIterator::getMTime' => ['int'], 'FilesystemIterator::getOwner' => ['int'], 'FilesystemIterator::getPath' => ['string'], 'FilesystemIterator::getPathInfo' => ['SplFileInfo', 'class_name='=>'string'], 'FilesystemIterator::getPathname' => ['string'], 'FilesystemIterator::getPerms' => ['int'], 'FilesystemIterator::getRealPath' => ['string'], 'FilesystemIterator::getSize' => ['int'], 'FilesystemIterator::getType' => ['string'], 'FilesystemIterator::isDir' => ['bool'], 'FilesystemIterator::isDot' => ['bool'], 'FilesystemIterator::isExecutable' => ['bool'], 'FilesystemIterator::isFile' => ['bool'], 'FilesystemIterator::isLink' => ['bool'], 'FilesystemIterator::isReadable' => ['bool'], 'FilesystemIterator::isWritable' => ['bool'], 'FilesystemIterator::key' => ['string'], 'FilesystemIterator::next' => ['void'], 'FilesystemIterator::openFile' => ['SplFileObject', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'FilesystemIterator::rewind' => ['void'], 'FilesystemIterator::seek' => ['void', 'position'=>'int'], 'FilesystemIterator::setFileClass' => ['void', 'class_name='=>'string'], 'FilesystemIterator::setFlags' => ['void', 'flags='=>'int'], 'FilesystemIterator::setInfoClass' => ['void', 'class_name='=>'string'], 'FilesystemIterator::valid' => ['bool'], 'filetype' => ['string|false', 'filename'=>'string'], 'filter_has_var' => ['bool', 'type'=>'int', 'variable_name'=>'string'], 'filter_id' => ['int|false', 'filtername'=>'string'], 'filter_input' => ['mixed|false', 'type'=>'int', 'variable_name'=>'string', 'filter='=>'int', 'options='=>'array|int'], 'filter_input_array' => ['mixed|false', 'type'=>'int', 'definition='=>'int|array', 'add_empty='=>'bool'], 'filter_list' => ['array'], 'filter_var' => ['mixed|false', 'variable'=>'mixed', 'filter='=>'int', 'options='=>'mixed'], 'filter_var_array' => ['mixed|false', 'data'=>'array', 'definition='=>'mixed', 'add_empty='=>'bool'], 'FilterIterator::__construct' => ['void', 'iterator'=>'Iterator'], 'FilterIterator::accept' => ['bool'], 'FilterIterator::current' => ['mixed'], 'FilterIterator::getInnerIterator' => ['Iterator'], 'FilterIterator::key' => ['mixed'], 'FilterIterator::next' => ['void'], 'FilterIterator::rewind' => ['void'], 'FilterIterator::valid' => ['bool'], 'finfo::__construct' => ['void', 'options='=>'int', 'magic_file='=>'string'], 'finfo::buffer' => ['string|false', 'string'=>'string', 'options='=>'int', 'context='=>'resource'], 'finfo::file' => ['string|false', 'file_name'=>'string', 'options='=>'int', 'context='=>'resource'], 'finfo::finfo' => ['void', 'options='=>'int', 'magic_file='=>'string'], 'finfo::set_flags' => ['bool', 'options'=>'int'], 'finfo_buffer' => ['string|false', 'finfo'=>'resource', 'string'=>'string', 'options='=>'int', 'context='=>'resource'], 'finfo_close' => ['bool', 'finfo'=>'resource'], 'finfo_file' => ['string|false', 'finfo'=>'resource', 'file_name'=>'string', 'options='=>'int', 'context='=>'resource'], 'finfo_open' => ['resource|false', 'options='=>'int', 'arg='=>'string'], 'finfo_set_flags' => ['bool', 'finfo'=>'resource', 'options'=>'int'], 'floatval' => ['float', 'value'=>'mixed'], 'flock' => ['bool', 'fp'=>'resource', 'operation'=>'int', '&w_wouldblock='=>'int'], 'floor' => ['float', 'number'=>'float'], 'flush' => ['void'], 'fmod' => ['float', 'x'=>'float', 'y'=>'float'], 'fnmatch' => ['bool', 'pattern'=>'string', 'filename'=>'string', 'flags='=>'int'], 'fopen' => ['resource|false', 'filename'=>'string', 'mode'=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'forward_static_call' => ['mixed|false', 'function'=>'callable', '...parameters='=>'mixed'], 'forward_static_call_array' => ['mixed|false', 'function'=>'callable', 'parameters'=>'list'], 'fpassthru' => ['int|false', 'fp'=>'resource'], 'fpm_get_status' => ['array|false'], 'fprintf' => ['int', 'stream'=>'resource', 'format'=>'string', '...args='=>'string|int|float'], 'fputcsv' => ['int|false', 'fp'=>'resource', 'fields'=>'array', 'delimiter='=>'string', 'enclosure='=>'string', 'escape_char='=>'string'], 'fputs' => ['int|false', 'fp'=>'resource', 'string'=>'string', 'length='=>'int'], 'fread' => ['string|false', 'fp'=>'resource', 'length'=>'int'], 'frenchtojd' => ['int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'fribidi_log2vis' => ['string', 'string'=>'string', 'direction'=>'string', 'charset'=>'int'], 'fscanf' => ['list', 'stream'=>'resource', 'format'=>'string'], 'fscanf\'1' => ['int', 'stream'=>'resource', 'format'=>'string', '&...w_vars='=>'string|int|float'], 'fseek' => ['int', 'fp'=>'resource', 'offset'=>'int', 'whence='=>'int'], 'fsockopen' => ['resource|false', 'hostname'=>'string', 'port='=>'int', '&w_errno='=>'int', '&w_errstr='=>'string', 'timeout='=>'float'], 'fstat' => ['array|false', 'fp'=>'resource'], 'ftell' => ['int|false', 'fp'=>'resource'], 'ftok' => ['int', 'pathname'=>'string', 'proj'=>'string'], 'ftp_alloc' => ['bool', 'stream'=>'resource', 'size'=>'int', '&w_response='=>'string'], 'ftp_append' => ['bool', 'ftp'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int'], 'ftp_cdup' => ['bool', 'stream'=>'resource'], 'ftp_chdir' => ['bool', 'stream'=>'resource', 'directory'=>'string'], 'ftp_chmod' => ['int|false', 'stream'=>'resource', 'mode'=>'int', 'filename'=>'string'], 'ftp_close' => ['bool', 'stream'=>'resource'], 'ftp_connect' => ['resource|false', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'ftp_delete' => ['bool', 'stream'=>'resource', 'file'=>'string'], 'ftp_exec' => ['bool', 'stream'=>'resource', 'command'=>'string'], 'ftp_fget' => ['bool', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'int', 'resumepos='=>'int'], 'ftp_fput' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'int', 'startpos='=>'int'], 'ftp_get' => ['bool', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'int', 'resume_pos='=>'int'], 'ftp_get_option' => ['mixed|false', 'stream'=>'resource', 'option'=>'int'], 'ftp_login' => ['bool', 'stream'=>'resource', 'username'=>'string', 'password'=>'string'], 'ftp_mdtm' => ['int', 'stream'=>'resource', 'filename'=>'string'], 'ftp_mkdir' => ['string|false', 'stream'=>'resource', 'directory'=>'string'], 'ftp_mlsd' => ['array', 'ftp_stream'=>'resource', 'directory'=>'string'], 'ftp_nb_continue' => ['int', 'stream'=>'resource'], 'ftp_nb_fget' => ['int', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'int', 'resumepos='=>'int'], 'ftp_nb_fput' => ['int', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'int', 'startpos='=>'int'], 'ftp_nb_get' => ['int', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'int', 'resume_pos='=>'int'], 'ftp_nb_put' => ['int', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int', 'startpos='=>'int'], 'ftp_nlist' => ['array|false', 'stream'=>'resource', 'directory'=>'string'], 'ftp_pasv' => ['bool', 'stream'=>'resource', 'pasv'=>'bool'], 'ftp_put' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int', 'startpos='=>'int'], 'ftp_pwd' => ['string|false', 'stream'=>'resource'], 'ftp_quit' => ['bool', 'stream'=>'resource'], 'ftp_raw' => ['array', 'stream'=>'resource', 'command'=>'string'], 'ftp_rawlist' => ['array|false', 'stream'=>'resource', 'directory'=>'string', 'recursive='=>'bool'], 'ftp_rename' => ['bool', 'stream'=>'resource', 'src'=>'string', 'dest'=>'string'], 'ftp_rmdir' => ['bool', 'stream'=>'resource', 'directory'=>'string'], 'ftp_set_option' => ['bool', 'stream'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'ftp_site' => ['bool', 'stream'=>'resource', 'cmd'=>'string'], 'ftp_size' => ['int', 'stream'=>'resource', 'filename'=>'string'], 'ftp_ssl_connect' => ['resource|false', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'ftp_systype' => ['string|false', 'stream'=>'resource'], 'ftruncate' => ['bool', 'fp'=>'resource', 'size'=>'int'], 'func_get_arg' => ['mixed|false', 'arg_num'=>'int'], 'func_get_args' => ['list'], 'func_num_args' => ['int'], 'function_exists' => ['bool', 'function_name'=>'string'], 'fwrite' => ['int|false', 'fp'=>'resource', 'string'=>'string', 'length='=>'int'], 'gc_collect_cycles' => ['int'], 'gc_disable' => ['void'], 'gc_enable' => ['void'], 'gc_enabled' => ['bool'], 'gc_mem_caches' => ['int'], 'gc_status' => ['array{runs:int,collected:int,threshold:int,roots:int}'], 'gd_info' => ['array'], 'gearman_bugreport' => [''], 'gearman_client_add_options' => ['', 'client_object'=>'', 'option'=>''], 'gearman_client_add_server' => ['', 'client_object'=>'', 'host'=>'', 'port'=>''], 'gearman_client_add_servers' => ['', 'client_object'=>'', 'servers'=>''], 'gearman_client_add_task' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_high' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_high_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_low' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_low_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_status' => ['', 'client_object'=>'', 'job_handle'=>'', 'context'=>''], 'gearman_client_clear_fn' => ['', 'client_object'=>''], 'gearman_client_clone' => ['', 'client_object'=>''], 'gearman_client_context' => ['', 'client_object'=>''], 'gearman_client_create' => ['', 'client_object'=>''], 'gearman_client_do' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_high' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_high_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_job_handle' => ['', 'client_object'=>''], 'gearman_client_do_low' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_low_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_normal' => ['', 'client_object'=>'', 'function_name'=>'string', 'workload'=>'string', 'unique'=>'string'], 'gearman_client_do_status' => ['', 'client_object'=>''], 'gearman_client_echo' => ['', 'client_object'=>'', 'workload'=>''], 'gearman_client_errno' => ['', 'client_object'=>''], 'gearman_client_error' => ['', 'client_object'=>''], 'gearman_client_job_status' => ['', 'client_object'=>'', 'job_handle'=>''], 'gearman_client_options' => ['', 'client_object'=>''], 'gearman_client_remove_options' => ['', 'client_object'=>'', 'option'=>''], 'gearman_client_return_code' => ['', 'client_object'=>''], 'gearman_client_run_tasks' => ['', 'data'=>''], 'gearman_client_set_complete_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_context' => ['', 'client_object'=>'', 'context'=>''], 'gearman_client_set_created_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_data_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_exception_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_fail_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_options' => ['', 'client_object'=>'', 'option'=>''], 'gearman_client_set_status_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_timeout' => ['', 'client_object'=>'', 'timeout'=>''], 'gearman_client_set_warning_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_workload_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_timeout' => ['', 'client_object'=>''], 'gearman_client_wait' => ['', 'client_object'=>''], 'gearman_job_function_name' => ['', 'job_object'=>''], 'gearman_job_handle' => ['string'], 'gearman_job_return_code' => ['', 'job_object'=>''], 'gearman_job_send_complete' => ['', 'job_object'=>'', 'result'=>''], 'gearman_job_send_data' => ['', 'job_object'=>'', 'data'=>''], 'gearman_job_send_exception' => ['', 'job_object'=>'', 'exception'=>''], 'gearman_job_send_fail' => ['', 'job_object'=>''], 'gearman_job_send_status' => ['', 'job_object'=>'', 'numerator'=>'', 'denominator'=>''], 'gearman_job_send_warning' => ['', 'job_object'=>'', 'warning'=>''], 'gearman_job_status' => ['array', 'job_handle'=>'string'], 'gearman_job_unique' => ['', 'job_object'=>''], 'gearman_job_workload' => ['', 'job_object'=>''], 'gearman_job_workload_size' => ['', 'job_object'=>''], 'gearman_task_data' => ['', 'task_object'=>''], 'gearman_task_data_size' => ['', 'task_object'=>''], 'gearman_task_denominator' => ['', 'task_object'=>''], 'gearman_task_function_name' => ['', 'task_object'=>''], 'gearman_task_is_known' => ['', 'task_object'=>''], 'gearman_task_is_running' => ['', 'task_object'=>''], 'gearman_task_job_handle' => ['', 'task_object'=>''], 'gearman_task_numerator' => ['', 'task_object'=>''], 'gearman_task_recv_data' => ['', 'task_object'=>'', 'data_len'=>''], 'gearman_task_return_code' => ['', 'task_object'=>''], 'gearman_task_send_workload' => ['', 'task_object'=>'', 'data'=>''], 'gearman_task_unique' => ['', 'task_object'=>''], 'gearman_verbose_name' => ['', 'verbose'=>''], 'gearman_version' => [''], 'gearman_worker_add_function' => ['', 'worker_object'=>'', 'function_name'=>'', 'function'=>'', 'data'=>'', 'timeout'=>''], 'gearman_worker_add_options' => ['', 'worker_object'=>'', 'option'=>''], 'gearman_worker_add_server' => ['', 'worker_object'=>'', 'host'=>'', 'port'=>''], 'gearman_worker_add_servers' => ['', 'worker_object'=>'', 'servers'=>''], 'gearman_worker_clone' => ['', 'worker_object'=>''], 'gearman_worker_create' => [''], 'gearman_worker_echo' => ['', 'worker_object'=>'', 'workload'=>''], 'gearman_worker_errno' => ['', 'worker_object'=>''], 'gearman_worker_error' => ['', 'worker_object'=>''], 'gearman_worker_grab_job' => ['', 'worker_object'=>''], 'gearman_worker_options' => ['', 'worker_object'=>''], 'gearman_worker_register' => ['', 'worker_object'=>'', 'function_name'=>'', 'timeout'=>''], 'gearman_worker_remove_options' => ['', 'worker_object'=>'', 'option'=>''], 'gearman_worker_return_code' => ['', 'worker_object'=>''], 'gearman_worker_set_options' => ['', 'worker_object'=>'', 'option'=>''], 'gearman_worker_set_timeout' => ['', 'worker_object'=>'', 'timeout'=>''], 'gearman_worker_timeout' => ['', 'worker_object'=>''], 'gearman_worker_unregister' => ['', 'worker_object'=>'', 'function_name'=>''], 'gearman_worker_unregister_all' => ['', 'worker_object'=>''], 'gearman_worker_wait' => ['', 'worker_object'=>''], 'gearman_worker_work' => ['', 'worker_object'=>''], 'GearmanClient::__construct' => ['void'], 'GearmanClient::addOptions' => ['bool', 'options'=>'int'], 'GearmanClient::addServer' => ['bool', 'host='=>'string', 'port='=>'int'], 'GearmanClient::addServers' => ['bool', 'servers='=>'string'], 'GearmanClient::addTask' => ['GearmanTask|false', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskBackground' => ['GearmanTask|false', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskHigh' => ['GearmanTask|false', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskHighBackground' => ['GearmanTask|false', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskLow' => ['GearmanTask|false', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskLowBackground' => ['GearmanTask|false', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskStatus' => ['GearmanTask', 'job_handle'=>'string', 'context='=>'string'], 'GearmanClient::clearCallbacks' => ['bool'], 'GearmanClient::clone' => ['GearmanClient'], 'GearmanClient::context' => ['string'], 'GearmanClient::data' => ['string'], 'GearmanClient::do' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doBackground' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doHigh' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doHighBackground' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doJobHandle' => ['string'], 'GearmanClient::doLow' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doLowBackground' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doNormal' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doStatus' => ['array'], 'GearmanClient::echo' => ['bool', 'workload'=>'string'], 'GearmanClient::error' => ['string'], 'GearmanClient::getErrno' => ['int'], 'GearmanClient::jobStatus' => ['array', 'job_handle'=>'string'], 'GearmanClient::options' => [''], 'GearmanClient::ping' => ['bool', 'workload'=>'string'], 'GearmanClient::removeOptions' => ['bool', 'options'=>'int'], 'GearmanClient::returnCode' => ['int'], 'GearmanClient::runTasks' => ['bool'], 'GearmanClient::setClientCallback' => ['void', 'callback'=>'callable'], 'GearmanClient::setCompleteCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setContext' => ['bool', 'context'=>'string'], 'GearmanClient::setCreatedCallback' => ['bool', 'callback'=>'string'], 'GearmanClient::setData' => ['bool', 'data'=>'string'], 'GearmanClient::setDataCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setExceptionCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setFailCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setOptions' => ['bool', 'options'=>'int'], 'GearmanClient::setStatusCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setTimeout' => ['bool', 'timeout'=>'int'], 'GearmanClient::setWarningCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setWorkloadCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::timeout' => ['int'], 'GearmanClient::wait' => [''], 'GearmanJob::__construct' => ['void'], 'GearmanJob::complete' => ['bool', 'result'=>'string'], 'GearmanJob::data' => ['bool', 'data'=>'string'], 'GearmanJob::exception' => ['bool', 'exception'=>'string'], 'GearmanJob::fail' => ['bool'], 'GearmanJob::functionName' => ['string'], 'GearmanJob::handle' => ['string'], 'GearmanJob::returnCode' => ['int'], 'GearmanJob::sendComplete' => ['bool', 'result'=>'string'], 'GearmanJob::sendData' => ['bool', 'data'=>'string'], 'GearmanJob::sendException' => ['bool', 'exception'=>'string'], 'GearmanJob::sendFail' => ['bool'], 'GearmanJob::sendStatus' => ['bool', 'numerator'=>'int', 'denominator'=>'int'], 'GearmanJob::sendWarning' => ['bool', 'warning'=>'string'], 'GearmanJob::setReturn' => ['bool', 'gearman_return_t'=>'string'], 'GearmanJob::status' => ['bool', 'numerator'=>'int', 'denominator'=>'int'], 'GearmanJob::unique' => ['string'], 'GearmanJob::warning' => ['bool', 'warning'=>'string'], 'GearmanJob::workload' => ['string'], 'GearmanJob::workloadSize' => ['int'], 'GearmanTask::__construct' => ['void'], 'GearmanTask::create' => ['GearmanTask'], 'GearmanTask::data' => ['string|false'], 'GearmanTask::dataSize' => ['int|false'], 'GearmanTask::function' => ['string'], 'GearmanTask::functionName' => ['string'], 'GearmanTask::isKnown' => ['bool'], 'GearmanTask::isRunning' => ['bool'], 'GearmanTask::jobHandle' => ['string'], 'GearmanTask::recvData' => ['array|false', 'data_len'=>'int'], 'GearmanTask::returnCode' => ['int'], 'GearmanTask::sendData' => ['int', 'data'=>'string'], 'GearmanTask::sendWorkload' => ['int|false', 'data'=>'string'], 'GearmanTask::taskDenominator' => ['int|false'], 'GearmanTask::taskNumerator' => ['int|false'], 'GearmanTask::unique' => ['string|false'], 'GearmanTask::uuid' => ['string'], 'GearmanWorker::__construct' => ['void'], 'GearmanWorker::addFunction' => ['bool', 'function_name'=>'string', 'function'=>'callable', 'context='=>'mixed', 'timeout='=>'int'], 'GearmanWorker::addOptions' => ['bool', 'option'=>'int'], 'GearmanWorker::addServer' => ['bool', 'host='=>'string', 'port='=>'int'], 'GearmanWorker::addServers' => ['bool', 'servers'=>'string'], 'GearmanWorker::clone' => ['void'], 'GearmanWorker::echo' => ['bool', 'workload'=>'string'], 'GearmanWorker::error' => ['string'], 'GearmanWorker::getErrno' => ['int'], 'GearmanWorker::grabJob' => [''], 'GearmanWorker::options' => ['int'], 'GearmanWorker::register' => ['bool', 'function_name'=>'string', 'timeout='=>'int'], 'GearmanWorker::removeOptions' => ['bool', 'option'=>'int'], 'GearmanWorker::returnCode' => ['int'], 'GearmanWorker::setId' => ['bool', 'id'=>'string'], 'GearmanWorker::setOptions' => ['bool', 'option'=>'int'], 'GearmanWorker::setTimeout' => ['bool', 'timeout'=>'int'], 'GearmanWorker::timeout' => ['int'], 'GearmanWorker::unregister' => ['bool', 'function_name'=>'string'], 'GearmanWorker::unregisterAll' => ['bool'], 'GearmanWorker::wait' => ['bool'], 'GearmanWorker::work' => ['bool'], 'Gender\Gender::__construct' => ['void', 'dsn='=>'string'], 'Gender\Gender::connect' => ['bool', 'dsn'=>'string'], 'Gender\Gender::country' => ['array', 'country'=>'int'], 'Gender\Gender::get' => ['int', 'name'=>'string', 'country='=>'int'], 'Gender\Gender::isNick' => ['array', 'name0'=>'string', 'name1'=>'string', 'country='=>'int'], 'Gender\Gender::similarNames' => ['array', 'name'=>'string', 'country='=>'int'], 'Generator::__wakeup' => ['void'], 'Generator::current' => ['mixed'], 'Generator::getReturn' => ['mixed'], 'Generator::key' => ['mixed'], 'Generator::next' => ['void'], 'Generator::rewind' => ['void'], 'Generator::send' => ['mixed', 'value'=>'mixed'], 'Generator::throw' => ['mixed', 'exception'=>'Exception|Throwable'], 'Generator::valid' => ['bool'], 'geoip_asnum_by_name' => ['string|false', 'hostname'=>'string'], 'geoip_continent_code_by_name' => ['string|false', 'hostname'=>'string'], 'geoip_country_code3_by_name' => ['string|false', 'hostname'=>'string'], 'geoip_country_code_by_name' => ['string|false', 'hostname'=>'string'], 'geoip_country_name_by_name' => ['string|false', 'hostname'=>'string'], 'geoip_database_info' => ['string', 'database='=>'int'], 'geoip_db_avail' => ['bool', 'database'=>'int'], 'geoip_db_filename' => ['string', 'database'=>'int'], 'geoip_db_get_all_info' => ['array'], 'geoip_domain_by_name' => ['string', 'hostname'=>'string'], 'geoip_id_by_name' => ['int', 'hostname'=>'string'], 'geoip_isp_by_name' => ['string|false', 'hostname'=>'string'], 'geoip_netspeedcell_by_name' => ['string|false', 'hostname'=>'string'], 'geoip_org_by_name' => ['string|false', 'hostname'=>'string'], 'geoip_record_by_name' => ['array|false', 'hostname'=>'string'], 'geoip_region_by_name' => ['array|false', 'hostname'=>'string'], 'geoip_region_name_by_code' => ['string|false', 'country_code'=>'string', 'region_code'=>'string'], 'geoip_setup_custom_directory' => ['void', 'path'=>'string'], 'geoip_time_zone_by_country_and_region' => ['string|false', 'country_code'=>'string', 'region_code='=>'string'], 'get_browser' => ['array|object|false', 'browser_name='=>'string', 'return_array='=>'bool'], 'get_call_stack' => [''], 'get_called_class' => ['class-string'], 'get_cfg_var' => ['string|false', 'option_name'=>'string'], 'get_class' => ['class-string|false', 'object='=>'object'], 'get_class_methods' => ['list|null', 'class'=>'mixed'], 'get_class_vars' => ['array', 'class_name'=>'string'], 'get_current_user' => ['string'], 'get_debug_type' => ['string', 'data'=>'mixed'], 'get_declared_classes' => ['list'], 'get_declared_interfaces' => ['list'], 'get_declared_traits' => ['list|null'], 'get_defined_constants' => ['array', 'categorize='=>'bool'], 'get_defined_functions' => ['array>', 'exclude_disabled='=>'bool'], 'get_defined_vars' => ['array'], 'get_extension_funcs' => ['list|false', 'extension_name'=>'string'], 'get_headers' => ['array|false', 'url'=>'string', 'format='=>'int', 'context='=>'resource'], 'get_html_translation_table' => ['array', 'table='=>'int', 'flags='=>'int', 'encoding='=>'string'], 'get_include_path' => ['string'], 'get_included_files' => ['list'], 'get_loaded_extensions' => ['list', 'zend_extensions='=>'bool'], 'get_magic_quotes_gpc' => ['int|false'], 'get_magic_quotes_runtime' => ['int|false'], 'get_meta_tags' => ['array', 'filename'=>'string', 'use_include_path='=>'bool'], 'get_object_vars' => ['array', 'object'=>'object'], 'get_parent_class' => ['class-string|false', 'object='=>'mixed'], 'get_required_files' => ['list'], 'get_resource_id' => ['int', 'res'=>'resource'], 'get_resource_type' => ['string', 'res'=>'resource'], 'get_resources' => ['array', 'resource_type='=>'string'], 'getallheaders' => ['array|false'], 'getcwd' => ['string|false'], 'getdate' => ['array', 'timestamp='=>'int'], 'getenv' => ['string|false', 'varname'=>'string', 'local_only='=>'bool'], 'getenv\'1' => ['array'], 'gethostbyaddr' => ['string|false', 'ip_address'=>'string'], 'gethostbyname' => ['string', 'hostname'=>'string'], 'gethostbynamel' => ['list|false', 'hostname'=>'string'], 'gethostname' => ['string|false'], 'getimagesize' => ['array|false', 'imagefile'=>'string', '&w_info='=>'array'], 'getimagesizefromstring' => ['array|false', 'data'=>'string', '&w_info='=>'array'], 'getlastmod' => ['int|false'], 'getmxrr' => ['bool', 'hostname'=>'string', '&w_mxhosts'=>'array', '&w_weight='=>'array'], 'getmygid' => ['int|false'], 'getmyinode' => ['int|false'], 'getmypid' => ['int|false'], 'getmyuid' => ['int|false'], 'getopt' => ['array|array|array>|false', 'options'=>'string', 'longopts='=>'array', '&w_optind='=>'int'], 'getprotobyname' => ['int|false', 'name'=>'string'], 'getprotobynumber' => ['string', 'proto'=>'int'], 'getrandmax' => ['int'], 'getrusage' => ['array', 'who='=>'int'], 'getservbyname' => ['int|false', 'service'=>'string', 'protocol'=>'string'], 'getservbyport' => ['string|false', 'port'=>'int', 'protocol'=>'string'], 'gettext' => ['string', 'msgid'=>'string'], 'gettimeofday' => ['array'], 'gettimeofday\'1' => ['float', 'get_as_float='=>'true'], 'gettype' => ['string', 'var'=>'mixed'], 'glob' => ['list|false', 'pattern'=>'string', 'flags='=>'int'], 'GlobIterator::__construct' => ['void', 'path'=>'string', 'flags='=>'int'], 'GlobIterator::count' => ['int'], 'GlobIterator::current' => ['FilesystemIterator|SplFileInfo|string'], 'GlobIterator::getATime' => [''], 'GlobIterator::getBasename' => ['', 'suffix='=>'string'], 'GlobIterator::getCTime' => [''], 'GlobIterator::getExtension' => [''], 'GlobIterator::getFileInfo' => [''], 'GlobIterator::getFilename' => [''], 'GlobIterator::getFlags' => ['int'], 'GlobIterator::getGroup' => [''], 'GlobIterator::getInode' => [''], 'GlobIterator::getLinkTarget' => [''], 'GlobIterator::getMTime' => [''], 'GlobIterator::getOwner' => [''], 'GlobIterator::getPath' => [''], 'GlobIterator::getPathInfo' => [''], 'GlobIterator::getPathname' => [''], 'GlobIterator::getPerms' => [''], 'GlobIterator::getRealPath' => [''], 'GlobIterator::getSize' => [''], 'GlobIterator::getType' => [''], 'GlobIterator::isDir' => [''], 'GlobIterator::isDot' => [''], 'GlobIterator::isExecutable' => [''], 'GlobIterator::isFile' => [''], 'GlobIterator::isLink' => [''], 'GlobIterator::isReadable' => [''], 'GlobIterator::isWritable' => [''], 'GlobIterator::key' => ['string'], 'GlobIterator::next' => ['void'], 'GlobIterator::openFile' => [''], 'GlobIterator::rewind' => ['void'], 'GlobIterator::seek' => ['void', 'position'=>'int'], 'GlobIterator::setFileClass' => [''], 'GlobIterator::setFlags' => ['void', 'flags='=>'int'], 'GlobIterator::setInfoClass' => [''], 'GlobIterator::valid' => [''], 'Gmagick::__construct' => ['void', 'filename='=>'string'], 'Gmagick::addimage' => ['Gmagick', 'gmagick'=>'gmagick'], 'Gmagick::addnoiseimage' => ['Gmagick', 'noise'=>'int'], 'Gmagick::annotateimage' => ['Gmagick', 'gmagickdraw'=>'gmagickdraw', 'x'=>'float', 'y'=>'float', 'angle'=>'float', 'text'=>'string'], 'Gmagick::blurimage' => ['Gmagick', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Gmagick::borderimage' => ['Gmagick', 'color'=>'gmagickpixel', 'width'=>'int', 'height'=>'int'], 'Gmagick::charcoalimage' => ['Gmagick', 'radius'=>'float', 'sigma'=>'float'], 'Gmagick::chopimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Gmagick::clear' => ['Gmagick'], 'Gmagick::commentimage' => ['Gmagick', 'comment'=>'string'], 'Gmagick::compositeimage' => ['Gmagick', 'source'=>'gmagick', 'compose'=>'int', 'x'=>'int', 'y'=>'int'], 'Gmagick::cropimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Gmagick::cropthumbnailimage' => ['Gmagick', 'width'=>'int', 'height'=>'int'], 'Gmagick::current' => ['Gmagick'], 'Gmagick::cyclecolormapimage' => ['Gmagick', 'displace'=>'int'], 'Gmagick::deconstructimages' => ['Gmagick'], 'Gmagick::despeckleimage' => ['Gmagick'], 'Gmagick::destroy' => ['bool'], 'Gmagick::drawimage' => ['Gmagick', 'gmagickdraw'=>'gmagickdraw'], 'Gmagick::edgeimage' => ['Gmagick', 'radius'=>'float'], 'Gmagick::embossimage' => ['Gmagick', 'radius'=>'float', 'sigma'=>'float'], 'Gmagick::enhanceimage' => ['Gmagick'], 'Gmagick::equalizeimage' => ['Gmagick'], 'Gmagick::flipimage' => ['Gmagick'], 'Gmagick::flopimage' => ['Gmagick'], 'Gmagick::frameimage' => ['Gmagick', 'color'=>'gmagickpixel', 'width'=>'int', 'height'=>'int', 'inner_bevel'=>'int', 'outer_bevel'=>'int'], 'Gmagick::gammaimage' => ['Gmagick', 'gamma'=>'float'], 'Gmagick::getcopyright' => ['string'], 'Gmagick::getfilename' => ['string'], 'Gmagick::getimagebackgroundcolor' => ['GmagickPixel'], 'Gmagick::getimageblueprimary' => ['array'], 'Gmagick::getimagebordercolor' => ['GmagickPixel'], 'Gmagick::getimagechanneldepth' => ['int', 'channel_type'=>'int'], 'Gmagick::getimagecolors' => ['int'], 'Gmagick::getimagecolorspace' => ['int'], 'Gmagick::getimagecompose' => ['int'], 'Gmagick::getimagedelay' => ['int'], 'Gmagick::getimagedepth' => ['int'], 'Gmagick::getimagedispose' => ['int'], 'Gmagick::getimageextrema' => ['array'], 'Gmagick::getimagefilename' => ['string'], 'Gmagick::getimageformat' => ['string'], 'Gmagick::getimagegamma' => ['float'], 'Gmagick::getimagegreenprimary' => ['array'], 'Gmagick::getimageheight' => ['int'], 'Gmagick::getimagehistogram' => ['array'], 'Gmagick::getimageindex' => ['int'], 'Gmagick::getimageinterlacescheme' => ['int'], 'Gmagick::getimageiterations' => ['int'], 'Gmagick::getimagematte' => ['int'], 'Gmagick::getimagemattecolor' => ['GmagickPixel'], 'Gmagick::getimageprofile' => ['string', 'name'=>'string'], 'Gmagick::getimageredprimary' => ['array'], 'Gmagick::getimagerenderingintent' => ['int'], 'Gmagick::getimageresolution' => ['array'], 'Gmagick::getimagescene' => ['int'], 'Gmagick::getimagesignature' => ['string'], 'Gmagick::getimagetype' => ['int'], 'Gmagick::getimageunits' => ['int'], 'Gmagick::getimagewhitepoint' => ['array'], 'Gmagick::getimagewidth' => ['int'], 'Gmagick::getpackagename' => ['string'], 'Gmagick::getquantumdepth' => ['array'], 'Gmagick::getreleasedate' => ['string'], 'Gmagick::getsamplingfactors' => ['array'], 'Gmagick::getsize' => ['array'], 'Gmagick::getversion' => ['array'], 'Gmagick::hasnextimage' => ['bool'], 'Gmagick::haspreviousimage' => ['bool'], 'Gmagick::implodeimage' => ['mixed', 'radius'=>'float'], 'Gmagick::labelimage' => ['mixed', 'label'=>'string'], 'Gmagick::levelimage' => ['mixed', 'blackpoint'=>'float', 'gamma'=>'float', 'whitepoint'=>'float', 'channel='=>'int'], 'Gmagick::magnifyimage' => ['mixed'], 'Gmagick::mapimage' => ['Gmagick', 'gmagick'=>'gmagick', 'dither'=>'bool'], 'Gmagick::medianfilterimage' => ['void', 'radius'=>'float'], 'Gmagick::minifyimage' => ['Gmagick'], 'Gmagick::modulateimage' => ['Gmagick', 'brightness'=>'float', 'saturation'=>'float', 'hue'=>'float'], 'Gmagick::motionblurimage' => ['Gmagick', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float'], 'Gmagick::newimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'background'=>'string', 'format='=>'string'], 'Gmagick::nextimage' => ['bool'], 'Gmagick::normalizeimage' => ['Gmagick', 'channel='=>'int'], 'Gmagick::oilpaintimage' => ['Gmagick', 'radius'=>'float'], 'Gmagick::previousimage' => ['bool'], 'Gmagick::profileimage' => ['Gmagick', 'name'=>'string', 'profile'=>'string'], 'Gmagick::quantizeimage' => ['Gmagick', 'numcolors'=>'int', 'colorspace'=>'int', 'treedepth'=>'int', 'dither'=>'bool', 'measureerror'=>'bool'], 'Gmagick::quantizeimages' => ['Gmagick', 'numcolors'=>'int', 'colorspace'=>'int', 'treedepth'=>'int', 'dither'=>'bool', 'measureerror'=>'bool'], 'Gmagick::queryfontmetrics' => ['array', 'draw'=>'gmagickdraw', 'text'=>'string'], 'Gmagick::queryfonts' => ['array', 'pattern='=>'string'], 'Gmagick::queryformats' => ['array', 'pattern='=>'string'], 'Gmagick::radialblurimage' => ['Gmagick', 'angle'=>'float', 'channel='=>'int'], 'Gmagick::raiseimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int', 'raise'=>'bool'], 'Gmagick::read' => ['Gmagick', 'filename'=>'string'], 'Gmagick::readimage' => ['Gmagick', 'filename'=>'string'], 'Gmagick::readimageblob' => ['Gmagick', 'imagecontents'=>'string', 'filename='=>'string'], 'Gmagick::readimagefile' => ['Gmagick', 'fp'=>'resource', 'filename='=>'string'], 'Gmagick::reducenoiseimage' => ['Gmagick', 'radius'=>'float'], 'Gmagick::removeimage' => ['Gmagick'], 'Gmagick::removeimageprofile' => ['string', 'name'=>'string'], 'Gmagick::resampleimage' => ['Gmagick', 'xresolution'=>'float', 'yresolution'=>'float', 'filter'=>'int', 'blur'=>'float'], 'Gmagick::resizeimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'filter'=>'int', 'blur'=>'float', 'fit='=>'bool'], 'Gmagick::rollimage' => ['Gmagick', 'x'=>'int', 'y'=>'int'], 'Gmagick::rotateimage' => ['Gmagick', 'color'=>'mixed', 'degrees'=>'float'], 'Gmagick::scaleimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'fit='=>'bool'], 'Gmagick::separateimagechannel' => ['Gmagick', 'channel'=>'int'], 'Gmagick::setCompressionQuality' => ['Gmagick', 'quality'=>'int'], 'Gmagick::setfilename' => ['Gmagick', 'filename'=>'string'], 'Gmagick::setimagebackgroundcolor' => ['Gmagick', 'color'=>'gmagickpixel'], 'Gmagick::setimageblueprimary' => ['Gmagick', 'x'=>'float', 'y'=>'float'], 'Gmagick::setimagebordercolor' => ['Gmagick', 'color'=>'gmagickpixel'], 'Gmagick::setimagechanneldepth' => ['Gmagick', 'channel'=>'int', 'depth'=>'int'], 'Gmagick::setimagecolorspace' => ['Gmagick', 'colorspace'=>'int'], 'Gmagick::setimagecompose' => ['Gmagick', 'composite'=>'int'], 'Gmagick::setimagedelay' => ['Gmagick', 'delay'=>'int'], 'Gmagick::setimagedepth' => ['Gmagick', 'depth'=>'int'], 'Gmagick::setimagedispose' => ['Gmagick', 'disposetype'=>'int'], 'Gmagick::setimagefilename' => ['Gmagick', 'filename'=>'string'], 'Gmagick::setimageformat' => ['Gmagick', 'imageformat'=>'string'], 'Gmagick::setimagegamma' => ['Gmagick', 'gamma'=>'float'], 'Gmagick::setimagegreenprimary' => ['Gmagick', 'x'=>'float', 'y'=>'float'], 'Gmagick::setimageindex' => ['Gmagick', 'index'=>'int'], 'Gmagick::setimageinterlacescheme' => ['Gmagick', 'interlace'=>'int'], 'Gmagick::setimageiterations' => ['Gmagick', 'iterations'=>'int'], 'Gmagick::setimageprofile' => ['Gmagick', 'name'=>'string', 'profile'=>'string'], 'Gmagick::setimageredprimary' => ['Gmagick', 'x'=>'float', 'y'=>'float'], 'Gmagick::setimagerenderingintent' => ['Gmagick', 'rendering_intent'=>'int'], 'Gmagick::setimageresolution' => ['Gmagick', 'xresolution'=>'float', 'yresolution'=>'float'], 'Gmagick::setimagescene' => ['Gmagick', 'scene'=>'int'], 'Gmagick::setimagetype' => ['Gmagick', 'imgtype'=>'int'], 'Gmagick::setimageunits' => ['Gmagick', 'resolution'=>'int'], 'Gmagick::setimagewhitepoint' => ['Gmagick', 'x'=>'float', 'y'=>'float'], 'Gmagick::setsamplingfactors' => ['Gmagick', 'factors'=>'array'], 'Gmagick::setsize' => ['Gmagick', 'columns'=>'int', 'rows'=>'int'], 'Gmagick::shearimage' => ['Gmagick', 'color'=>'mixed', 'xshear'=>'float', 'yshear'=>'float'], 'Gmagick::solarizeimage' => ['Gmagick', 'threshold'=>'int'], 'Gmagick::spreadimage' => ['Gmagick', 'radius'=>'float'], 'Gmagick::stripimage' => ['Gmagick'], 'Gmagick::swirlimage' => ['Gmagick', 'degrees'=>'float'], 'Gmagick::thumbnailimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'fit='=>'bool'], 'Gmagick::trimimage' => ['Gmagick', 'fuzz'=>'float'], 'Gmagick::write' => ['Gmagick', 'filename'=>'string'], 'Gmagick::writeimage' => ['Gmagick', 'filename'=>'string', 'all_frames='=>'bool'], 'GmagickDraw::annotate' => ['GmagickDraw', 'x'=>'float', 'y'=>'float', 'text'=>'string'], 'GmagickDraw::arc' => ['GmagickDraw', 'sx'=>'float', 'sy'=>'float', 'ex'=>'float', 'ey'=>'float', 'sd'=>'float', 'ed'=>'float'], 'GmagickDraw::bezier' => ['GmagickDraw', 'coordinate_array'=>'array'], 'GmagickDraw::ellipse' => ['GmagickDraw', 'ox'=>'float', 'oy'=>'float', 'rx'=>'float', 'ry'=>'float', 'start'=>'float', 'end'=>'float'], 'GmagickDraw::getfillcolor' => ['GmagickPixel'], 'GmagickDraw::getfillopacity' => ['float'], 'GmagickDraw::getfont' => ['string|false'], 'GmagickDraw::getfontsize' => ['float'], 'GmagickDraw::getfontstyle' => ['int'], 'GmagickDraw::getfontweight' => ['int'], 'GmagickDraw::getstrokecolor' => ['GmagickPixel'], 'GmagickDraw::getstrokeopacity' => ['float'], 'GmagickDraw::getstrokewidth' => ['float'], 'GmagickDraw::gettextdecoration' => ['int'], 'GmagickDraw::gettextencoding' => ['string|false'], 'GmagickDraw::line' => ['GmagickDraw', 'sx'=>'float', 'sy'=>'float', 'ex'=>'float', 'ey'=>'float'], 'GmagickDraw::point' => ['GmagickDraw', 'x'=>'float', 'y'=>'float'], 'GmagickDraw::polygon' => ['GmagickDraw', 'coordinates'=>'array'], 'GmagickDraw::polyline' => ['GmagickDraw', 'coordinate_array'=>'array'], 'GmagickDraw::rectangle' => ['GmagickDraw', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float'], 'GmagickDraw::rotate' => ['GmagickDraw', 'degrees'=>'float'], 'GmagickDraw::roundrectangle' => ['GmagickDraw', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'rx'=>'float', 'ry'=>'float'], 'GmagickDraw::scale' => ['GmagickDraw', 'x'=>'float', 'y'=>'float'], 'GmagickDraw::setfillcolor' => ['GmagickDraw', 'color'=>'string'], 'GmagickDraw::setfillopacity' => ['GmagickDraw', 'fill_opacity'=>'float'], 'GmagickDraw::setfont' => ['GmagickDraw', 'font'=>'string'], 'GmagickDraw::setfontsize' => ['GmagickDraw', 'pointsize'=>'float'], 'GmagickDraw::setfontstyle' => ['GmagickDraw', 'style'=>'int'], 'GmagickDraw::setfontweight' => ['GmagickDraw', 'weight'=>'int'], 'GmagickDraw::setstrokecolor' => ['GmagickDraw', 'color'=>'gmagickpixel'], 'GmagickDraw::setstrokeopacity' => ['GmagickDraw', 'stroke_opacity'=>'float'], 'GmagickDraw::setstrokewidth' => ['GmagickDraw', 'width'=>'float'], 'GmagickDraw::settextdecoration' => ['GmagickDraw', 'decoration'=>'int'], 'GmagickDraw::settextencoding' => ['GmagickDraw', 'encoding'=>'string'], 'GmagickPixel::__construct' => ['void', 'color='=>'string'], 'GmagickPixel::getcolor' => ['mixed', 'as_array='=>'bool', 'normalize_array='=>'bool'], 'GmagickPixel::getcolorcount' => ['int'], 'GmagickPixel::getcolorvalue' => ['float', 'color'=>'int'], 'GmagickPixel::setcolor' => ['GmagickPixel', 'color'=>'string'], 'GmagickPixel::setcolorvalue' => ['GmagickPixel', 'color'=>'int', 'value'=>'float'], 'gmdate' => ['string|false', 'format'=>'string', 'timestamp='=>'int'], 'gmmktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'GMP::__construct' => ['void'], 'GMP::__toString' => ['numeric-string'], 'GMP::serialize' => ['string'], 'GMP::unserialize' => ['void', 'serialized'=>'string'], 'gmp_abs' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_add' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_and' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_binomial' => ['GMP|false', 'n'=>'GMP|string|int', 'k'=>'int'], 'gmp_clrbit' => ['void', 'a'=>'GMP|string|int', 'index'=>'int'], 'gmp_cmp' => ['int', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_com' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_div' => ['GMP', 'a'=>'GMP|resource|string', 'b'=>'GMP|resource|string', 'round='=>'int'], 'gmp_div_q' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int', 'round='=>'int'], 'gmp_div_qr' => ['array{0: GMP, 1: GMP}', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int', 'round='=>'int'], 'gmp_div_r' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int', 'round='=>'int'], 'gmp_divexact' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_export' => ['string|false', 'gmpnumber'=>'GMP|string|int', 'word_size='=>'int', 'options='=>'int'], 'gmp_fact' => ['GMP', 'a'=>'int'], 'gmp_gcd' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_gcdext' => ['array', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_hamdist' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_import' => ['GMP|false', 'data'=>'string', 'word_size='=>'int', 'options='=>'int'], 'gmp_init' => ['GMP', 'number'=>'int|string', 'base='=>'int'], 'gmp_intval' => ['int', 'gmpnumber'=>'GMP|string|int'], 'gmp_invert' => ['GMP|false', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_jacobi' => ['int', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_kronecker' => ['int', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_lcm' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_legendre' => ['int', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_mod' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_mul' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_neg' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_nextprime' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_or' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_perfect_power' => ['bool', 'a'=>'GMP|string|int'], 'gmp_perfect_square' => ['bool', 'a'=>'GMP|string|int'], 'gmp_popcount' => ['int', 'a'=>'GMP|string|int'], 'gmp_pow' => ['GMP', 'base'=>'GMP|string|int', 'exp'=>'int'], 'gmp_powm' => ['GMP', 'base'=>'GMP|string|int', 'exp'=>'GMP|string|int', 'mod'=>'GMP|string|int'], 'gmp_prob_prime' => ['int', 'a'=>'GMP|string|int', 'reps='=>'int'], 'gmp_random' => ['GMP', 'limiter='=>'int'], 'gmp_random_bits' => ['GMP', 'bits'=>'int'], 'gmp_random_range' => ['GMP', 'min'=>'GMP|string|int', 'max'=>'GMP|string|int'], 'gmp_random_seed' => ['void', 'seed'=>'GMP|string|int'], 'gmp_root' => ['GMP', 'a'=>'GMP|string|int', 'nth'=>'int'], 'gmp_rootrem' => ['array{0: GMP, 1: GMP}', 'a'=>'GMP|string|int', 'nth'=>'int'], 'gmp_scan0' => ['int', 'a'=>'GMP|string|int', 'start'=>'int'], 'gmp_scan1' => ['int', 'a'=>'GMP|string|int', 'start'=>'int'], 'gmp_setbit' => ['void', 'a'=>'GMP|string|int', 'index'=>'int', 'set_clear='=>'bool'], 'gmp_sign' => ['int', 'a'=>'GMP|string|int'], 'gmp_sqrt' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_sqrtrem' => ['array{0: GMP, 1: GMP}', 'a'=>'GMP|string|int'], 'gmp_strval' => ['numeric-string', 'gmpnumber'=>'GMP|string|int', 'base='=>'int'], 'gmp_sub' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_testbit' => ['bool', 'a'=>'GMP|string|int', 'index'=>'int'], 'gmp_xor' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmstrftime' => ['string', 'format'=>'string', 'timestamp='=>'int'], 'gnupg::adddecryptkey' => ['bool', 'fingerprint'=>'string', 'passphrase'=>'string'], 'gnupg::addencryptkey' => ['bool', 'fingerprint'=>'string'], 'gnupg::addsignkey' => ['bool', 'fingerprint'=>'string', 'passphrase='=>'string'], 'gnupg::cleardecryptkeys' => ['bool'], 'gnupg::clearencryptkeys' => ['bool'], 'gnupg::clearsignkeys' => ['bool'], 'gnupg::decrypt' => ['string|false', 'text'=>'string'], 'gnupg::decryptverify' => ['array|false', 'text'=>'string', '&plaintext'=>'string'], 'gnupg::encrypt' => ['string|false', 'plaintext'=>'string'], 'gnupg::encryptsign' => ['string|false', 'plaintext'=>'string'], 'gnupg::export' => ['string|false', 'fingerprint'=>'string'], 'gnupg::geterror' => ['string|false'], 'gnupg::getprotocol' => ['int'], 'gnupg::import' => ['array|false', 'keydata'=>'string'], 'gnupg::init' => ['resource'], 'gnupg::keyinfo' => ['array', 'pattern'=>'string'], 'gnupg::setarmor' => ['bool', 'armor'=>'int'], 'gnupg::seterrormode' => ['void', 'errormode'=>'int'], 'gnupg::setsignmode' => ['bool', 'signmode'=>'int'], 'gnupg::sign' => ['string|false', 'plaintext'=>'string'], 'gnupg::verify' => ['array|false', 'signed_text'=>'string', 'signature'=>'string', '&plaintext='=>'string'], 'gnupg_adddecryptkey' => ['bool', 'identifier'=>'resource', 'fingerprint'=>'string', 'passphrase'=>'string'], 'gnupg_addencryptkey' => ['bool', 'identifier'=>'resource', 'fingerprint'=>'string'], 'gnupg_addsignkey' => ['bool', 'identifier'=>'resource', 'fingerprint'=>'string', 'passphrase='=>'string'], 'gnupg_cleardecryptkeys' => ['bool', 'identifier'=>'resource'], 'gnupg_clearencryptkeys' => ['bool', 'identifier'=>'resource'], 'gnupg_clearsignkeys' => ['bool', 'identifier'=>'resource'], 'gnupg_decrypt' => ['string', 'identifier'=>'resource', 'text'=>'string'], 'gnupg_decryptverify' => ['array', 'identifier'=>'resource', 'text'=>'string', 'plaintext'=>'string'], 'gnupg_encrypt' => ['string', 'identifier'=>'resource', 'plaintext'=>'string'], 'gnupg_encryptsign' => ['string', 'identifier'=>'resource', 'plaintext'=>'string'], 'gnupg_export' => ['string', 'identifier'=>'resource', 'fingerprint'=>'string'], 'gnupg_geterror' => ['string', 'identifier'=>'resource'], 'gnupg_getprotocol' => ['int', 'identifier'=>'resource'], 'gnupg_import' => ['array', 'identifier'=>'resource', 'keydata'=>'string'], 'gnupg_init' => ['resource'], 'gnupg_keyinfo' => ['array', 'identifier'=>'resource', 'pattern'=>'string'], 'gnupg_setarmor' => ['bool', 'identifier'=>'resource', 'armor'=>'int'], 'gnupg_seterrormode' => ['void', 'identifier'=>'resource', 'errormode'=>'int'], 'gnupg_setsignmode' => ['bool', 'identifier'=>'resource', 'signmode'=>'int'], 'gnupg_sign' => ['string', 'identifier'=>'resource', 'plaintext'=>'string'], 'gnupg_verify' => ['array', 'identifier'=>'resource', 'signed_text'=>'string', 'signature'=>'string', 'plaintext='=>'string'], 'gopher_parsedir' => ['array', 'dirent'=>'string'], 'grapheme_extract' => ['string|false', 'string'=>'string', 'size'=>'int', 'extract_type='=>'int', 'start='=>'int', '&w_next='=>'int'], 'grapheme_stripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'grapheme_stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool'], 'grapheme_strlen' => ['int|false|null', 'string'=>'string'], 'grapheme_strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'grapheme_strripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'grapheme_strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'grapheme_strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool'], 'grapheme_substr' => ['string|false', 'string'=>'string', 'start'=>'int', 'length='=>'int'], 'gregoriantojd' => ['int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'gridObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'Grpc\Call::__construct' => ['void', 'channel'=>'Grpc\Channel', 'method'=>'string', 'absolute_deadline'=>'Grpc\Timeval', 'host_override='=>'mixed'], 'Grpc\Call::cancel' => [''], 'Grpc\Call::getPeer' => ['string'], 'Grpc\Call::setCredentials' => ['int', 'creds_obj'=>'Grpc\CallCredentials'], 'Grpc\Call::startBatch' => ['object', 'batch'=>'array'], 'Grpc\CallCredentials::createComposite' => ['Grpc\CallCredentials', 'cred1'=>'Grpc\CallCredentials', 'cred2'=>'Grpc\CallCredentials'], 'Grpc\CallCredentials::createFromPlugin' => ['Grpc\CallCredentials', 'callback'=>'Closure'], 'Grpc\Channel::__construct' => ['void', 'target'=>'string', 'args='=>'array'], 'Grpc\Channel::close' => [''], 'Grpc\Channel::getConnectivityState' => ['int', 'try_to_connect='=>'bool'], 'Grpc\Channel::getTarget' => ['string'], 'Grpc\Channel::watchConnectivityState' => ['bool', 'last_state'=>'int', 'deadline_obj'=>'Grpc\Timeval'], 'Grpc\ChannelCredentials::createComposite' => ['Grpc\ChannelCredentials', 'cred1'=>'Grpc\ChannelCredentials', 'cred2'=>'Grpc\CallCredentials'], 'Grpc\ChannelCredentials::createDefault' => ['Grpc\ChannelCredentials'], 'Grpc\ChannelCredentials::createInsecure' => ['null'], 'Grpc\ChannelCredentials::createSsl' => ['Grpc\ChannelCredentials', 'pem_root_certs'=>'string', 'pem_private_key='=>'string', 'pem_cert_chain='=>'string'], 'Grpc\ChannelCredentials::setDefaultRootsPem' => ['', 'pem_roots'=>'string'], 'Grpc\Server::__construct' => ['void', 'args'=>'array'], 'Grpc\Server::addHttp2Port' => ['bool', 'addr'=>'string'], 'Grpc\Server::addSecureHttp2Port' => ['bool', 'addr'=>'string', 'creds_obj'=>'Grpc\ServerCredentials'], 'Grpc\Server::requestCall' => ['', 'tag_new'=>'int', 'tag_cancel'=>'int'], 'Grpc\Server::start' => [''], 'Grpc\ServerCredentials::createSsl' => ['object', 'pem_root_certs'=>'string', 'pem_private_key'=>'string', 'pem_cert_chain'=>'string'], 'Grpc\Timeval::__construct' => ['void', 'usec'=>'int'], 'Grpc\Timeval::add' => ['Grpc\Timeval', 'other'=>'Grpc\Timeval'], 'Grpc\Timeval::compare' => ['int', 'a'=>'Grpc\Timeval', 'b'=>'Grpc\Timeval'], 'Grpc\Timeval::infFuture' => ['Grpc\Timeval'], 'Grpc\Timeval::infPast' => ['Grpc\Timeval'], 'Grpc\Timeval::now' => ['Grpc\Timeval'], 'Grpc\Timeval::similar' => ['bool', 'a'=>'Grpc\Timeval', 'b'=>'Grpc\Timeval', 'threshold'=>'Grpc\Timeval'], 'Grpc\Timeval::sleepUntil' => [''], 'Grpc\Timeval::subtract' => ['Grpc\Timeval', 'other'=>'Grpc\Timeval'], 'Grpc\Timeval::zero' => ['Grpc\Timeval'], 'gupnp_context_get_host_ip' => ['string', 'context'=>'resource'], 'gupnp_context_get_port' => ['int', 'context'=>'resource'], 'gupnp_context_get_subscription_timeout' => ['int', 'context'=>'resource'], 'gupnp_context_host_path' => ['bool', 'context'=>'resource', 'local_path'=>'string', 'server_path'=>'string'], 'gupnp_context_new' => ['resource', 'host_ip='=>'string', 'port='=>'int'], 'gupnp_context_set_subscription_timeout' => ['void', 'context'=>'resource', 'timeout'=>'int'], 'gupnp_context_timeout_add' => ['bool', 'context'=>'resource', 'timeout'=>'int', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_context_unhost_path' => ['bool', 'context'=>'resource', 'server_path'=>'string'], 'gupnp_control_point_browse_start' => ['bool', 'cpoint'=>'resource'], 'gupnp_control_point_browse_stop' => ['bool', 'cpoint'=>'resource'], 'gupnp_control_point_callback_set' => ['bool', 'cpoint'=>'resource', 'signal'=>'int', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_control_point_new' => ['resource', 'context'=>'resource', 'target'=>'string'], 'gupnp_device_action_callback_set' => ['bool', 'root_device'=>'resource', 'signal'=>'int', 'action_name'=>'string', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_device_info_get' => ['array', 'root_device'=>'resource'], 'gupnp_device_info_get_service' => ['resource', 'root_device'=>'resource', 'type'=>'string'], 'gupnp_root_device_get_available' => ['bool', 'root_device'=>'resource'], 'gupnp_root_device_get_relative_location' => ['string', 'root_device'=>'resource'], 'gupnp_root_device_new' => ['resource', 'context'=>'resource', 'location'=>'string', 'description_dir'=>'string'], 'gupnp_root_device_set_available' => ['bool', 'root_device'=>'resource', 'available'=>'bool'], 'gupnp_root_device_start' => ['bool', 'root_device'=>'resource'], 'gupnp_root_device_stop' => ['bool', 'root_device'=>'resource'], 'gupnp_service_action_get' => ['mixed', 'action'=>'resource', 'name'=>'string', 'type'=>'int'], 'gupnp_service_action_return' => ['bool', 'action'=>'resource'], 'gupnp_service_action_return_error' => ['bool', 'action'=>'resource', 'error_code'=>'int', 'error_description='=>'string'], 'gupnp_service_action_set' => ['bool', 'action'=>'resource', 'name'=>'string', 'type'=>'int', 'value'=>'mixed'], 'gupnp_service_freeze_notify' => ['bool', 'service'=>'resource'], 'gupnp_service_info_get' => ['array', 'proxy'=>'resource'], 'gupnp_service_info_get_introspection' => ['mixed', 'proxy'=>'resource', 'callback='=>'mixed', 'arg='=>'mixed'], 'gupnp_service_introspection_get_state_variable' => ['array', 'introspection'=>'resource', 'variable_name'=>'string'], 'gupnp_service_notify' => ['bool', 'service'=>'resource', 'name'=>'string', 'type'=>'int', 'value'=>'mixed'], 'gupnp_service_proxy_action_get' => ['mixed', 'proxy'=>'resource', 'action'=>'string', 'name'=>'string', 'type'=>'int'], 'gupnp_service_proxy_action_set' => ['bool', 'proxy'=>'resource', 'action'=>'string', 'name'=>'string', 'value'=>'mixed', 'type'=>'int'], 'gupnp_service_proxy_add_notify' => ['bool', 'proxy'=>'resource', 'value'=>'string', 'type'=>'int', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_service_proxy_callback_set' => ['bool', 'proxy'=>'resource', 'signal'=>'int', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_service_proxy_get_subscribed' => ['bool', 'proxy'=>'resource'], 'gupnp_service_proxy_remove_notify' => ['bool', 'proxy'=>'resource', 'value'=>'string'], 'gupnp_service_proxy_send_action' => ['array', 'proxy'=>'resource', 'action'=>'string', 'in_params'=>'array', 'out_params'=>'array'], 'gupnp_service_proxy_set_subscribed' => ['bool', 'proxy'=>'resource', 'subscribed'=>'bool'], 'gupnp_service_thaw_notify' => ['bool', 'service'=>'resource'], 'gzclose' => ['bool', 'zp'=>'resource'], 'gzcompress' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'], 'gzdecode' => ['string|false', 'data'=>'string', 'length='=>'int'], 'gzdeflate' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'], 'gzencode' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding_mode='=>'int'], 'gzeof' => ['bool|int', 'zp'=>'resource'], 'gzfile' => ['list', 'filename'=>'string', 'use_include_path='=>'int'], 'gzgetc' => ['string|false', 'zp'=>'resource'], 'gzgets' => ['string|false', 'zp'=>'resource', 'length='=>'int'], 'gzgetss' => ['string|false', 'zp'=>'resource', 'length'=>'int', 'allowable_tags='=>'string'], 'gzinflate' => ['string|false', 'data'=>'string', 'length='=>'int'], 'gzopen' => ['resource|false', 'filename'=>'string', 'mode'=>'string', 'use_include_path='=>'int'], 'gzpassthru' => ['int|false', 'zp'=>'resource'], 'gzputs' => ['int', 'zp'=>'resource', 'string'=>'string', 'length='=>'int'], 'gzread' => ['string', 'zp'=>'resource', 'length'=>'int'], 'gzrewind' => ['bool', 'zp'=>'resource'], 'gzseek' => ['int', 'zp'=>'resource', 'offset'=>'int', 'whence='=>'int'], 'gztell' => ['int|false', 'zp'=>'resource'], 'gzuncompress' => ['string|false', 'data'=>'string', 'length='=>'int'], 'gzwrite' => ['int', 'zp'=>'resource', 'string'=>'string', 'length='=>'int'], 'HaruAnnotation::setBorderStyle' => ['bool', 'width'=>'float', 'dash_on'=>'int', 'dash_off'=>'int'], 'HaruAnnotation::setHighlightMode' => ['bool', 'mode'=>'int'], 'HaruAnnotation::setIcon' => ['bool', 'icon'=>'int'], 'HaruAnnotation::setOpened' => ['bool', 'opened'=>'bool'], 'HaruDestination::setFit' => ['bool'], 'HaruDestination::setFitB' => ['bool'], 'HaruDestination::setFitBH' => ['bool', 'top'=>'float'], 'HaruDestination::setFitBV' => ['bool', 'left'=>'float'], 'HaruDestination::setFitH' => ['bool', 'top'=>'float'], 'HaruDestination::setFitR' => ['bool', 'left'=>'float', 'bottom'=>'float', 'right'=>'float', 'top'=>'float'], 'HaruDestination::setFitV' => ['bool', 'left'=>'float'], 'HaruDestination::setXYZ' => ['bool', 'left'=>'float', 'top'=>'float', 'zoom'=>'float'], 'HaruDoc::__construct' => ['void'], 'HaruDoc::addPage' => ['object'], 'HaruDoc::addPageLabel' => ['bool', 'first_page'=>'int', 'style'=>'int', 'first_num'=>'int', 'prefix='=>'string'], 'HaruDoc::createOutline' => ['object', 'title'=>'string', 'parent_outline='=>'object', 'encoder='=>'object'], 'HaruDoc::getCurrentEncoder' => ['object'], 'HaruDoc::getCurrentPage' => ['object'], 'HaruDoc::getEncoder' => ['object', 'encoding'=>'string'], 'HaruDoc::getFont' => ['object', 'fontname'=>'string', 'encoding='=>'string'], 'HaruDoc::getInfoAttr' => ['string', 'type'=>'int'], 'HaruDoc::getPageLayout' => ['int'], 'HaruDoc::getPageMode' => ['int'], 'HaruDoc::getStreamSize' => ['int'], 'HaruDoc::insertPage' => ['object', 'page'=>'object'], 'HaruDoc::loadJPEG' => ['object', 'filename'=>'string'], 'HaruDoc::loadPNG' => ['object', 'filename'=>'string', 'deferred='=>'bool'], 'HaruDoc::loadRaw' => ['object', 'filename'=>'string', 'width'=>'int', 'height'=>'int', 'color_space'=>'int'], 'HaruDoc::loadTTC' => ['string', 'fontfile'=>'string', 'index'=>'int', 'embed='=>'bool'], 'HaruDoc::loadTTF' => ['string', 'fontfile'=>'string', 'embed='=>'bool'], 'HaruDoc::loadType1' => ['string', 'afmfile'=>'string', 'pfmfile='=>'string'], 'HaruDoc::output' => ['bool'], 'HaruDoc::readFromStream' => ['string', 'bytes'=>'int'], 'HaruDoc::resetError' => ['bool'], 'HaruDoc::resetStream' => ['bool'], 'HaruDoc::save' => ['bool', 'file'=>'string'], 'HaruDoc::saveToStream' => ['bool'], 'HaruDoc::setCompressionMode' => ['bool', 'mode'=>'int'], 'HaruDoc::setCurrentEncoder' => ['bool', 'encoding'=>'string'], 'HaruDoc::setEncryptionMode' => ['bool', 'mode'=>'int', 'key_len='=>'int'], 'HaruDoc::setInfoAttr' => ['bool', 'type'=>'int', 'info'=>'string'], 'HaruDoc::setInfoDateAttr' => ['bool', 'type'=>'int', 'year'=>'int', 'month'=>'int', 'day'=>'int', 'hour'=>'int', 'min'=>'int', 'sec'=>'int', 'ind'=>'string', 'off_hour'=>'int', 'off_min'=>'int'], 'HaruDoc::setOpenAction' => ['bool', 'destination'=>'object'], 'HaruDoc::setPageLayout' => ['bool', 'layout'=>'int'], 'HaruDoc::setPageMode' => ['bool', 'mode'=>'int'], 'HaruDoc::setPagesConfiguration' => ['bool', 'page_per_pages'=>'int'], 'HaruDoc::setPassword' => ['bool', 'owner_password'=>'string', 'user_password'=>'string'], 'HaruDoc::setPermission' => ['bool', 'permission'=>'int'], 'HaruDoc::useCNSEncodings' => ['bool'], 'HaruDoc::useCNSFonts' => ['bool'], 'HaruDoc::useCNTEncodings' => ['bool'], 'HaruDoc::useCNTFonts' => ['bool'], 'HaruDoc::useJPEncodings' => ['bool'], 'HaruDoc::useJPFonts' => ['bool'], 'HaruDoc::useKREncodings' => ['bool'], 'HaruDoc::useKRFonts' => ['bool'], 'HaruEncoder::getByteType' => ['int', 'text'=>'string', 'index'=>'int'], 'HaruEncoder::getType' => ['int'], 'HaruEncoder::getUnicode' => ['int', 'character'=>'int'], 'HaruEncoder::getWritingMode' => ['int'], 'HaruFont::getAscent' => ['int'], 'HaruFont::getCapHeight' => ['int'], 'HaruFont::getDescent' => ['int'], 'HaruFont::getEncodingName' => ['string'], 'HaruFont::getFontName' => ['string'], 'HaruFont::getTextWidth' => ['array', 'text'=>'string'], 'HaruFont::getUnicodeWidth' => ['int', 'character'=>'int'], 'HaruFont::getXHeight' => ['int'], 'HaruFont::measureText' => ['int', 'text'=>'string', 'width'=>'float', 'font_size'=>'float', 'char_space'=>'float', 'word_space'=>'float', 'word_wrap='=>'bool'], 'HaruImage::getBitsPerComponent' => ['int'], 'HaruImage::getColorSpace' => ['string'], 'HaruImage::getHeight' => ['int'], 'HaruImage::getSize' => ['array'], 'HaruImage::getWidth' => ['int'], 'HaruImage::setColorMask' => ['bool', 'rmin'=>'int', 'rmax'=>'int', 'gmin'=>'int', 'gmax'=>'int', 'bmin'=>'int', 'bmax'=>'int'], 'HaruImage::setMaskImage' => ['bool', 'mask_image'=>'object'], 'HaruOutline::setDestination' => ['bool', 'destination'=>'object'], 'HaruOutline::setOpened' => ['bool', 'opened'=>'bool'], 'HaruPage::arc' => ['bool', 'x'=>'float', 'y'=>'float', 'ray'=>'float', 'ang1'=>'float', 'ang2'=>'float'], 'HaruPage::beginText' => ['bool'], 'HaruPage::circle' => ['bool', 'x'=>'float', 'y'=>'float', 'ray'=>'float'], 'HaruPage::closePath' => ['bool'], 'HaruPage::concat' => ['bool', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'x'=>'float', 'y'=>'float'], 'HaruPage::createDestination' => ['object'], 'HaruPage::createLinkAnnotation' => ['object', 'rectangle'=>'array', 'destination'=>'object'], 'HaruPage::createTextAnnotation' => ['object', 'rectangle'=>'array', 'text'=>'string', 'encoder='=>'object'], 'HaruPage::createURLAnnotation' => ['object', 'rectangle'=>'array', 'url'=>'string'], 'HaruPage::curveTo' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'HaruPage::curveTo2' => ['bool', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'HaruPage::curveTo3' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x3'=>'float', 'y3'=>'float'], 'HaruPage::drawImage' => ['bool', 'image'=>'object', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'HaruPage::ellipse' => ['bool', 'x'=>'float', 'y'=>'float', 'xray'=>'float', 'yray'=>'float'], 'HaruPage::endPath' => ['bool'], 'HaruPage::endText' => ['bool'], 'HaruPage::eofill' => ['bool'], 'HaruPage::eoFillStroke' => ['bool', 'close_path='=>'bool'], 'HaruPage::fill' => ['bool'], 'HaruPage::fillStroke' => ['bool', 'close_path='=>'bool'], 'HaruPage::getCharSpace' => ['float'], 'HaruPage::getCMYKFill' => ['array'], 'HaruPage::getCMYKStroke' => ['array'], 'HaruPage::getCurrentFont' => ['object'], 'HaruPage::getCurrentFontSize' => ['float'], 'HaruPage::getCurrentPos' => ['array'], 'HaruPage::getCurrentTextPos' => ['array'], 'HaruPage::getDash' => ['array'], 'HaruPage::getFillingColorSpace' => ['int'], 'HaruPage::getFlatness' => ['float'], 'HaruPage::getGMode' => ['int'], 'HaruPage::getGrayFill' => ['float'], 'HaruPage::getGrayStroke' => ['float'], 'HaruPage::getHeight' => ['float'], 'HaruPage::getHorizontalScaling' => ['float'], 'HaruPage::getLineCap' => ['int'], 'HaruPage::getLineJoin' => ['int'], 'HaruPage::getLineWidth' => ['float'], 'HaruPage::getMiterLimit' => ['float'], 'HaruPage::getRGBFill' => ['array'], 'HaruPage::getRGBStroke' => ['array'], 'HaruPage::getStrokingColorSpace' => ['int'], 'HaruPage::getTextLeading' => ['float'], 'HaruPage::getTextMatrix' => ['array'], 'HaruPage::getTextRenderingMode' => ['int'], 'HaruPage::getTextRise' => ['float'], 'HaruPage::getTextWidth' => ['float', 'text'=>'string'], 'HaruPage::getTransMatrix' => ['array'], 'HaruPage::getWidth' => ['float'], 'HaruPage::getWordSpace' => ['float'], 'HaruPage::lineTo' => ['bool', 'x'=>'float', 'y'=>'float'], 'HaruPage::measureText' => ['int', 'text'=>'string', 'width'=>'float', 'wordwrap='=>'bool'], 'HaruPage::moveTextPos' => ['bool', 'x'=>'float', 'y'=>'float', 'set_leading='=>'bool'], 'HaruPage::moveTo' => ['bool', 'x'=>'float', 'y'=>'float'], 'HaruPage::moveToNextLine' => ['bool'], 'HaruPage::rectangle' => ['bool', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'HaruPage::setCharSpace' => ['bool', 'char_space'=>'float'], 'HaruPage::setCMYKFill' => ['bool', 'c'=>'float', 'm'=>'float', 'y'=>'float', 'k'=>'float'], 'HaruPage::setCMYKStroke' => ['bool', 'c'=>'float', 'm'=>'float', 'y'=>'float', 'k'=>'float'], 'HaruPage::setDash' => ['bool', 'pattern'=>'array', 'phase'=>'int'], 'HaruPage::setFlatness' => ['bool', 'flatness'=>'float'], 'HaruPage::setFontAndSize' => ['bool', 'font'=>'object', 'size'=>'float'], 'HaruPage::setGrayFill' => ['bool', 'value'=>'float'], 'HaruPage::setGrayStroke' => ['bool', 'value'=>'float'], 'HaruPage::setHeight' => ['bool', 'height'=>'float'], 'HaruPage::setHorizontalScaling' => ['bool', 'scaling'=>'float'], 'HaruPage::setLineCap' => ['bool', 'cap'=>'int'], 'HaruPage::setLineJoin' => ['bool', 'join'=>'int'], 'HaruPage::setLineWidth' => ['bool', 'width'=>'float'], 'HaruPage::setMiterLimit' => ['bool', 'limit'=>'float'], 'HaruPage::setRGBFill' => ['bool', 'r'=>'float', 'g'=>'float', 'b'=>'float'], 'HaruPage::setRGBStroke' => ['bool', 'r'=>'float', 'g'=>'float', 'b'=>'float'], 'HaruPage::setRotate' => ['bool', 'angle'=>'int'], 'HaruPage::setSize' => ['bool', 'size'=>'int', 'direction'=>'int'], 'HaruPage::setSlideShow' => ['bool', 'type'=>'int', 'disp_time'=>'float', 'trans_time'=>'float'], 'HaruPage::setTextLeading' => ['bool', 'text_leading'=>'float'], 'HaruPage::setTextMatrix' => ['bool', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'x'=>'float', 'y'=>'float'], 'HaruPage::setTextRenderingMode' => ['bool', 'mode'=>'int'], 'HaruPage::setTextRise' => ['bool', 'rise'=>'float'], 'HaruPage::setWidth' => ['bool', 'width'=>'float'], 'HaruPage::setWordSpace' => ['bool', 'word_space'=>'float'], 'HaruPage::showText' => ['bool', 'text'=>'string'], 'HaruPage::showTextNextLine' => ['bool', 'text'=>'string', 'word_space='=>'float', 'char_space='=>'float'], 'HaruPage::stroke' => ['bool', 'close_path='=>'bool'], 'HaruPage::textOut' => ['bool', 'x'=>'float', 'y'=>'float', 'text'=>'string'], 'HaruPage::textRect' => ['bool', 'left'=>'float', 'top'=>'float', 'right'=>'float', 'bottom'=>'float', 'text'=>'string', 'align='=>'int'], 'hash' => ['string|false', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'], 'hash_algos' => ['list'], 'hash_copy' => ['HashContext', 'context'=>'HashContext|resource'], 'hash_equals' => ['bool', 'known_string'=>'string', 'user_string'=>'string'], 'hash_file' => ['string|false', 'algo'=>'string', 'filename'=>'string', 'raw_output='=>'bool'], 'hash_final' => ['string', 'context'=>'HashContext|resource', 'raw_output='=>'bool'], 'hash_hkdf' => ['string|false', 'algo'=>'string', 'ikm'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'], 'hash_hmac' => ['string|false', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'], 'hash_hmac_algos' => ['list'], 'hash_hmac_file' => ['string|false', 'algo'=>'string', 'filename'=>'string', 'key'=>'string', 'raw_output='=>'bool'], 'hash_init' => ['HashContext|false', 'algo'=>'string', 'options='=>'int', 'key='=>'string'], 'hash_pbkdf2' => ['string|false', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'], 'hash_update' => ['bool', 'context'=>'HashContext', 'data'=>'string'], 'hash_update_file' => ['bool', 'context'=>'HashContext', 'filename'=>'string', 'scontext='=>'?HashContext'], 'hash_update_stream' => ['int', 'context'=>'HashContext', 'handle'=>'resource', 'length='=>'int'], 'hashTableObj::clear' => ['void'], 'hashTableObj::get' => ['string', 'key'=>'string'], 'hashTableObj::nextkey' => ['string', 'previousKey'=>'string'], 'hashTableObj::remove' => ['int', 'key'=>'string'], 'hashTableObj::set' => ['int', 'key'=>'string', 'value'=>'string'], 'header' => ['void', 'header'=>'string', 'replace='=>'bool', 'http_response_code='=>'int'], 'header_register_callback' => ['bool', 'callback'=>'callable():void'], 'header_remove' => ['void', 'name='=>'string'], 'headers_list' => ['list'], 'headers_sent' => ['bool', '&w_file='=>'string', '&w_line='=>'int'], 'hebrev' => ['string', 'string'=>'string', 'max_chars_per_line='=>'int'], 'hebrevc' => ['string', 'string'=>'string', 'max_chars_per_line='=>'int'], 'hex2bin' => ['string|false', 'data'=>'string'], 'hexdec' => ['int|float', 'hexadecimal_number'=>'string'], 'highlight_file' => ['string|bool', 'file_name'=>'string', 'return='=>'bool'], 'highlight_string' => ['string|bool', 'string'=>'string', 'return='=>'bool'], 'hrtime' => ['array{0:int,1:int}|false', 'get_as_number='=>'false'], 'hrtime\'1' => ['int|float|false', 'get_as_number='=>'true'], 'HRTime\PerformanceCounter::getElapsedTicks' => ['int'], 'HRTime\PerformanceCounter::getFrequency' => ['int'], 'HRTime\PerformanceCounter::getLastElapsedTicks' => ['int'], 'HRTime\PerformanceCounter::getTicks' => ['int'], 'HRTime\PerformanceCounter::getTicksSince' => ['int', 'start'=>'int'], 'HRTime\PerformanceCounter::isRunning' => ['bool'], 'HRTime\PerformanceCounter::start' => ['void'], 'HRTime\PerformanceCounter::stop' => ['void'], 'HRTime\StopWatch::getElapsedTicks' => ['int'], 'HRTime\StopWatch::getElapsedTime' => ['float', 'unit='=>'int'], 'HRTime\StopWatch::getLastElapsedTicks' => ['int'], 'HRTime\StopWatch::getLastElapsedTime' => ['float', 'unit='=>'int'], 'HRTime\StopWatch::isRunning' => ['bool'], 'HRTime\StopWatch::start' => ['void'], 'HRTime\StopWatch::stop' => ['void'], 'html_entity_decode' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string'], 'htmlentities' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string', 'double_encode='=>'bool'], 'htmlspecialchars' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string', 'double_encode='=>'bool'], 'htmlspecialchars_decode' => ['string', 'string'=>'string', 'quote_style='=>'int'], 'http\Client::__construct' => ['void', 'driver='=>'string', 'persistent_handle_id='=>'string'], 'http\Client::addCookies' => ['http\Client', 'cookies='=>'?array'], 'http\Client::addSslOptions' => ['http\Client', 'ssl_options='=>'?array'], 'http\Client::attach' => ['void', 'observer'=>'SplObserver'], 'http\Client::configure' => ['http\Client', 'settings'=>'array'], 'http\Client::count' => ['int'], 'http\Client::dequeue' => ['http\Client', 'request'=>'http\Client\Request'], 'http\Client::detach' => ['void', 'observer'=>'SplObserver'], 'http\Client::enableEvents' => ['http\Client', 'enable='=>'mixed'], 'http\Client::enablePipelining' => ['http\Client', 'enable='=>'mixed'], 'http\Client::enqueue' => ['http\Client', 'request'=>'http\Client\Request', 'callable='=>'mixed'], 'http\Client::getAvailableConfiguration' => ['array'], 'http\Client::getAvailableDrivers' => ['array'], 'http\Client::getAvailableOptions' => ['array'], 'http\Client::getCookies' => ['array'], 'http\Client::getHistory' => ['http\Message'], 'http\Client::getObservers' => ['SplObjectStorage'], 'http\Client::getOptions' => ['array'], 'http\Client::getProgressInfo' => ['null|object', 'request'=>'http\Client\Request'], 'http\Client::getResponse' => ['http\Client\Response|null', 'request='=>'?http\Client\Request'], 'http\Client::getSslOptions' => ['array'], 'http\Client::getTransferInfo' => ['object', 'request'=>'http\Client\Request'], 'http\Client::notify' => ['void', 'request='=>'?http\Client\Request'], 'http\Client::once' => ['bool'], 'http\Client::requeue' => ['http\Client', 'request'=>'http\Client\Request', 'callable='=>'mixed'], 'http\Client::reset' => ['http\Client'], 'http\Client::send' => ['http\Client'], 'http\Client::setCookies' => ['http\Client', 'cookies='=>'?array'], 'http\Client::setDebug' => ['http\Client', 'callback'=>'callable'], 'http\Client::setOptions' => ['http\Client', 'options='=>'?array'], 'http\Client::setSslOptions' => ['http\Client', 'ssl_option='=>'?array'], 'http\Client::wait' => ['bool', 'timeout='=>'mixed'], 'http\Client\Curl\User::init' => ['', 'run'=>'callable'], 'http\Client\Curl\User::once' => [''], 'http\Client\Curl\User::send' => [''], 'http\Client\Curl\User::socket' => ['', 'socket'=>'resource', 'action'=>'int'], 'http\Client\Curl\User::timer' => ['', 'timeout_ms'=>'int'], 'http\Client\Curl\User::wait' => ['', 'timeout_ms='=>'mixed'], 'http\Client\Request::__construct' => ['void', 'method='=>'mixed', 'url='=>'mixed', 'headers='=>'?array', 'body='=>'?http\Message\Body'], 'http\Client\Request::__toString' => ['string'], 'http\Client\Request::addBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Client\Request::addHeader' => ['http\Message', 'header'=>'string', 'value'=>'mixed'], 'http\Client\Request::addHeaders' => ['http\Message', 'headers'=>'array', 'append='=>'mixed'], 'http\Client\Request::addQuery' => ['http\Client\Request', 'query_data'=>'mixed'], 'http\Client\Request::addSslOptions' => ['http\Client\Request', 'ssl_options='=>'?array'], 'http\Client\Request::count' => ['int'], 'http\Client\Request::current' => ['mixed'], 'http\Client\Request::detach' => ['http\Message'], 'http\Client\Request::getBody' => ['http\Message\Body'], 'http\Client\Request::getContentType' => ['null|string'], 'http\Client\Request::getHeader' => ['http\Header|mixed', 'header'=>'string', 'into_class='=>'mixed'], 'http\Client\Request::getHeaders' => ['array'], 'http\Client\Request::getHttpVersion' => ['string'], 'http\Client\Request::getInfo' => ['null|string'], 'http\Client\Request::getOptions' => ['array'], 'http\Client\Request::getParentMessage' => ['http\Message'], 'http\Client\Request::getQuery' => ['null|string'], 'http\Client\Request::getRequestMethod' => ['false|string'], 'http\Client\Request::getRequestUrl' => ['false|string'], 'http\Client\Request::getResponseCode' => ['false|int'], 'http\Client\Request::getResponseStatus' => ['false|string'], 'http\Client\Request::getSslOptions' => ['array'], 'http\Client\Request::getType' => ['int'], 'http\Client\Request::isMultipart' => ['bool', '&boundary='=>'mixed'], 'http\Client\Request::key' => ['int|string'], 'http\Client\Request::next' => ['void'], 'http\Client\Request::prepend' => ['http\Message', 'message'=>'http\Message', 'top='=>'mixed'], 'http\Client\Request::reverse' => ['http\Message'], 'http\Client\Request::rewind' => ['void'], 'http\Client\Request::serialize' => ['string'], 'http\Client\Request::setBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Client\Request::setContentType' => ['http\Client\Request', 'content_type'=>'string'], 'http\Client\Request::setHeader' => ['http\Message', 'header'=>'string', 'value='=>'mixed'], 'http\Client\Request::setHeaders' => ['http\Message', 'headers'=>'array'], 'http\Client\Request::setHttpVersion' => ['http\Message', 'http_version'=>'string'], 'http\Client\Request::setInfo' => ['http\Message', 'http_info'=>'string'], 'http\Client\Request::setOptions' => ['http\Client\Request', 'options='=>'?array'], 'http\Client\Request::setQuery' => ['http\Client\Request', 'query_data='=>'mixed'], 'http\Client\Request::setRequestMethod' => ['http\Message', 'request_method'=>'string'], 'http\Client\Request::setRequestUrl' => ['http\Message', 'url'=>'string'], 'http\Client\Request::setResponseCode' => ['http\Message', 'response_code'=>'int', 'strict='=>'mixed'], 'http\Client\Request::setResponseStatus' => ['http\Message', 'response_status'=>'string'], 'http\Client\Request::setSslOptions' => ['http\Client\Request', 'ssl_options='=>'?array'], 'http\Client\Request::setType' => ['http\Message', 'type'=>'int'], 'http\Client\Request::splitMultipartBody' => ['http\Message'], 'http\Client\Request::toCallback' => ['http\Message', 'callback'=>'callable'], 'http\Client\Request::toStream' => ['http\Message', 'stream'=>'resource'], 'http\Client\Request::toString' => ['string', 'include_parent='=>'mixed'], 'http\Client\Request::unserialize' => ['void', 'serialized'=>'string'], 'http\Client\Request::valid' => ['bool'], 'http\Client\Response::__construct' => ['Iterator'], 'http\Client\Response::__toString' => ['string'], 'http\Client\Response::addBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Client\Response::addHeader' => ['http\Message', 'header'=>'string', 'value'=>'mixed'], 'http\Client\Response::addHeaders' => ['http\Message', 'headers'=>'array', 'append='=>'mixed'], 'http\Client\Response::count' => ['int'], 'http\Client\Response::current' => ['mixed'], 'http\Client\Response::detach' => ['http\Message'], 'http\Client\Response::getBody' => ['http\Message\Body'], 'http\Client\Response::getCookies' => ['array', 'flags='=>'mixed', 'allowed_extras='=>'mixed'], 'http\Client\Response::getHeader' => ['http\Header|mixed', 'header'=>'string', 'into_class='=>'mixed'], 'http\Client\Response::getHeaders' => ['array'], 'http\Client\Response::getHttpVersion' => ['string'], 'http\Client\Response::getInfo' => ['null|string'], 'http\Client\Response::getParentMessage' => ['http\Message'], 'http\Client\Response::getRequestMethod' => ['false|string'], 'http\Client\Response::getRequestUrl' => ['false|string'], 'http\Client\Response::getResponseCode' => ['false|int'], 'http\Client\Response::getResponseStatus' => ['false|string'], 'http\Client\Response::getTransferInfo' => ['mixed|object', 'element='=>'mixed'], 'http\Client\Response::getType' => ['int'], 'http\Client\Response::isMultipart' => ['bool', '&boundary='=>'mixed'], 'http\Client\Response::key' => ['int|string'], 'http\Client\Response::next' => ['void'], 'http\Client\Response::prepend' => ['http\Message', 'message'=>'http\Message', 'top='=>'mixed'], 'http\Client\Response::reverse' => ['http\Message'], 'http\Client\Response::rewind' => ['void'], 'http\Client\Response::serialize' => ['string'], 'http\Client\Response::setBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Client\Response::setHeader' => ['http\Message', 'header'=>'string', 'value='=>'mixed'], 'http\Client\Response::setHeaders' => ['http\Message', 'headers'=>'array'], 'http\Client\Response::setHttpVersion' => ['http\Message', 'http_version'=>'string'], 'http\Client\Response::setInfo' => ['http\Message', 'http_info'=>'string'], 'http\Client\Response::setRequestMethod' => ['http\Message', 'request_method'=>'string'], 'http\Client\Response::setRequestUrl' => ['http\Message', 'url'=>'string'], 'http\Client\Response::setResponseCode' => ['http\Message', 'response_code'=>'int', 'strict='=>'mixed'], 'http\Client\Response::setResponseStatus' => ['http\Message', 'response_status'=>'string'], 'http\Client\Response::setType' => ['http\Message', 'type'=>'int'], 'http\Client\Response::splitMultipartBody' => ['http\Message'], 'http\Client\Response::toCallback' => ['http\Message', 'callback'=>'callable'], 'http\Client\Response::toStream' => ['http\Message', 'stream'=>'resource'], 'http\Client\Response::toString' => ['string', 'include_parent='=>'mixed'], 'http\Client\Response::unserialize' => ['void', 'serialized'=>'string'], 'http\Client\Response::valid' => ['bool'], 'http\Cookie::__construct' => ['void', 'cookie_string='=>'mixed', 'parser_flags='=>'int', 'allowed_extras='=>'array'], 'http\Cookie::__toString' => ['string'], 'http\Cookie::addCookie' => ['http\Cookie', 'cookie_name'=>'string', 'cookie_value'=>'string'], 'http\Cookie::addCookies' => ['http\Cookie', 'cookies'=>'array'], 'http\Cookie::addExtra' => ['http\Cookie', 'extra_name'=>'string', 'extra_value'=>'string'], 'http\Cookie::addExtras' => ['http\Cookie', 'extras'=>'array'], 'http\Cookie::getCookie' => ['null|string', 'name'=>'string'], 'http\Cookie::getCookies' => ['array'], 'http\Cookie::getDomain' => ['string'], 'http\Cookie::getExpires' => ['int'], 'http\Cookie::getExtra' => ['string', 'name'=>'string'], 'http\Cookie::getExtras' => ['array'], 'http\Cookie::getFlags' => ['int'], 'http\Cookie::getMaxAge' => ['int'], 'http\Cookie::getPath' => ['string'], 'http\Cookie::setCookie' => ['http\Cookie', 'cookie_name'=>'string', 'cookie_value='=>'mixed'], 'http\Cookie::setCookies' => ['http\Cookie', 'cookies='=>'mixed'], 'http\Cookie::setDomain' => ['http\Cookie', 'value='=>'mixed'], 'http\Cookie::setExpires' => ['http\Cookie', 'value='=>'mixed'], 'http\Cookie::setExtra' => ['http\Cookie', 'extra_name'=>'string', 'extra_value='=>'mixed'], 'http\Cookie::setExtras' => ['http\Cookie', 'extras='=>'mixed'], 'http\Cookie::setFlags' => ['http\Cookie', 'value='=>'mixed'], 'http\Cookie::setMaxAge' => ['http\Cookie', 'value='=>'mixed'], 'http\Cookie::setPath' => ['http\Cookie', 'value='=>'mixed'], 'http\Cookie::toArray' => ['array'], 'http\Cookie::toString' => ['string'], 'http\Encoding\Stream::__construct' => ['void', 'flags='=>'mixed'], 'http\Encoding\Stream::done' => ['bool'], 'http\Encoding\Stream::finish' => ['string'], 'http\Encoding\Stream::flush' => ['string'], 'http\Encoding\Stream::update' => ['string', 'data'=>'string'], 'http\Encoding\Stream\Debrotli::__construct' => ['void', 'flags='=>'int'], 'http\Encoding\Stream\Debrotli::decode' => ['string', 'data'=>'string'], 'http\Encoding\Stream\Debrotli::done' => ['bool'], 'http\Encoding\Stream\Debrotli::finish' => ['string'], 'http\Encoding\Stream\Debrotli::flush' => ['string'], 'http\Encoding\Stream\Debrotli::update' => ['string', 'data'=>'string'], 'http\Encoding\Stream\Dechunk::__construct' => ['void', 'flags='=>'mixed'], 'http\Encoding\Stream\Dechunk::decode' => ['false|string', 'data'=>'string', '&decoded_len='=>'mixed'], 'http\Encoding\Stream\Dechunk::done' => ['bool'], 'http\Encoding\Stream\Dechunk::finish' => ['string'], 'http\Encoding\Stream\Dechunk::flush' => ['string'], 'http\Encoding\Stream\Dechunk::update' => ['string', 'data'=>'string'], 'http\Encoding\Stream\Deflate::__construct' => ['void', 'flags='=>'mixed'], 'http\Encoding\Stream\Deflate::done' => ['bool'], 'http\Encoding\Stream\Deflate::encode' => ['string', 'data'=>'string', 'flags='=>'mixed'], 'http\Encoding\Stream\Deflate::finish' => ['string'], 'http\Encoding\Stream\Deflate::flush' => ['string'], 'http\Encoding\Stream\Deflate::update' => ['string', 'data'=>'string'], 'http\Encoding\Stream\Enbrotli::__construct' => ['void', 'flags='=>'int'], 'http\Encoding\Stream\Enbrotli::done' => ['bool'], 'http\Encoding\Stream\Enbrotli::encode' => ['string', 'data'=>'string', 'flags='=>'int'], 'http\Encoding\Stream\Enbrotli::finish' => ['string'], 'http\Encoding\Stream\Enbrotli::flush' => ['string'], 'http\Encoding\Stream\Enbrotli::update' => ['string', 'data'=>'string'], 'http\Encoding\Stream\Inflate::__construct' => ['void', 'flags='=>'mixed'], 'http\Encoding\Stream\Inflate::decode' => ['string', 'data'=>'string'], 'http\Encoding\Stream\Inflate::done' => ['bool'], 'http\Encoding\Stream\Inflate::finish' => ['string'], 'http\Encoding\Stream\Inflate::flush' => ['string'], 'http\Encoding\Stream\Inflate::update' => ['string', 'data'=>'string'], 'http\Env::getRequestBody' => ['http\Message\Body', 'body_class_name='=>'mixed'], 'http\Env::getRequestHeader' => ['array|null|string', 'header_name='=>'mixed'], 'http\Env::getResponseCode' => ['int'], 'http\Env::getResponseHeader' => ['array|null|string', 'header_name='=>'mixed'], 'http\Env::getResponseStatusForAllCodes' => ['array'], 'http\Env::getResponseStatusForCode' => ['string', 'code'=>'int'], 'http\Env::negotiate' => ['null|string', 'params'=>'string', 'supported'=>'array', 'primary_type_separator='=>'mixed', '&result_array='=>'mixed'], 'http\Env::negotiateCharset' => ['null|string', 'supported'=>'array', '&result_array='=>'mixed'], 'http\Env::negotiateContentType' => ['null|string', 'supported'=>'array', '&result_array='=>'mixed'], 'http\Env::negotiateEncoding' => ['null|string', 'supported'=>'array', '&result_array='=>'mixed'], 'http\Env::negotiateLanguage' => ['null|string', 'supported'=>'array', '&result_array='=>'mixed'], 'http\Env::setResponseCode' => ['bool', 'code'=>'int'], 'http\Env::setResponseHeader' => ['bool', 'header_name'=>'string', 'header_value='=>'mixed', 'response_code='=>'mixed', 'replace_header='=>'mixed'], 'http\Env\Request::__construct' => ['void'], 'http\Env\Request::__toString' => ['string'], 'http\Env\Request::addBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Env\Request::addHeader' => ['http\Message', 'header'=>'string', 'value'=>'mixed'], 'http\Env\Request::addHeaders' => ['http\Message', 'headers'=>'array', 'append='=>'mixed'], 'http\Env\Request::count' => ['int'], 'http\Env\Request::current' => ['mixed'], 'http\Env\Request::detach' => ['http\Message'], 'http\Env\Request::getBody' => ['http\Message\Body'], 'http\Env\Request::getCookie' => ['mixed', 'name='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool'], 'http\Env\Request::getFiles' => ['array'], 'http\Env\Request::getForm' => ['mixed', 'name='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool'], 'http\Env\Request::getHeader' => ['http\Header|mixed', 'header'=>'string', 'into_class='=>'mixed'], 'http\Env\Request::getHeaders' => ['array'], 'http\Env\Request::getHttpVersion' => ['string'], 'http\Env\Request::getInfo' => ['null|string'], 'http\Env\Request::getParentMessage' => ['http\Message'], 'http\Env\Request::getQuery' => ['mixed', 'name='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool'], 'http\Env\Request::getRequestMethod' => ['false|string'], 'http\Env\Request::getRequestUrl' => ['false|string'], 'http\Env\Request::getResponseCode' => ['false|int'], 'http\Env\Request::getResponseStatus' => ['false|string'], 'http\Env\Request::getType' => ['int'], 'http\Env\Request::isMultipart' => ['bool', '&boundary='=>'mixed'], 'http\Env\Request::key' => ['int|string'], 'http\Env\Request::next' => ['void'], 'http\Env\Request::prepend' => ['http\Message', 'message'=>'http\Message', 'top='=>'mixed'], 'http\Env\Request::reverse' => ['http\Message'], 'http\Env\Request::rewind' => ['void'], 'http\Env\Request::serialize' => ['string'], 'http\Env\Request::setBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Env\Request::setHeader' => ['http\Message', 'header'=>'string', 'value='=>'mixed'], 'http\Env\Request::setHeaders' => ['http\Message', 'headers'=>'array'], 'http\Env\Request::setHttpVersion' => ['http\Message', 'http_version'=>'string'], 'http\Env\Request::setInfo' => ['http\Message', 'http_info'=>'string'], 'http\Env\Request::setRequestMethod' => ['http\Message', 'request_method'=>'string'], 'http\Env\Request::setRequestUrl' => ['http\Message', 'url'=>'string'], 'http\Env\Request::setResponseCode' => ['http\Message', 'response_code'=>'int', 'strict='=>'mixed'], 'http\Env\Request::setResponseStatus' => ['http\Message', 'response_status'=>'string'], 'http\Env\Request::setType' => ['http\Message', 'type'=>'int'], 'http\Env\Request::splitMultipartBody' => ['http\Message'], 'http\Env\Request::toCallback' => ['http\Message', 'callback'=>'callable'], 'http\Env\Request::toStream' => ['http\Message', 'stream'=>'resource'], 'http\Env\Request::toString' => ['string', 'include_parent='=>'mixed'], 'http\Env\Request::unserialize' => ['void', 'serialized'=>'string'], 'http\Env\Request::valid' => ['bool'], 'http\Env\Response::__construct' => ['void'], 'http\Env\Response::__invoke' => ['bool', 'data'=>'string', 'ob_flags='=>'int'], 'http\Env\Response::__toString' => ['string'], 'http\Env\Response::addBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Env\Response::addHeader' => ['http\Message', 'header'=>'string', 'value'=>'mixed'], 'http\Env\Response::addHeaders' => ['http\Message', 'headers'=>'array', 'append='=>'mixed'], 'http\Env\Response::count' => ['int'], 'http\Env\Response::current' => ['mixed'], 'http\Env\Response::detach' => ['http\Message'], 'http\Env\Response::getBody' => ['http\Message\Body'], 'http\Env\Response::getHeader' => ['http\Header|mixed', 'header'=>'string', 'into_class='=>'mixed'], 'http\Env\Response::getHeaders' => ['array'], 'http\Env\Response::getHttpVersion' => ['string'], 'http\Env\Response::getInfo' => ['?string'], 'http\Env\Response::getParentMessage' => ['http\Message'], 'http\Env\Response::getRequestMethod' => ['false|string'], 'http\Env\Response::getRequestUrl' => ['false|string'], 'http\Env\Response::getResponseCode' => ['false|int'], 'http\Env\Response::getResponseStatus' => ['false|string'], 'http\Env\Response::getType' => ['int'], 'http\Env\Response::isCachedByETag' => ['int', 'header_name='=>'string'], 'http\Env\Response::isCachedByLastModified' => ['int', 'header_name='=>'string'], 'http\Env\Response::isMultipart' => ['bool', '&boundary='=>'mixed'], 'http\Env\Response::key' => ['int|string'], 'http\Env\Response::next' => ['void'], 'http\Env\Response::prepend' => ['http\Message', 'message'=>'http\Message', 'top='=>'mixed'], 'http\Env\Response::reverse' => ['http\Message'], 'http\Env\Response::rewind' => ['void'], 'http\Env\Response::send' => ['bool', 'stream='=>'resource'], 'http\Env\Response::serialize' => ['string'], 'http\Env\Response::setBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Env\Response::setCacheControl' => ['http\Env\Response', 'cache_control'=>'string'], 'http\Env\Response::setContentDisposition' => ['http\Env\Response', 'disposition_params'=>'array'], 'http\Env\Response::setContentEncoding' => ['http\Env\Response', 'content_encoding'=>'int'], 'http\Env\Response::setContentType' => ['http\Env\Response', 'content_type'=>'string'], 'http\Env\Response::setCookie' => ['http\Env\Response', 'cookie'=>'mixed'], 'http\Env\Response::setEnvRequest' => ['http\Env\Response', 'env_request'=>'http\Message'], 'http\Env\Response::setEtag' => ['http\Env\Response', 'etag'=>'string'], 'http\Env\Response::setHeader' => ['http\Message', 'header'=>'string', 'value='=>'mixed'], 'http\Env\Response::setHeaders' => ['http\Message', 'headers'=>'array'], 'http\Env\Response::setHttpVersion' => ['http\Message', 'http_version'=>'string'], 'http\Env\Response::setInfo' => ['http\Message', 'http_info'=>'string'], 'http\Env\Response::setLastModified' => ['http\Env\Response', 'last_modified'=>'int'], 'http\Env\Response::setRequestMethod' => ['http\Message', 'request_method'=>'string'], 'http\Env\Response::setRequestUrl' => ['http\Message', 'url'=>'string'], 'http\Env\Response::setResponseCode' => ['http\Message', 'response_code'=>'int', 'strict='=>'mixed'], 'http\Env\Response::setResponseStatus' => ['http\Message', 'response_status'=>'string'], 'http\Env\Response::setThrottleRate' => ['http\Env\Response', 'chunk_size'=>'int', 'delay='=>'float|int'], 'http\Env\Response::setType' => ['http\Message', 'type'=>'int'], 'http\Env\Response::splitMultipartBody' => ['http\Message'], 'http\Env\Response::toCallback' => ['http\Message', 'callback'=>'callable'], 'http\Env\Response::toStream' => ['http\Message', 'stream'=>'resource'], 'http\Env\Response::toString' => ['string', 'include_parent='=>'mixed'], 'http\Env\Response::unserialize' => ['void', 'serialized'=>'string'], 'http\Env\Response::valid' => ['bool'], 'http\Header::__construct' => ['void', 'name='=>'mixed', 'value='=>'mixed'], 'http\Header::__toString' => ['string'], 'http\Header::getParams' => ['http\Params', 'param_sep='=>'mixed', 'arg_sep='=>'mixed', 'val_sep='=>'mixed', 'flags='=>'mixed'], 'http\Header::match' => ['bool', 'value'=>'string', 'flags='=>'mixed'], 'http\Header::negotiate' => ['null|string', 'supported'=>'array', '&result='=>'mixed'], 'http\Header::parse' => ['array|false', 'string'=>'string', 'header_class='=>'mixed'], 'http\Header::serialize' => ['string'], 'http\Header::toString' => ['string'], 'http\Header::unserialize' => ['void', 'serialized'=>'string'], 'http\Header\Parser::getState' => ['int'], 'http\Header\Parser::parse' => ['int', 'data'=>'string', 'flags'=>'int', '&headers'=>'array'], 'http\Header\Parser::stream' => ['int', 'stream'=>'resource', 'flags'=>'int', '&headers'=>'array'], 'http\Message::__construct' => ['void', 'message='=>'mixed', 'greedy='=>'bool'], 'http\Message::__toString' => ['string'], 'http\Message::addBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Message::addHeader' => ['http\Message', 'header'=>'string', 'value'=>'mixed'], 'http\Message::addHeaders' => ['http\Message', 'headers'=>'array', 'append='=>'mixed'], 'http\Message::count' => ['int'], 'http\Message::current' => ['mixed'], 'http\Message::detach' => ['http\Message'], 'http\Message::getBody' => ['http\Message\Body'], 'http\Message::getHeader' => ['http\Header|mixed', 'header'=>'string', 'into_class='=>'mixed'], 'http\Message::getHeaders' => ['array'], 'http\Message::getHttpVersion' => ['string'], 'http\Message::getInfo' => ['null|string'], 'http\Message::getParentMessage' => ['http\Message'], 'http\Message::getRequestMethod' => ['false|string'], 'http\Message::getRequestUrl' => ['false|string'], 'http\Message::getResponseCode' => ['false|int'], 'http\Message::getResponseStatus' => ['false|string'], 'http\Message::getType' => ['int'], 'http\Message::isMultipart' => ['bool', '&boundary='=>'mixed'], 'http\Message::key' => ['int|string'], 'http\Message::next' => ['void'], 'http\Message::prepend' => ['http\Message', 'message'=>'http\Message', 'top='=>'mixed'], 'http\Message::reverse' => ['http\Message'], 'http\Message::rewind' => ['void'], 'http\Message::serialize' => ['string'], 'http\Message::setBody' => ['http\Message', 'body'=>'http\Message\Body'], 'http\Message::setHeader' => ['http\Message', 'header'=>'string', 'value='=>'mixed'], 'http\Message::setHeaders' => ['http\Message', 'headers'=>'array'], 'http\Message::setHttpVersion' => ['http\Message', 'http_version'=>'string'], 'http\Message::setInfo' => ['http\Message', 'http_info'=>'string'], 'http\Message::setRequestMethod' => ['http\Message', 'request_method'=>'string'], 'http\Message::setRequestUrl' => ['http\Message', 'url'=>'string'], 'http\Message::setResponseCode' => ['http\Message', 'response_code'=>'int', 'strict='=>'mixed'], 'http\Message::setResponseStatus' => ['http\Message', 'response_status'=>'string'], 'http\Message::setType' => ['http\Message', 'type'=>'int'], 'http\Message::splitMultipartBody' => ['http\Message'], 'http\Message::toCallback' => ['http\Message', 'callback'=>'callable'], 'http\Message::toStream' => ['http\Message', 'stream'=>'resource'], 'http\Message::toString' => ['string', 'include_parent='=>'mixed'], 'http\Message::unserialize' => ['void', 'serialized'=>'string'], 'http\Message::valid' => ['bool'], 'http\Message\Body::__construct' => ['void', 'stream='=>'resource'], 'http\Message\Body::__toString' => ['string'], 'http\Message\Body::addForm' => ['http\Message\Body', 'fields='=>'?array', 'files='=>'?array'], 'http\Message\Body::addPart' => ['http\Message\Body', 'message'=>'http\Message'], 'http\Message\Body::append' => ['http\Message\Body', 'string'=>'string'], 'http\Message\Body::etag' => ['false|string'], 'http\Message\Body::getBoundary' => ['null|string'], 'http\Message\Body::getResource' => ['resource'], 'http\Message\Body::serialize' => ['string'], 'http\Message\Body::stat' => ['int|object', 'field='=>'mixed'], 'http\Message\Body::toCallback' => ['http\Message\Body', 'callback'=>'callable', 'offset='=>'mixed', 'maxlen='=>'mixed'], 'http\Message\Body::toStream' => ['http\Message\Body', 'stream'=>'resource', 'offset='=>'mixed', 'maxlen='=>'mixed'], 'http\Message\Body::toString' => ['string'], 'http\Message\Body::unserialize' => ['void', 'serialized'=>'string'], 'http\Message\Parser::getState' => ['int'], 'http\Message\Parser::parse' => ['int', 'data'=>'string', 'flags'=>'int', '&message'=>'http\Message'], '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::toArray' => ['array'], 'http\Params::toString' => ['string'], 'http\QueryString::__construct' => ['void', 'querystring'=>'string'], 'http\QueryString::__toString' => ['string'], 'http\QueryString::get' => ['http\QueryString|string|mixed', 'name='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getArray' => ['array|mixed', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getBool' => ['bool|mixed', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getFloat' => ['float|mixed', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getGlobalInstance' => ['http\QueryString'], 'http\QueryString::getInt' => ['int|mixed', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getIterator' => ['IteratorAggregate'], '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::serialize' => ['string'], 'http\QueryString::set' => ['http\QueryString', 'params'=>'mixed'], 'http\QueryString::toArray' => ['array'], 'http\QueryString::toString' => ['string'], 'http\QueryString::unserialize' => ['void', 'serialized'=>'string'], 'http\QueryString::xlate' => ['http\QueryString'], 'http\Url::__construct' => ['void', 'old_url='=>'mixed', 'new_url='=>'mixed', 'flags='=>'int'], 'http\Url::__toString' => ['string'], 'http\Url::mod' => ['http\Url', 'parts'=>'mixed', 'flags='=>'float|int|mixed'], 'http\Url::toArray' => ['string[]'], 'http\Url::toString' => ['string'], 'http_build_cookie' => ['string', 'cookie'=>'array'], 'http_build_query' => ['string', 'querydata'=>'array|object', 'prefix='=>'string', 'arg_separator='=>'string', 'enc_type='=>'int'], 'http_build_str' => ['string', 'query'=>'array', 'prefix='=>'?string', 'arg_separator='=>'string'], 'http_build_url' => ['string', 'url='=>'string|array', 'parts='=>'string|array', 'flags='=>'int', 'new_url='=>'array'], 'http_cache_etag' => ['bool', 'etag='=>'string'], 'http_cache_last_modified' => ['bool', 'timestamp_or_expires='=>'int'], 'http_chunked_decode' => ['string|false', 'encoded'=>'string'], 'http_date' => ['string', 'timestamp='=>'int'], 'http_deflate' => ['?string', 'data'=>'string', 'flags='=>'int'], 'http_get' => ['string', 'url'=>'string', 'options='=>'array', 'info='=>'array'], 'http_get_request_body' => ['?string'], 'http_get_request_body_stream' => ['?resource'], 'http_get_request_headers' => ['array'], 'http_head' => ['string', 'url'=>'string', 'options='=>'array', 'info='=>'array'], 'http_inflate' => ['?string', 'data'=>'string'], 'http_match_etag' => ['bool', 'etag'=>'string', 'for_range='=>'bool'], 'http_match_modified' => ['bool', 'timestamp='=>'int', 'for_range='=>'bool'], 'http_match_request_header' => ['bool', 'header'=>'string', 'value'=>'string', 'match_case='=>'bool'], 'http_negotiate_charset' => ['string', 'supported'=>'array', 'result='=>'array'], 'http_negotiate_content_type' => ['string', 'supported'=>'array', 'result='=>'array'], 'http_negotiate_language' => ['string', 'supported'=>'array', 'result='=>'array'], 'http_parse_cookie' => ['stdClass|false', 'cookie'=>'string', 'flags='=>'int', 'allowed_extras='=>'array'], 'http_parse_headers' => ['array|false', 'header'=>'string'], 'http_parse_message' => ['object', 'message'=>'string'], 'http_parse_params' => ['stdClass', 'param'=>'string', 'flags='=>'int'], 'http_persistent_handles_clean' => ['string', 'ident='=>'string'], 'http_persistent_handles_count' => ['stdClass|false'], 'http_persistent_handles_ident' => ['string|false', 'ident='=>'string'], 'http_post_data' => ['string', 'url'=>'string', 'data'=>'string', 'options='=>'array', 'info='=>'array'], 'http_post_fields' => ['string', 'url'=>'string', 'data'=>'array', 'files='=>'array', 'options='=>'array', 'info='=>'array'], 'http_put_data' => ['string', 'url'=>'string', 'data'=>'string', 'options='=>'array', 'info='=>'array'], 'http_put_file' => ['string', 'url'=>'string', 'file'=>'string', 'options='=>'array', 'info='=>'array'], 'http_put_stream' => ['string', 'url'=>'string', 'stream'=>'resource', 'options='=>'array', 'info='=>'array'], 'http_redirect' => ['int|false', 'url='=>'string', 'params='=>'array', 'session='=>'bool', 'status='=>'int'], 'http_request' => ['string', 'method'=>'int', 'url'=>'string', 'body='=>'string', 'options='=>'array', 'info='=>'array'], 'http_request_body_encode' => ['string|false', 'fields'=>'array', 'files'=>'array'], 'http_request_method_exists' => ['bool', 'method'=>'mixed'], 'http_request_method_name' => ['string|false', 'method'=>'int'], 'http_request_method_register' => ['int|false', 'method'=>'string'], 'http_request_method_unregister' => ['bool', 'method'=>'mixed'], 'http_response_code' => ['int|bool', 'response_code='=>'int'], 'http_send_content_disposition' => ['bool', 'filename'=>'string', 'inline='=>'bool'], 'http_send_content_type' => ['bool', 'content_type='=>'string'], 'http_send_data' => ['bool', 'data'=>'string'], 'http_send_file' => ['bool', 'file'=>'string'], 'http_send_last_modified' => ['bool', 'timestamp='=>'int'], 'http_send_status' => ['bool', 'status'=>'int'], 'http_send_stream' => ['bool', 'stream'=>'resource'], 'http_support' => ['int', 'feature='=>'int'], 'http_throttle' => ['void', 'sec'=>'float', 'bytes='=>'int'], 'HttpDeflateStream::__construct' => ['void', 'flags='=>'int'], 'HttpDeflateStream::factory' => ['HttpDeflateStream', 'flags='=>'int', 'class_name='=>'string'], 'HttpDeflateStream::finish' => ['string', 'data='=>'string'], 'HttpDeflateStream::flush' => ['string|false', 'data='=>'string'], 'HttpDeflateStream::update' => ['string|false', 'data'=>'string'], 'HttpInflateStream::__construct' => ['void', 'flags='=>'int'], 'HttpInflateStream::factory' => ['HttpInflateStream', 'flags='=>'int', 'class_name='=>'string'], 'HttpInflateStream::finish' => ['string', 'data='=>'string'], 'HttpInflateStream::flush' => ['string|false', 'data='=>'string'], 'HttpInflateStream::update' => ['string|false', 'data'=>'string'], 'HttpMessage::__construct' => ['void', 'message='=>'string'], 'HttpMessage::__toString' => ['string'], 'HttpMessage::addHeaders' => ['void', 'headers'=>'array', 'append='=>'bool'], 'HttpMessage::count' => ['int'], 'HttpMessage::current' => ['mixed'], 'HttpMessage::detach' => ['HttpMessage'], 'HttpMessage::factory' => ['?HttpMessage', 'raw_message='=>'string', 'class_name='=>'string'], 'HttpMessage::fromEnv' => ['?HttpMessage', 'message_type'=>'int', 'class_name='=>'string'], 'HttpMessage::fromString' => ['?HttpMessage', 'raw_message='=>'string', 'class_name='=>'string'], 'HttpMessage::getBody' => ['string'], 'HttpMessage::getHeader' => ['?string', 'header'=>'string'], 'HttpMessage::getHeaders' => ['array'], 'HttpMessage::getHttpVersion' => ['string'], 'HttpMessage::getInfo' => [''], 'HttpMessage::getParentMessage' => ['HttpMessage'], 'HttpMessage::getRequestMethod' => ['string|false'], 'HttpMessage::getRequestUrl' => ['string|false'], 'HttpMessage::getResponseCode' => ['int'], 'HttpMessage::getResponseStatus' => ['string'], 'HttpMessage::getType' => ['int'], 'HttpMessage::guessContentType' => ['string|false', 'magic_file'=>'string', 'magic_mode='=>'int'], 'HttpMessage::key' => ['int|string'], 'HttpMessage::next' => ['void'], 'HttpMessage::prepend' => ['void', 'message'=>'HttpMessage', 'top='=>'bool'], 'HttpMessage::reverse' => ['HttpMessage'], 'HttpMessage::rewind' => ['void'], 'HttpMessage::send' => ['bool'], 'HttpMessage::serialize' => ['string'], 'HttpMessage::setBody' => ['void', 'body'=>'string'], 'HttpMessage::setHeaders' => ['void', 'headers'=>'array'], 'HttpMessage::setHttpVersion' => ['bool', 'version'=>'string'], 'HttpMessage::setInfo' => ['', 'http_info'=>''], 'HttpMessage::setRequestMethod' => ['bool', 'method'=>'string'], 'HttpMessage::setRequestUrl' => ['bool', 'url'=>'string'], 'HttpMessage::setResponseCode' => ['bool', 'code'=>'int'], 'HttpMessage::setResponseStatus' => ['bool', 'status'=>'string'], 'HttpMessage::setType' => ['void', 'type'=>'int'], 'HttpMessage::toMessageTypeObject' => ['HttpRequest|HttpResponse|null'], 'HttpMessage::toString' => ['string', 'include_parent='=>'bool'], 'HttpMessage::unserialize' => ['void', 'serialized'=>'string'], 'HttpMessage::valid' => ['bool'], 'HttpQueryString::__construct' => ['void', 'global='=>'bool', 'add='=>'mixed'], 'HttpQueryString::__toString' => ['string'], 'HttpQueryString::factory' => ['', 'global'=>'', 'params'=>'', 'class_name'=>''], 'HttpQueryString::get' => ['mixed', 'key='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool'], 'HttpQueryString::getArray' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getBool' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getFloat' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getInt' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], '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::serialize' => ['string'], 'HttpQueryString::set' => ['string', 'params'=>'mixed'], 'HttpQueryString::singleton' => ['HttpQueryString', 'global='=>'bool'], 'HttpQueryString::toArray' => ['array'], 'HttpQueryString::toString' => ['string'], 'HttpQueryString::unserialize' => ['void', 'serialized'=>'string'], 'HttpQueryString::xlate' => ['bool', 'ie'=>'string', 'oe'=>'string'], 'HttpRequest::__construct' => ['void', 'url='=>'string', 'request_method='=>'int', 'options='=>'array'], 'HttpRequest::addBody' => ['', 'request_body_data'=>''], 'HttpRequest::addCookies' => ['bool', 'cookies'=>'array'], 'HttpRequest::addHeaders' => ['bool', 'headers'=>'array'], 'HttpRequest::addPostFields' => ['bool', 'post_data'=>'array'], 'HttpRequest::addPostFile' => ['bool', 'name'=>'string', 'file'=>'string', 'content_type='=>'string'], 'HttpRequest::addPutData' => ['bool', 'put_data'=>'string'], 'HttpRequest::addQueryData' => ['bool', 'query_params'=>'array'], 'HttpRequest::addRawPostData' => ['bool', 'raw_post_data'=>'string'], 'HttpRequest::addSslOptions' => ['bool', 'options'=>'array'], 'HttpRequest::clearHistory' => ['void'], 'HttpRequest::enableCookies' => ['bool'], 'HttpRequest::encodeBody' => ['', 'fields'=>'', 'files'=>''], 'HttpRequest::factory' => ['', 'url'=>'', 'method'=>'', 'options'=>'', 'class_name'=>''], 'HttpRequest::flushCookies' => [''], 'HttpRequest::get' => ['', 'url'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::getBody' => [''], 'HttpRequest::getContentType' => ['string'], 'HttpRequest::getCookies' => ['array'], 'HttpRequest::getHeaders' => ['array'], 'HttpRequest::getHistory' => ['HttpMessage'], 'HttpRequest::getMethod' => ['int'], 'HttpRequest::getOptions' => ['array'], 'HttpRequest::getPostFields' => ['array'], 'HttpRequest::getPostFiles' => ['array'], 'HttpRequest::getPutData' => ['string'], 'HttpRequest::getPutFile' => ['string'], 'HttpRequest::getQueryData' => ['string'], 'HttpRequest::getRawPostData' => ['string'], 'HttpRequest::getRawRequestMessage' => ['string'], 'HttpRequest::getRawResponseMessage' => ['string'], 'HttpRequest::getRequestMessage' => ['HttpMessage'], 'HttpRequest::getResponseBody' => ['string'], 'HttpRequest::getResponseCode' => ['int'], 'HttpRequest::getResponseCookies' => ['stdClass[]', 'flags='=>'int', 'allowed_extras='=>'array'], 'HttpRequest::getResponseData' => ['array'], 'HttpRequest::getResponseHeader' => ['mixed', 'name='=>'string'], 'HttpRequest::getResponseInfo' => ['mixed', 'name='=>'string'], 'HttpRequest::getResponseMessage' => ['HttpMessage'], 'HttpRequest::getResponseStatus' => ['string'], 'HttpRequest::getSslOptions' => ['array'], 'HttpRequest::getUrl' => ['string'], 'HttpRequest::head' => ['', 'url'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::methodExists' => ['', 'method'=>''], 'HttpRequest::methodName' => ['', 'method_id'=>''], 'HttpRequest::methodRegister' => ['', 'method_name'=>''], 'HttpRequest::methodUnregister' => ['', 'method'=>''], 'HttpRequest::postData' => ['', 'url'=>'', 'data'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::postFields' => ['', 'url'=>'', 'data'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::putData' => ['', 'url'=>'', 'data'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::putFile' => ['', 'url'=>'', 'file'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::putStream' => ['', 'url'=>'', 'stream'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::resetCookies' => ['bool', 'session_only='=>'bool'], 'HttpRequest::send' => ['HttpMessage'], 'HttpRequest::setBody' => ['bool', 'request_body_data='=>'string'], 'HttpRequest::setContentType' => ['bool', 'content_type'=>'string'], 'HttpRequest::setCookies' => ['bool', 'cookies='=>'array'], 'HttpRequest::setHeaders' => ['bool', 'headers='=>'array'], 'HttpRequest::setMethod' => ['bool', 'request_method'=>'int'], 'HttpRequest::setOptions' => ['bool', 'options='=>'array'], 'HttpRequest::setPostFields' => ['bool', 'post_data'=>'array'], 'HttpRequest::setPostFiles' => ['bool', 'post_files'=>'array'], 'HttpRequest::setPutData' => ['bool', 'put_data='=>'string'], 'HttpRequest::setPutFile' => ['bool', 'file='=>'string'], 'HttpRequest::setQueryData' => ['bool', 'query_data'=>'mixed'], 'HttpRequest::setRawPostData' => ['bool', 'raw_post_data='=>'string'], 'HttpRequest::setSslOptions' => ['bool', 'options='=>'array'], 'HttpRequest::setUrl' => ['bool', 'url'=>'string'], 'HttpRequestDataShare::__construct' => ['void'], 'HttpRequestDataShare::__destruct' => ['void'], 'HttpRequestDataShare::attach' => ['', 'request'=>'HttpRequest'], 'HttpRequestDataShare::count' => ['int'], 'HttpRequestDataShare::detach' => ['', 'request'=>'HttpRequest'], 'HttpRequestDataShare::factory' => ['', 'global'=>'', 'class_name'=>''], 'HttpRequestDataShare::reset' => [''], 'HttpRequestDataShare::singleton' => ['', 'global'=>''], 'HttpRequestPool::__construct' => ['void', 'request='=>'HttpRequest'], 'HttpRequestPool::__destruct' => ['void'], 'HttpRequestPool::attach' => ['bool', 'request'=>'HttpRequest'], 'HttpRequestPool::count' => ['int'], 'HttpRequestPool::current' => ['mixed'], 'HttpRequestPool::detach' => ['bool', 'request'=>'HttpRequest'], 'HttpRequestPool::enableEvents' => ['', 'enable'=>''], 'HttpRequestPool::enablePipelining' => ['', 'enable'=>''], 'HttpRequestPool::getAttachedRequests' => ['array'], 'HttpRequestPool::getFinishedRequests' => ['array'], 'HttpRequestPool::key' => ['int|string'], 'HttpRequestPool::next' => ['void'], 'HttpRequestPool::reset' => ['void'], 'HttpRequestPool::rewind' => ['void'], 'HttpRequestPool::send' => ['bool'], 'HttpRequestPool::socketPerform' => ['bool'], 'HttpRequestPool::socketSelect' => ['bool', 'timeout='=>'float'], 'HttpRequestPool::valid' => ['bool'], 'HttpResponse::capture' => ['void'], 'HttpResponse::getBufferSize' => ['int'], 'HttpResponse::getCache' => ['bool'], 'HttpResponse::getCacheControl' => ['string'], 'HttpResponse::getContentDisposition' => ['string'], 'HttpResponse::getContentType' => ['string'], 'HttpResponse::getData' => ['string'], 'HttpResponse::getETag' => ['string'], 'HttpResponse::getFile' => ['string'], 'HttpResponse::getGzip' => ['bool'], 'HttpResponse::getHeader' => ['mixed', 'name='=>'string'], 'HttpResponse::getLastModified' => ['int'], 'HttpResponse::getRequestBody' => ['string'], 'HttpResponse::getRequestBodyStream' => ['resource'], 'HttpResponse::getRequestHeaders' => ['array'], 'HttpResponse::getStream' => ['resource'], 'HttpResponse::getThrottleDelay' => ['float'], 'HttpResponse::guessContentType' => ['string|false', 'magic_file'=>'string', 'magic_mode='=>'int'], 'HttpResponse::redirect' => ['void', 'url='=>'string', 'params='=>'array', 'session='=>'bool', 'status='=>'int'], 'HttpResponse::send' => ['bool', 'clean_ob='=>'bool'], 'HttpResponse::setBufferSize' => ['bool', 'bytes'=>'int'], 'HttpResponse::setCache' => ['bool', 'cache'=>'bool'], 'HttpResponse::setCacheControl' => ['bool', 'control'=>'string', 'max_age='=>'int', 'must_revalidate='=>'bool'], 'HttpResponse::setContentDisposition' => ['bool', 'filename'=>'string', 'inline='=>'bool'], 'HttpResponse::setContentType' => ['bool', 'content_type'=>'string'], 'HttpResponse::setData' => ['bool', 'data'=>'mixed'], 'HttpResponse::setETag' => ['bool', 'etag'=>'string'], 'HttpResponse::setFile' => ['bool', 'file'=>'string'], 'HttpResponse::setGzip' => ['bool', 'gzip'=>'bool'], 'HttpResponse::setHeader' => ['bool', 'name'=>'string', 'value='=>'mixed', 'replace='=>'bool'], 'HttpResponse::setLastModified' => ['bool', 'timestamp'=>'int'], 'HttpResponse::setStream' => ['bool', 'stream'=>'resource'], 'HttpResponse::setThrottleDelay' => ['bool', 'seconds'=>'float'], 'HttpResponse::status' => ['bool', 'status'=>'int'], 'HttpUtil::buildCookie' => ['', 'cookie_array'=>''], 'HttpUtil::buildStr' => ['', 'query'=>'', 'prefix'=>'', 'arg_sep'=>''], 'HttpUtil::buildUrl' => ['', 'url'=>'', 'parts'=>'', 'flags'=>'', '&composed'=>''], 'HttpUtil::chunkedDecode' => ['', 'encoded_string'=>''], 'HttpUtil::date' => ['', 'timestamp'=>''], 'HttpUtil::deflate' => ['', 'plain'=>'', 'flags'=>''], 'HttpUtil::inflate' => ['', 'encoded'=>''], 'HttpUtil::matchEtag' => ['', 'plain_etag'=>'', 'for_range'=>''], 'HttpUtil::matchModified' => ['', 'last_modified'=>'', 'for_range'=>''], 'HttpUtil::matchRequestHeader' => ['', 'header_name'=>'', 'header_value'=>'', 'case_sensitive'=>''], 'HttpUtil::negotiateCharset' => ['', 'supported'=>'', '&result'=>''], 'HttpUtil::negotiateContentType' => ['', 'supported'=>'', '&result'=>''], 'HttpUtil::negotiateLanguage' => ['', 'supported'=>'', '&result'=>''], 'HttpUtil::parseCookie' => ['', 'cookie_string'=>''], 'HttpUtil::parseHeaders' => ['', 'headers_string'=>''], 'HttpUtil::parseMessage' => ['', 'message_string'=>''], 'HttpUtil::parseParams' => ['', 'param_string'=>'', 'flags'=>''], 'HttpUtil::support' => ['', 'feature'=>''], 'hw_api::checkin' => ['bool', 'parameter'=>'array'], 'hw_api::checkout' => ['bool', 'parameter'=>'array'], 'hw_api::children' => ['array', 'parameter'=>'array'], 'hw_api::content' => ['HW_API_Content', 'parameter'=>'array'], 'hw_api::copy' => ['hw_api_content', 'parameter'=>'array'], 'hw_api::dbstat' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::dcstat' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::dstanchors' => ['array', 'parameter'=>'array'], 'hw_api::dstofsrcanchor' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::find' => ['array', 'parameter'=>'array'], 'hw_api::ftstat' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::hwstat' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::identify' => ['bool', 'parameter'=>'array'], 'hw_api::info' => ['array', 'parameter'=>'array'], 'hw_api::insert' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::insertanchor' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::insertcollection' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::insertdocument' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::link' => ['bool', 'parameter'=>'array'], 'hw_api::lock' => ['bool', 'parameter'=>'array'], 'hw_api::move' => ['bool', 'parameter'=>'array'], 'hw_api::object' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::objectbyanchor' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::parents' => ['array', 'parameter'=>'array'], 'hw_api::remove' => ['bool', 'parameter'=>'array'], 'hw_api::replace' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::setcommittedversion' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::srcanchors' => ['array', 'parameter'=>'array'], 'hw_api::srcsofdst' => ['array', 'parameter'=>'array'], 'hw_api::unlock' => ['bool', 'parameter'=>'array'], 'hw_api::user' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::userlist' => ['array', 'parameter'=>'array'], 'hw_api_attribute' => ['HW_API_Attribute', 'name='=>'string', 'value='=>'string'], 'hw_api_attribute::key' => ['string'], 'hw_api_attribute::langdepvalue' => ['string', 'language'=>'string'], 'hw_api_attribute::value' => ['string'], 'hw_api_attribute::values' => ['array'], 'hw_api_content' => ['HW_API_Content', 'content'=>'string', 'mimetype'=>'string'], 'hw_api_content::mimetype' => ['string'], 'hw_api_content::read' => ['string', 'buffer'=>'string', 'length'=>'int'], 'hw_api_error::count' => ['int'], 'hw_api_error::reason' => ['HW_API_Reason'], 'hw_api_object' => ['hw_api_object', 'parameter'=>'array'], 'hw_api_object::assign' => ['bool', 'parameter'=>'array'], 'hw_api_object::attreditable' => ['bool', 'parameter'=>'array'], 'hw_api_object::count' => ['int', 'parameter'=>'array'], 'hw_api_object::insert' => ['bool', 'attribute'=>'hw_api_attribute'], 'hw_api_object::remove' => ['bool', 'name'=>'string'], 'hw_api_object::title' => ['string', 'parameter'=>'array'], 'hw_api_object::value' => ['string', 'name'=>'string'], 'hw_api_reason::description' => ['string'], 'hw_api_reason::type' => ['HW_API_Reason'], 'hw_Array2Objrec' => ['string', 'object_array'=>'array'], 'hw_changeobject' => ['bool', 'link'=>'int', 'objid'=>'int', 'attributes'=>'array'], 'hw_Children' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_ChildrenObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_Close' => ['bool', 'connection'=>'int'], 'hw_Connect' => ['int', 'host'=>'string', 'port'=>'int', 'username='=>'string', 'password='=>'string'], 'hw_connection_info' => ['', 'link'=>'int'], 'hw_cp' => ['int', 'connection'=>'int', 'object_id_array'=>'array', 'destination_id'=>'int'], 'hw_Deleteobject' => ['bool', 'connection'=>'int', 'object_to_delete'=>'int'], 'hw_DocByAnchor' => ['int', 'connection'=>'int', 'anchorid'=>'int'], 'hw_DocByAnchorObj' => ['string', 'connection'=>'int', 'anchorid'=>'int'], 'hw_Document_Attributes' => ['string', 'hw_document'=>'int'], 'hw_Document_BodyTag' => ['string', 'hw_document'=>'int', 'prefix='=>'string'], 'hw_Document_Content' => ['string', 'hw_document'=>'int'], 'hw_Document_SetContent' => ['bool', 'hw_document'=>'int', 'content'=>'string'], 'hw_Document_Size' => ['int', 'hw_document'=>'int'], 'hw_dummy' => ['string', 'link'=>'int', 'id'=>'int', 'msgid'=>'int'], 'hw_EditText' => ['bool', 'connection'=>'int', 'hw_document'=>'int'], 'hw_Error' => ['int', 'connection'=>'int'], 'hw_ErrorMsg' => ['string', 'connection'=>'int'], 'hw_Free_Document' => ['bool', 'hw_document'=>'int'], 'hw_GetAnchors' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetAnchorsObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetAndLock' => ['string', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetChildColl' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetChildCollObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetChildDocColl' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetChildDocCollObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetObject' => ['', 'connection'=>'int', 'objectid'=>'', 'query='=>'string'], 'hw_GetObjectByQuery' => ['array', 'connection'=>'int', 'query'=>'string', 'max_hits'=>'int'], 'hw_GetObjectByQueryColl' => ['array', 'connection'=>'int', 'objectid'=>'int', 'query'=>'string', 'max_hits'=>'int'], 'hw_GetObjectByQueryCollObj' => ['array', 'connection'=>'int', 'objectid'=>'int', 'query'=>'string', 'max_hits'=>'int'], 'hw_GetObjectByQueryObj' => ['array', 'connection'=>'int', 'query'=>'string', 'max_hits'=>'int'], 'hw_GetParents' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetParentsObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_getrellink' => ['string', 'link'=>'int', 'rootid'=>'int', 'sourceid'=>'int', 'destid'=>'int'], 'hw_GetRemote' => ['int', 'connection'=>'int', 'objectid'=>'int'], 'hw_getremotechildren' => ['', 'connection'=>'int', 'object_record'=>'string'], 'hw_GetSrcByDestObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetText' => ['int', 'connection'=>'int', 'objectid'=>'int', 'prefix='=>''], 'hw_getusername' => ['string', 'connection'=>'int'], 'hw_Identify' => ['string', 'link'=>'int', 'username'=>'string', 'password'=>'string'], 'hw_InCollections' => ['array', 'connection'=>'int', 'object_id_array'=>'array', 'collection_id_array'=>'array', 'return_collections'=>'int'], 'hw_Info' => ['string', 'connection'=>'int'], 'hw_InsColl' => ['int', 'connection'=>'int', 'objectid'=>'int', 'object_array'=>'array'], 'hw_InsDoc' => ['int', 'connection'=>'', 'parentid'=>'int', 'object_record'=>'string', 'text='=>'string'], 'hw_insertanchors' => ['bool', 'hwdoc'=>'int', 'anchorecs'=>'array', 'dest'=>'array', 'urlprefixes='=>'array'], 'hw_InsertDocument' => ['int', 'connection'=>'int', 'parent_id'=>'int', 'hw_document'=>'int'], 'hw_InsertObject' => ['int', 'connection'=>'int', 'object_rec'=>'string', 'parameter'=>'string'], 'hw_mapid' => ['int', 'connection'=>'int', 'server_id'=>'int', 'object_id'=>'int'], 'hw_Modifyobject' => ['bool', 'connection'=>'int', 'object_to_change'=>'int', 'remove'=>'array', 'add'=>'array', 'mode='=>'int'], 'hw_mv' => ['int', 'connection'=>'int', 'object_id_array'=>'array', 'source_id'=>'int', 'destination_id'=>'int'], 'hw_New_Document' => ['int', 'object_record'=>'string', 'document_data'=>'string', 'document_size'=>'int'], 'hw_objrec2array' => ['array', 'object_record'=>'string', 'format='=>'array'], 'hw_Output_Document' => ['bool', 'hw_document'=>'int'], 'hw_pConnect' => ['int', 'host'=>'string', 'port'=>'int', 'username='=>'string', 'password='=>'string'], 'hw_PipeDocument' => ['int', 'connection'=>'int', 'objectid'=>'int', 'url_prefixes='=>'array'], 'hw_Root' => ['int'], 'hw_setlinkroot' => ['int', 'link'=>'int', 'rootid'=>'int'], 'hw_stat' => ['string', 'link'=>'int'], 'hw_Unlock' => ['bool', 'connection'=>'int', 'objectid'=>'int'], 'hw_Who' => ['array', 'connection'=>'int'], 'hwapi_attribute_new' => ['HW_API_Attribute', 'name='=>'string', 'value='=>'string'], 'hwapi_content_new' => ['HW_API_Content', 'content'=>'string', 'mimetype'=>'string'], 'hwapi_hgcsp' => ['HW_API', 'hostname'=>'string', 'port='=>'int'], 'hwapi_object_new' => ['hw_api_object', 'parameter'=>'array'], 'hypot' => ['float', 'num1'=>'float', 'num2'=>'float'], 'ibase_add_user' => ['bool', 'service_handle'=>'resource', 'user_name'=>'string', 'password'=>'string', 'first_name='=>'string', 'middle_name='=>'string', 'last_name='=>'string'], 'ibase_affected_rows' => ['int', 'link_identifier='=>'resource'], 'ibase_backup' => ['mixed', 'service_handle'=>'resource', 'source_db'=>'string', 'dest_file'=>'string', 'options='=>'int', 'verbose='=>'bool'], 'ibase_blob_add' => ['void', 'blob_handle'=>'resource', 'data'=>'string'], 'ibase_blob_cancel' => ['bool', 'blob_handle'=>'resource'], 'ibase_blob_close' => ['string|bool', 'blob_handle'=>'resource'], 'ibase_blob_create' => ['resource', 'link_identifier='=>'resource'], 'ibase_blob_echo' => ['bool', 'link_identifier'=>'', 'blob_id'=>'string'], 'ibase_blob_echo\'1' => ['bool', 'blob_id'=>'string'], 'ibase_blob_get' => ['string|false', 'blob_handle'=>'resource', 'length'=>'int'], 'ibase_blob_import' => ['string|false', 'link_identifier'=>'resource', 'file_handle'=>'resource'], 'ibase_blob_info' => ['array', 'link_identifier'=>'resource', 'blob_id'=>'string'], 'ibase_blob_info\'1' => ['array', 'blob_id'=>'string'], 'ibase_blob_open' => ['resource|false', 'link_identifier'=>'', 'blob_id'=>'string'], 'ibase_blob_open\'1' => ['resource', 'blob_id'=>'string'], 'ibase_close' => ['bool', 'link_identifier='=>'resource'], 'ibase_commit' => ['bool', 'link_identifier='=>'resource'], 'ibase_commit_ret' => ['bool', 'link_identifier='=>'resource'], 'ibase_connect' => ['resource|false', 'database='=>'string', 'username='=>'string', 'password='=>'string', 'charset='=>'string', 'buffers='=>'int', 'dialect='=>'int', 'role='=>'string'], 'ibase_db_info' => ['string', 'service_handle'=>'resource', 'db'=>'string', 'action'=>'int', 'argument='=>'int'], 'ibase_delete_user' => ['bool', 'service_handle'=>'resource', 'user_name'=>'string', 'password='=>'string', 'first_name='=>'string', 'middle_name='=>'string', 'last_name='=>'string'], 'ibase_drop_db' => ['bool', 'link_identifier='=>'resource'], 'ibase_errcode' => ['int|false'], 'ibase_errmsg' => ['string|false'], 'ibase_execute' => ['resource|false', 'query'=>'resource', 'bind_arg='=>'mixed', '...args='=>'mixed'], 'ibase_fetch_assoc' => ['array|false', 'result'=>'resource', 'fetch_flags='=>'int'], 'ibase_fetch_object' => ['object|false', 'result'=>'resource', 'fetch_flags='=>'int'], 'ibase_fetch_row' => ['array|false', 'result'=>'resource', 'fetch_flags='=>'int'], 'ibase_field_info' => ['array', 'query_result'=>'resource', 'field_number'=>'int'], 'ibase_free_event_handler' => ['bool', 'event'=>'resource'], 'ibase_free_query' => ['bool', 'query'=>'resource'], 'ibase_free_result' => ['bool', 'result'=>'resource'], 'ibase_gen_id' => ['int|string', 'generator'=>'string', 'increment='=>'int', 'link_identifier='=>'resource'], 'ibase_maintain_db' => ['bool', 'service_handle'=>'resource', 'db'=>'string', 'action'=>'int', 'argument='=>'int'], 'ibase_modify_user' => ['bool', 'service_handle'=>'resource', 'user_name'=>'string', 'password'=>'string', 'first_name='=>'string', 'middle_name='=>'string', 'last_name='=>'string'], 'ibase_name_result' => ['bool', 'result'=>'resource', 'name'=>'string'], 'ibase_num_fields' => ['int', 'query_result'=>'resource'], 'ibase_num_params' => ['int', 'query'=>'resource'], 'ibase_num_rows' => ['int', 'result_identifier'=>''], 'ibase_param_info' => ['array', 'query'=>'resource', 'field_number'=>'int'], 'ibase_pconnect' => ['resource|false', 'database='=>'string', 'username='=>'string', 'password='=>'string', 'charset='=>'string', 'buffers='=>'int', 'dialect='=>'int', 'role='=>'string'], 'ibase_prepare' => ['resource|false', 'link_identifier'=>'', 'query'=>'string', 'trans_identifier'=>''], 'ibase_query' => ['resource|false', 'link_identifier='=>'resource', 'string='=>'string', 'bind_arg='=>'int', '...args='=>''], 'ibase_restore' => ['mixed', 'service_handle'=>'resource', 'source_file'=>'string', 'dest_db'=>'string', 'options='=>'int', 'verbose='=>'bool'], 'ibase_rollback' => ['bool', 'link_identifier='=>'resource'], 'ibase_rollback_ret' => ['bool', 'link_identifier='=>'resource'], 'ibase_server_info' => ['string', 'service_handle'=>'resource', 'action'=>'int'], 'ibase_service_attach' => ['resource', 'host'=>'string', 'dba_username'=>'string', 'dba_password'=>'string'], 'ibase_service_detach' => ['bool', 'service_handle'=>'resource'], 'ibase_set_event_handler' => ['resource', 'link_identifier'=>'', 'callback'=>'callable', 'event='=>'string', '...args='=>''], 'ibase_set_event_handler\'1' => ['resource', 'callback'=>'callable', 'event'=>'string', '...args'=>''], 'ibase_timefmt' => ['bool', 'format'=>'string', 'columntype='=>'int'], 'ibase_trans' => ['resource|false', 'trans_args='=>'int', 'link_identifier='=>'', '...args='=>''], 'ibase_wait_event' => ['string', 'link_identifier'=>'', 'event='=>'string', '...args='=>''], 'ibase_wait_event\'1' => ['string', 'event'=>'string', '...args'=>''], 'iconv' => ['string|false', 'in_charset'=>'string', 'out_charset'=>'string', 'string'=>'string'], 'iconv_get_encoding' => ['mixed', 'type='=>'string'], 'iconv_mime_decode' => ['string|false', 'encoded_string'=>'string', 'mode='=>'int', 'charset='=>'string'], 'iconv_mime_decode_headers' => ['array|false', 'headers'=>'string', 'mode='=>'int', 'charset='=>'string'], 'iconv_mime_encode' => ['string|false', 'field_name'=>'string', 'field_value'=>'string', 'preference='=>'array'], 'iconv_set_encoding' => ['bool', 'type'=>'string', 'charset'=>'string'], 'iconv_strlen' => ['int|false', 'string'=>'string', 'charset='=>'string'], 'iconv_strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'charset='=>'string'], 'iconv_strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'charset='=>'string'], 'iconv_substr' => ['string|false', 'string'=>'string', 'offset'=>'int', 'length='=>'int', 'charset='=>'string'], 'id3_get_frame_long_name' => ['string', 'frameid'=>'string'], 'id3_get_frame_short_name' => ['string', 'frameid'=>'string'], 'id3_get_genre_id' => ['int', 'genre'=>'string'], 'id3_get_genre_list' => ['array'], 'id3_get_genre_name' => ['string', 'genre_id'=>'int'], 'id3_get_tag' => ['array', 'filename'=>'string', 'version='=>'int'], 'id3_get_version' => ['int', 'filename'=>'string'], 'id3_remove_tag' => ['bool', 'filename'=>'string', 'version='=>'int'], 'id3_set_tag' => ['bool', 'filename'=>'string', 'tag'=>'array', 'version='=>'int'], 'idate' => ['int', 'format'=>'string', 'timestamp='=>'int'], 'idn_strerror' => ['string', 'errorcode'=>'int'], 'idn_to_ascii' => ['string|false', 'domain'=>'string', 'options='=>'int', 'variant='=>'int', '&w_idna_info='=>'array'], 'idn_to_utf8' => ['string|false', 'domain'=>'string', 'options='=>'int', 'variant='=>'int', '&w_idna_info='=>'array'], 'ifx_affected_rows' => ['int', 'result_id'=>'resource'], 'ifx_blobinfile_mode' => ['bool', 'mode'=>'int'], 'ifx_byteasvarchar' => ['bool', 'mode'=>'int'], 'ifx_close' => ['bool', 'link_identifier='=>'resource'], 'ifx_connect' => ['resource', 'database='=>'string', 'userid='=>'string', 'password='=>'string'], 'ifx_copy_blob' => ['int', 'bid'=>'int'], 'ifx_create_blob' => ['int', 'type'=>'int', 'mode'=>'int', 'param'=>'string'], 'ifx_create_char' => ['int', 'param'=>'string'], 'ifx_do' => ['bool', 'result_id'=>'resource'], 'ifx_error' => ['string', 'link_identifier='=>'resource'], 'ifx_errormsg' => ['string', 'errorcode='=>'int'], 'ifx_fetch_row' => ['array', 'result_id'=>'resource', 'position='=>'mixed'], 'ifx_fieldproperties' => ['array', 'result_id'=>'resource'], 'ifx_fieldtypes' => ['array', 'result_id'=>'resource'], 'ifx_free_blob' => ['bool', 'bid'=>'int'], 'ifx_free_char' => ['bool', 'bid'=>'int'], 'ifx_free_result' => ['bool', 'result_id'=>'resource'], 'ifx_get_blob' => ['string', 'bid'=>'int'], 'ifx_get_char' => ['string', 'bid'=>'int'], 'ifx_getsqlca' => ['array', 'result_id'=>'resource'], 'ifx_htmltbl_result' => ['int', 'result_id'=>'resource', 'html_table_options='=>'string'], 'ifx_nullformat' => ['bool', 'mode'=>'int'], 'ifx_num_fields' => ['int', 'result_id'=>'resource'], 'ifx_num_rows' => ['int', 'result_id'=>'resource'], 'ifx_pconnect' => ['resource', 'database='=>'string', 'userid='=>'string', 'password='=>'string'], 'ifx_prepare' => ['resource', 'query'=>'string', 'link_identifier'=>'resource', 'cursor_def='=>'int', 'blobidarray='=>'mixed'], 'ifx_query' => ['resource', 'query'=>'string', 'link_identifier'=>'resource', 'cursor_type='=>'int', 'blobidarray='=>'mixed'], 'ifx_textasvarchar' => ['bool', 'mode'=>'int'], 'ifx_update_blob' => ['bool', 'bid'=>'int', 'content'=>'string'], 'ifx_update_char' => ['bool', 'bid'=>'int', 'content'=>'string'], 'ifxus_close_slob' => ['bool', 'bid'=>'int'], 'ifxus_create_slob' => ['int', 'mode'=>'int'], 'ifxus_free_slob' => ['bool', 'bid'=>'int'], 'ifxus_open_slob' => ['int', 'bid'=>'int', 'mode'=>'int'], 'ifxus_read_slob' => ['string', 'bid'=>'int', 'nbytes'=>'int'], 'ifxus_seek_slob' => ['int', 'bid'=>'int', 'mode'=>'int', 'offset'=>'int'], 'ifxus_tell_slob' => ['int', 'bid'=>'int'], 'ifxus_write_slob' => ['int', 'bid'=>'int', 'content'=>'string'], 'igbinary_serialize' => ['string|false', 'value'=>'mixed'], 'igbinary_unserialize' => ['mixed', 'string'=>'string'], 'ignore_user_abort' => ['int', 'value='=>'bool'], 'iis_add_server' => ['int', 'path'=>'string', 'comment'=>'string', 'server_ip'=>'string', 'port'=>'int', 'host_name'=>'string', 'rights'=>'int', 'start_server'=>'int'], 'iis_get_dir_security' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string'], 'iis_get_script_map' => ['string', 'server_instance'=>'int', 'virtual_path'=>'string', 'script_extension'=>'string'], 'iis_get_server_by_comment' => ['int', 'comment'=>'string'], 'iis_get_server_by_path' => ['int', 'path'=>'string'], 'iis_get_server_rights' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string'], 'iis_get_service_state' => ['int', 'service_id'=>'string'], 'iis_remove_server' => ['int', 'server_instance'=>'int'], 'iis_set_app_settings' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string', 'application_scope'=>'string'], 'iis_set_dir_security' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string', 'directory_flags'=>'int'], 'iis_set_script_map' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string', 'script_extension'=>'string', 'engine_path'=>'string', 'allow_scripting'=>'int'], 'iis_set_server_rights' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string', 'directory_flags'=>'int'], 'iis_start_server' => ['int', 'server_instance'=>'int'], 'iis_start_service' => ['int', 'service_id'=>'string'], 'iis_stop_server' => ['int', 'server_instance'=>'int'], 'iis_stop_service' => ['int', 'service_id'=>'string'], 'image2wbmp' => ['bool', 'im'=>'resource', 'filename='=>'?string', 'threshold='=>'int'], 'image_type_to_extension' => ['string', 'imagetype'=>'int', 'include_dot='=>'bool'], 'image_type_to_mime_type' => ['string', 'imagetype'=>'int'], 'imageaffine' => ['resource|false', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'], 'imageaffineconcat' => ['array|false', 'm1'=>'array', 'm2'=>'array'], 'imageaffinematrixconcat' => ['array{0:float,1:float,2:float,3:float,4:float,5:float}|false', 'm1'=>'array', 'm2'=>'array'], 'imageaffinematrixget' => ['array{0:float,1:float,2:float,3:float,4:float,5:float}|false', 'type'=>'int', 'options'=>'array|float'], 'imagealphablending' => ['bool', 'im'=>'resource', 'on'=>'bool'], 'imageantialias' => ['bool', 'im'=>'resource', 'on'=>'bool'], 'imagearc' => ['bool', 'im'=>'resource', 'cx'=>'int', 'cy'=>'int', 'w'=>'int', 'h'=>'int', 's'=>'int', 'e'=>'int', 'col'=>'int'], 'imagebmp' => ['bool', 'image'=>'resource', 'to='=>'string|resource|null', 'compressed='=>'bool'], 'imagechar' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'c'=>'string', 'col'=>'int'], 'imagecharup' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'c'=>'string', 'col'=>'int'], 'imagecolorallocate' => ['int|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolorallocatealpha' => ['int|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], 'imagecolorat' => ['int|false', 'im'=>'resource', 'x'=>'int', 'y'=>'int'], 'imagecolorclosest' => ['int|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolorclosestalpha' => ['int|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], 'imagecolorclosesthwb' => ['int|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolordeallocate' => ['bool', 'im'=>'resource', 'index'=>'int'], 'imagecolorexact' => ['int|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolorexactalpha' => ['int|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], 'imagecolormatch' => ['bool', 'im1'=>'resource', 'im2'=>'resource'], 'imagecolorresolve' => ['int|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolorresolvealpha' => ['int|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], 'imagecolorset' => ['void', 'im'=>'resource', 'col'=>'int', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha='=>'int'], 'imagecolorsforindex' => ['array|false', 'im'=>'resource', 'col'=>'int'], 'imagecolorstotal' => ['int|false', 'im'=>'resource'], 'imagecolortransparent' => ['int|false', 'im'=>'resource', 'col='=>'int'], 'imageconvolution' => ['bool', 'src_im'=>'resource', 'matrix3x3'=>'array', 'div'=>'float', 'offset'=>'float'], 'imagecopy' => ['bool', 'dst_im'=>'resource', 'src_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'src_w'=>'int', 'src_h'=>'int'], 'imagecopymerge' => ['bool', 'src_im'=>'resource', 'dst_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'src_w'=>'int', 'src_h'=>'int', 'pct'=>'int'], 'imagecopymergegray' => ['bool', 'src_im'=>'resource', 'dst_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'src_w'=>'int', 'src_h'=>'int', 'pct'=>'int'], 'imagecopyresampled' => ['bool', 'dst_im'=>'resource', 'src_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'dst_w'=>'int', 'dst_h'=>'int', 'src_w'=>'int', 'src_h'=>'int'], 'imagecopyresized' => ['bool', 'dst_im'=>'resource', 'src_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'dst_w'=>'int', 'dst_h'=>'int', 'src_w'=>'int', 'src_h'=>'int'], 'imagecreate' => ['resource|false', 'x_size'=>'int', 'y_size'=>'int'], 'imagecreatefrombmp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd2' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd2part' => ['resource|false', 'filename'=>'string', 'srcx'=>'int', 'srcy'=>'int', 'width'=>'int', 'height'=>'int'], 'imagecreatefromgif' => ['resource|false', 'filename'=>'string'], 'imagecreatefromjpeg' => ['resource|false', 'filename'=>'string'], 'imagecreatefrompng' => ['resource|false', 'filename'=>'string'], 'imagecreatefromstring' => ['resource|false', 'image'=>'string'], 'imagecreatefromwbmp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromwebp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxbm' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxpm' => ['resource|false', 'filename'=>'string'], 'imagecreatetruecolor' => ['resource|false', 'x_size'=>'int', 'y_size'=>'int'], 'imagecrop' => ['resource|false', 'im'=>'resource', 'rect'=>'array'], 'imagecropauto' => ['resource|false', 'im'=>'resource', 'mode'=>'int', 'threshold'=>'float', 'color'=>'int'], 'imagedashedline' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int', 'col'=>'int'], 'imagedestroy' => ['bool', 'im'=>'resource'], 'imageellipse' => ['bool', 'im'=>'resource', 'cx'=>'int', 'cy'=>'int', 'w'=>'int', 'h'=>'int', 'color'=>'int'], 'imagefill' => ['bool', 'im'=>'resource', 'x'=>'int', 'y'=>'int', 'col'=>'int'], 'imagefilledarc' => ['bool', 'im'=>'resource', 'cx'=>'int', 'cy'=>'int', 'w'=>'int', 'h'=>'int', 's'=>'int', 'e'=>'int', 'col'=>'int', 'style'=>'int'], 'imagefilledellipse' => ['bool', 'im'=>'resource', 'cx'=>'int', 'cy'=>'int', 'w'=>'int', 'h'=>'int', 'color'=>'int'], 'imagefilledpolygon' => ['bool', 'im'=>'resource', 'point'=>'array', 'num_points'=>'int', 'col'=>'int'], 'imagefilledrectangle' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int', 'col'=>'int'], 'imagefilltoborder' => ['bool', 'im'=>'resource', 'x'=>'int', 'y'=>'int', 'border'=>'int', 'col'=>'int'], 'imagefilter' => ['bool', 'src_im'=>'resource', 'filtertype'=>'int', 'arg1='=>'int', 'arg2='=>'int', 'arg3='=>'int', 'arg4='=>'int'], 'imageflip' => ['bool', 'im'=>'resource', 'mode'=>'int'], 'imagefontheight' => ['int', 'font'=>'int'], 'imagefontwidth' => ['int', 'font'=>'int'], 'imageftbbox' => ['array|false', 'size'=>'float', 'angle'=>'float', 'font_file'=>'string', 'text'=>'string', 'extrainfo='=>'array'], 'imagefttext' => ['array|false', 'im'=>'resource', 'size'=>'float', 'angle'=>'float', 'x'=>'int', 'y'=>'int', 'col'=>'int', 'font_file'=>'string', 'text'=>'string', 'extrainfo='=>'array'], 'imagegammacorrect' => ['bool', 'im'=>'resource', 'inputgamma'=>'float', 'outputgamma'=>'float'], 'imagegd' => ['bool', 'im'=>'resource', 'to='=>'string|resource|null'], 'imagegd2' => ['bool', 'im'=>'resource', 'to='=>'string|resource|null', 'chunk_size='=>'int', 'type='=>'int'], 'imagegetclip' => ['array|false', 'im'=>'resource'], 'imagegif' => ['bool', 'im'=>'resource', 'to='=>'string|resource|null'], 'imagegrabscreen' => ['false|resource'], 'imagegrabwindow' => ['false|resource', 'window_handle'=>'int', 'client_area='=>'int'], 'imageinterlace' => ['int|false', 'im'=>'resource', 'interlace='=>'int'], 'imageistruecolor' => ['bool', 'im'=>'resource'], 'imagejpeg' => ['bool', 'im'=>'resource', 'to='=>'string|resource|null', 'quality='=>'int'], 'imagejpeg\'1' => ['string|false', 'im'=>'resource', 'filename='=>'null', 'quality='=>'int'], 'imagelayereffect' => ['bool', 'im'=>'resource', 'effect'=>'int'], 'imageline' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int', 'col'=>'int'], 'imageloadfont' => ['int|false', 'filename'=>'string'], 'imageObj::pasteImage' => ['void', 'srcImg'=>'imageObj', 'transparentColorHex'=>'int', 'dstX'=>'int', 'dstY'=>'int', 'angle'=>'int'], 'imageObj::saveImage' => ['int', 'filename'=>'string', 'oMap'=>'mapObj'], 'imageObj::saveWebImage' => ['string'], 'imageopenpolygon' => ['bool', 'image'=>'resource', 'points'=>'array', 'num_points'=>'int', 'color'=>'int'], 'imagepalettecopy' => ['void', 'dst'=>'resource', 'src'=>'resource'], 'imagepalettetotruecolor' => ['bool', 'src'=>'resource'], 'imagepng' => ['bool', 'im'=>'resource', 'to='=>'string|resource|null', 'quality='=>'int', 'filters='=>'int'], 'imagepolygon' => ['bool', 'im'=>'resource', 'point'=>'array', 'num_points'=>'int', 'col'=>'int'], 'imagerectangle' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int', 'col'=>'int'], 'imageresolution' => ['array|bool', 'image'=>'resource', 'res_x='=>'int', 'res_y='=>'int'], 'imagerotate' => ['resource|false', 'src_im'=>'resource', 'angle'=>'float', 'bgdcolor'=>'int', 'ignoretransparent='=>'int'], 'imagesavealpha' => ['bool', 'im'=>'resource', 'on'=>'bool'], 'imagescale' => ['resource|false', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'], 'imagesetbrush' => ['bool', 'image'=>'resource', 'brush'=>'resource'], 'imagesetclip' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int'], 'imagesetinterpolation' => ['bool', 'im'=>'resource', 'method'=>'int'], 'imagesetpixel' => ['bool', 'im'=>'resource', 'x'=>'int', 'y'=>'int', 'col'=>'int'], 'imagesetstyle' => ['bool', 'im'=>'resource', 'styles'=>'non-empty-array'], 'imagesetthickness' => ['bool', 'im'=>'resource', 'thickness'=>'int'], 'imagesettile' => ['bool', 'image'=>'resource', 'tile'=>'resource'], 'imagestring' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'string'=>'string', 'col'=>'int'], 'imagestringup' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'string'=>'string', 'col'=>'int'], 'imagesx' => ['int|false', 'im'=>'resource'], 'imagesy' => ['int|false', 'im'=>'resource'], 'imagetruecolortopalette' => ['bool', 'im'=>'resource', 'ditherflag'=>'bool', 'colorswanted'=>'int'], 'imagettfbbox' => ['false|array', 'size'=>'float', 'angle'=>'float', 'font_file'=>'string', 'text'=>'string'], 'imagettftext' => ['false|array', 'im'=>'resource', 'size'=>'float', 'angle'=>'float', 'x'=>'int', 'y'=>'int', 'col'=>'int', 'font_file'=>'string', 'text'=>'string'], 'imagetypes' => ['int'], 'imagewbmp' => ['bool', 'im'=>'resource', 'to='=>'string|resource|null', 'foreground='=>'int'], 'imagewebp' => ['bool', 'im'=>'resource', 'to='=>'string|resource|null', 'quality='=>'int'], 'imagexbm' => ['bool', 'im'=>'resource', 'filename='=>'?string', 'foreground='=>'int'], 'Imagick::__construct' => ['void', 'files='=>'string|string[]'], 'Imagick::__toString' => ['string'], 'Imagick::adaptiveBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::adaptiveResizeImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'bestfit='=>'bool'], 'Imagick::adaptiveSharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::adaptiveThresholdImage' => ['bool', 'width'=>'int', 'height'=>'int', 'offset'=>'int'], 'Imagick::addImage' => ['bool', 'source'=>'imagick'], 'Imagick::addNoiseImage' => ['bool', 'noise_type'=>'int', 'channel='=>'int'], 'Imagick::affineTransformImage' => ['bool', 'matrix'=>'imagickdraw'], 'Imagick::animateImages' => ['bool', 'x_server'=>'string'], 'Imagick::annotateImage' => ['bool', 'draw_settings'=>'imagickdraw', 'x'=>'float', 'y'=>'float', 'angle'=>'float', 'text'=>'string'], 'Imagick::appendImages' => ['Imagick', 'stack'=>'bool'], 'Imagick::autoGammaImage' => ['bool', 'channel='=>'int'], 'Imagick::autoLevelImage' => ['void', 'CHANNEL='=>'string'], 'Imagick::autoOrient' => ['bool'], 'Imagick::averageImages' => ['Imagick'], 'Imagick::blackThresholdImage' => ['bool', 'threshold'=>'mixed'], 'Imagick::blueShiftImage' => ['void', 'factor='=>'float'], 'Imagick::blurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::borderImage' => ['bool', 'bordercolor'=>'mixed', 'width'=>'int', 'height'=>'int'], 'Imagick::brightnessContrastImage' => ['void', 'brightness'=>'string', 'contrast'=>'string', 'CHANNEL='=>'string'], 'Imagick::charcoalImage' => ['bool', 'radius'=>'float', 'sigma'=>'float'], 'Imagick::chopImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::clampImage' => ['void', 'CHANNEL='=>'string'], 'Imagick::clear' => ['bool'], 'Imagick::clipImage' => ['bool'], 'Imagick::clipImagePath' => ['void', 'pathname'=>'string', 'inside'=>'string'], 'Imagick::clipPathImage' => ['bool', 'pathname'=>'string', 'inside'=>'bool'], 'Imagick::clone' => ['Imagick'], 'Imagick::clutImage' => ['bool', 'lookup_table'=>'imagick', 'channel='=>'float'], 'Imagick::coalesceImages' => ['Imagick'], 'Imagick::colorFloodfillImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int'], 'Imagick::colorizeImage' => ['bool', 'colorize'=>'mixed', 'opacity'=>'mixed'], 'Imagick::colorMatrixImage' => ['void', 'color_matrix'=>'string'], 'Imagick::combineImages' => ['Imagick', 'channeltype'=>'int'], 'Imagick::commentImage' => ['bool', 'comment'=>'string'], 'Imagick::compareImageChannels' => ['array', 'image'=>'imagick', 'channeltype'=>'int', 'metrictype'=>'int'], 'Imagick::compareImageLayers' => ['Imagick', 'method'=>'int'], 'Imagick::compareImages' => ['array', 'compare'=>'imagick', 'metric'=>'int'], 'Imagick::compositeImage' => ['bool', 'composite_object'=>'imagick', 'composite'=>'int', 'x'=>'int', 'y'=>'int', 'channel='=>'int'], 'Imagick::compositeImageGravity' => ['bool', 'imagick'=>'Imagick', 'COMPOSITE_CONSTANT'=>'int', 'GRAVITY_CONSTANT'=>'int'], 'Imagick::contrastImage' => ['bool', 'sharpen'=>'bool'], 'Imagick::contrastStretchImage' => ['bool', 'black_point'=>'float', 'white_point'=>'float', 'channel='=>'int'], 'Imagick::convolveImage' => ['bool', 'kernel'=>'array', 'channel='=>'int'], 'Imagick::count' => ['void', 'mode='=>'string'], 'Imagick::cropImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::cropThumbnailImage' => ['bool', 'width'=>'int', 'height'=>'int', 'legacy='=>'bool'], 'Imagick::current' => ['Imagick'], 'Imagick::cycleColormapImage' => ['bool', 'displace'=>'int'], 'Imagick::decipherImage' => ['bool', 'passphrase'=>'string'], 'Imagick::deconstructImages' => ['Imagick'], 'Imagick::deleteImageArtifact' => ['bool', 'artifact'=>'string'], 'Imagick::deleteImageProperty' => ['void', 'name'=>'string'], 'Imagick::deskewImage' => ['bool', 'threshold'=>'float'], 'Imagick::despeckleImage' => ['bool'], 'Imagick::destroy' => ['bool'], 'Imagick::displayImage' => ['bool', 'servername'=>'string'], 'Imagick::displayImages' => ['bool', 'servername'=>'string'], 'Imagick::distortImage' => ['bool', 'method'=>'int', 'arguments'=>'array', 'bestfit'=>'bool'], 'Imagick::drawImage' => ['bool', 'draw'=>'imagickdraw'], 'Imagick::edgeImage' => ['bool', 'radius'=>'float'], 'Imagick::embossImage' => ['bool', 'radius'=>'float', 'sigma'=>'float'], 'Imagick::encipherImage' => ['bool', 'passphrase'=>'string'], 'Imagick::enhanceImage' => ['bool'], 'Imagick::equalizeImage' => ['bool'], 'Imagick::evaluateImage' => ['bool', 'op'=>'int', 'constant'=>'float', 'channel='=>'int'], 'Imagick::evaluateImages' => ['bool', 'EVALUATE_CONSTANT'=>'int'], 'Imagick::exportImagePixels' => ['array', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'int'], 'Imagick::extentImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::filter' => ['void', 'ImagickKernel'=>'ImagickKernel', 'CHANNEL='=>'int'], 'Imagick::flattenImages' => ['Imagick'], 'Imagick::flipImage' => ['bool'], 'Imagick::floodFillPaintImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'target'=>'mixed', 'x'=>'int', 'y'=>'int', 'invert'=>'bool', 'channel='=>'int'], 'Imagick::flopImage' => ['bool'], 'Imagick::forwardFourierTransformimage' => ['void', 'magnitude'=>'bool'], 'Imagick::frameImage' => ['bool', 'matte_color'=>'mixed', 'width'=>'int', 'height'=>'int', 'inner_bevel'=>'int', 'outer_bevel'=>'int'], 'Imagick::functionImage' => ['bool', 'function'=>'int', 'arguments'=>'array', 'channel='=>'int'], 'Imagick::fxImage' => ['Imagick', 'expression'=>'string', 'channel='=>'int'], 'Imagick::gammaImage' => ['bool', 'gamma'=>'float', 'channel='=>'int'], 'Imagick::gaussianBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::getColorspace' => ['int'], 'Imagick::getCompression' => ['int'], 'Imagick::getCompressionQuality' => ['int'], 'Imagick::getConfigureOptions' => ['string'], 'Imagick::getCopyright' => ['string'], 'Imagick::getFeatures' => ['string'], 'Imagick::getFilename' => ['string'], 'Imagick::getFont' => ['string|false'], 'Imagick::getFormat' => ['string'], 'Imagick::getGravity' => ['int'], 'Imagick::getHDRIEnabled' => ['int'], 'Imagick::getHomeURL' => ['string'], 'Imagick::getImage' => ['Imagick'], 'Imagick::getImageAlphaChannel' => ['int'], 'Imagick::getImageArtifact' => ['string', 'artifact'=>'string'], 'Imagick::getImageAttribute' => ['string', 'key'=>'string'], 'Imagick::getImageBackgroundColor' => ['ImagickPixel'], 'Imagick::getImageBlob' => ['string'], 'Imagick::getImageBluePrimary' => ['array'], 'Imagick::getImageBorderColor' => ['ImagickPixel'], 'Imagick::getImageChannelDepth' => ['int', 'channel'=>'int'], 'Imagick::getImageChannelDistortion' => ['float', 'reference'=>'imagick', 'channel'=>'int', 'metric'=>'int'], 'Imagick::getImageChannelDistortions' => ['float', 'reference'=>'imagick', 'metric'=>'int', 'channel='=>'int'], 'Imagick::getImageChannelExtrema' => ['array', 'channel'=>'int'], 'Imagick::getImageChannelKurtosis' => ['array', 'channel='=>'int'], 'Imagick::getImageChannelMean' => ['array', 'channel'=>'int'], 'Imagick::getImageChannelRange' => ['array', 'channel'=>'int'], 'Imagick::getImageChannelStatistics' => ['array'], 'Imagick::getImageClipMask' => ['Imagick'], 'Imagick::getImageColormapColor' => ['ImagickPixel', 'index'=>'int'], 'Imagick::getImageColors' => ['int'], 'Imagick::getImageColorspace' => ['int'], 'Imagick::getImageCompose' => ['int'], 'Imagick::getImageCompression' => ['int'], 'Imagick::getImageCompressionQuality' => ['int'], 'Imagick::getImageDelay' => ['int'], 'Imagick::getImageDepth' => ['int'], 'Imagick::getImageDispose' => ['int'], 'Imagick::getImageDistortion' => ['float', 'reference'=>'magickwand', 'metric'=>'int'], 'Imagick::getImageExtrema' => ['array'], 'Imagick::getImageFilename' => ['string'], 'Imagick::getImageFormat' => ['string'], 'Imagick::getImageGamma' => ['float'], 'Imagick::getImageGeometry' => ['array'], 'Imagick::getImageGravity' => ['int'], 'Imagick::getImageGreenPrimary' => ['array'], 'Imagick::getImageHeight' => ['int'], 'Imagick::getImageHistogram' => ['array'], 'Imagick::getImageIndex' => ['int'], 'Imagick::getImageInterlaceScheme' => ['int'], 'Imagick::getImageInterpolateMethod' => ['int'], 'Imagick::getImageIterations' => ['int'], 'Imagick::getImageLength' => ['int'], 'Imagick::getImageMagickLicense' => ['string'], 'Imagick::getImageMatte' => ['bool'], 'Imagick::getImageMatteColor' => ['ImagickPixel'], 'Imagick::getImageMimeType' => ['string'], 'Imagick::getImageOrientation' => ['int'], 'Imagick::getImagePage' => ['array'], 'Imagick::getImagePixelColor' => ['ImagickPixel', 'x'=>'int', 'y'=>'int'], 'Imagick::getImageProfile' => ['string', 'name'=>'string'], 'Imagick::getImageProfiles' => ['array', 'pattern='=>'string', 'only_names='=>'bool'], 'Imagick::getImageProperties' => ['array', 'pattern='=>'string', 'only_names='=>'bool'], 'Imagick::getImageProperty' => ['string|false', 'name'=>'string'], 'Imagick::getImageRedPrimary' => ['array'], 'Imagick::getImageRegion' => ['Imagick', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::getImageRenderingIntent' => ['int'], 'Imagick::getImageResolution' => ['array'], 'Imagick::getImagesBlob' => ['string'], 'Imagick::getImageScene' => ['int'], 'Imagick::getImageSignature' => ['string'], 'Imagick::getImageSize' => ['int'], 'Imagick::getImageTicksPerSecond' => ['int'], 'Imagick::getImageTotalInkDensity' => ['float'], 'Imagick::getImageType' => ['int'], 'Imagick::getImageUnits' => ['int'], 'Imagick::getImageVirtualPixelMethod' => ['int'], 'Imagick::getImageWhitePoint' => ['array'], 'Imagick::getImageWidth' => ['int'], 'Imagick::getInterlaceScheme' => ['int'], 'Imagick::getIteratorIndex' => ['int'], 'Imagick::getNumberImages' => ['int'], 'Imagick::getOption' => ['string', 'key'=>'string'], 'Imagick::getPackageName' => ['string'], 'Imagick::getPage' => ['array'], 'Imagick::getPixelIterator' => ['ImagickPixelIterator'], 'Imagick::getPixelRegionIterator' => ['ImagickPixelIterator', 'x'=>'int', 'y'=>'int', 'columns'=>'int', 'rows'=>'int'], 'Imagick::getPointSize' => ['float'], 'Imagick::getQuantum' => ['int'], 'Imagick::getQuantumDepth' => ['array'], 'Imagick::getQuantumRange' => ['array'], 'Imagick::getRegistry' => ['string|false', 'key'=>'string'], 'Imagick::getReleaseDate' => ['string'], 'Imagick::getResource' => ['int', 'type'=>'int'], 'Imagick::getResourceLimit' => ['int', 'type'=>'int'], 'Imagick::getSamplingFactors' => ['array'], 'Imagick::getSize' => ['array'], 'Imagick::getSizeOffset' => ['int'], 'Imagick::getVersion' => ['array'], 'Imagick::haldClutImage' => ['bool', 'clut'=>'imagick', 'channel='=>'int'], 'Imagick::hasNextImage' => ['bool'], 'Imagick::hasPreviousImage' => ['bool'], 'Imagick::identifyFormat' => ['string|false', 'embedText'=>'string'], 'Imagick::identifyImage' => ['array', 'appendrawoutput='=>'bool'], 'Imagick::identifyImageType' => ['int'], 'Imagick::implodeImage' => ['bool', 'radius'=>'float'], 'Imagick::importImagePixels' => ['bool', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'int', 'pixels'=>'array'], 'Imagick::inverseFourierTransformImage' => ['void', 'complement'=>'string', 'magnitude'=>'string'], 'Imagick::key' => ['int|string'], 'Imagick::labelImage' => ['bool', 'label'=>'string'], 'Imagick::levelImage' => ['bool', 'blackpoint'=>'float', 'gamma'=>'float', 'whitepoint'=>'float', 'channel='=>'int'], 'Imagick::linearStretchImage' => ['bool', 'blackpoint'=>'float', 'whitepoint'=>'float'], 'Imagick::liquidRescaleImage' => ['bool', 'width'=>'int', 'height'=>'int', 'delta_x'=>'float', 'rigidity'=>'float'], 'Imagick::listRegistry' => ['array'], 'Imagick::localContrastImage' => ['bool', 'radius'=>'float', 'strength'=>'float'], 'Imagick::magnifyImage' => ['bool'], 'Imagick::mapImage' => ['bool', 'map'=>'imagick', 'dither'=>'bool'], 'Imagick::matteFloodfillImage' => ['bool', 'alpha'=>'float', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int'], 'Imagick::medianFilterImage' => ['bool', 'radius'=>'float'], 'Imagick::mergeImageLayers' => ['Imagick', 'layer_method'=>'int'], 'Imagick::minifyImage' => ['bool'], 'Imagick::modulateImage' => ['bool', 'brightness'=>'float', 'saturation'=>'float', 'hue'=>'float'], 'Imagick::montageImage' => ['Imagick', 'draw'=>'imagickdraw', 'tile_geometry'=>'string', 'thumbnail_geometry'=>'string', 'mode'=>'int', 'frame'=>'string'], 'Imagick::morphImages' => ['Imagick', 'number_frames'=>'int'], 'Imagick::morphology' => ['void', 'morphologyMethod'=>'int', 'iterations'=>'int', 'ImagickKernel'=>'ImagickKernel', 'CHANNEL='=>'string'], 'Imagick::mosaicImages' => ['Imagick'], 'Imagick::motionBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float', 'channel='=>'int'], 'Imagick::negateImage' => ['bool', 'gray'=>'bool', 'channel='=>'int'], 'Imagick::newImage' => ['bool', 'cols'=>'int', 'rows'=>'int', 'background'=>'mixed', 'format='=>'string'], 'Imagick::newPseudoImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'pseudostring'=>'string'], 'Imagick::next' => ['void'], 'Imagick::nextImage' => ['bool'], 'Imagick::normalizeImage' => ['bool', 'channel='=>'int'], 'Imagick::oilPaintImage' => ['bool', 'radius'=>'float'], 'Imagick::opaquePaintImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'invert'=>'bool', 'channel='=>'int'], 'Imagick::optimizeImageLayers' => ['bool'], 'Imagick::orderedPosterizeImage' => ['bool', 'threshold_map'=>'string', 'channel='=>'int'], 'Imagick::paintFloodfillImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int', 'channel='=>'int'], 'Imagick::paintOpaqueImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'channel='=>'int'], 'Imagick::paintTransparentImage' => ['bool', 'target'=>'mixed', 'alpha'=>'float', 'fuzz'=>'float'], 'Imagick::pingImage' => ['bool', 'filename'=>'string'], 'Imagick::pingImageBlob' => ['bool', 'image'=>'string'], 'Imagick::pingImageFile' => ['bool', 'filehandle'=>'resource', 'filename='=>'string'], 'Imagick::polaroidImage' => ['bool', 'properties'=>'imagickdraw', 'angle'=>'float'], 'Imagick::posterizeImage' => ['bool', 'levels'=>'int', 'dither'=>'bool'], 'Imagick::previewImages' => ['bool', 'preview'=>'int'], 'Imagick::previousImage' => ['bool'], 'Imagick::profileImage' => ['bool', 'name'=>'string', 'profile'=>'string'], 'Imagick::quantizeImage' => ['bool', 'numbercolors'=>'int', 'colorspace'=>'int', 'treedepth'=>'int', 'dither'=>'bool', 'measureerror'=>'bool'], 'Imagick::quantizeImages' => ['bool', 'numbercolors'=>'int', 'colorspace'=>'int', 'treedepth'=>'int', 'dither'=>'bool', 'measureerror'=>'bool'], 'Imagick::queryFontMetrics' => ['array', 'properties'=>'imagickdraw', 'text'=>'string', 'multiline='=>'bool'], 'Imagick::queryFonts' => ['array', 'pattern='=>'string'], 'Imagick::queryFormats' => ['array', 'pattern='=>'string'], 'Imagick::radialBlurImage' => ['bool', 'angle'=>'float', 'channel='=>'int'], 'Imagick::raiseImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int', 'raise'=>'bool'], 'Imagick::randomThresholdImage' => ['bool', 'low'=>'float', 'high'=>'float', 'channel='=>'int'], 'Imagick::readImage' => ['bool', 'filename'=>'string'], 'Imagick::readImageBlob' => ['bool', 'image'=>'string', 'filename='=>'string'], 'Imagick::readImageFile' => ['bool', 'filehandle'=>'resource', 'filename='=>'string'], 'Imagick::readImages' => ['Imagick', 'filenames'=>'string'], 'Imagick::recolorImage' => ['bool', 'matrix'=>'array'], 'Imagick::reduceNoiseImage' => ['bool', 'radius'=>'float'], 'Imagick::remapImage' => ['bool', 'replacement'=>'imagick', 'dither'=>'int'], 'Imagick::removeImage' => ['bool'], 'Imagick::removeImageProfile' => ['string', 'name'=>'string'], 'Imagick::render' => ['bool'], 'Imagick::resampleImage' => ['bool', 'x_resolution'=>'float', 'y_resolution'=>'float', 'filter'=>'int', 'blur'=>'float'], 'Imagick::resetImagePage' => ['bool', 'page'=>'string'], 'Imagick::resetIterator' => [''], 'Imagick::resizeImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'filter'=>'int', 'blur'=>'float', 'bestfit='=>'bool'], 'Imagick::rewind' => ['void'], 'Imagick::rollImage' => ['bool', 'x'=>'int', 'y'=>'int'], 'Imagick::rotateImage' => ['bool', 'background'=>'mixed', 'degrees'=>'float'], 'Imagick::rotationalBlurImage' => ['void', 'angle'=>'string', 'CHANNEL='=>'string'], 'Imagick::roundCorners' => ['bool', 'x_rounding'=>'float', 'y_rounding'=>'float', 'stroke_width='=>'float', 'displace='=>'float', 'size_correction='=>'float'], 'Imagick::roundCornersImage' => ['', 'xRounding'=>'', 'yRounding'=>'', 'strokeWidth'=>'', 'displace'=>'', 'sizeCorrection'=>''], 'Imagick::sampleImage' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::scaleImage' => ['bool', 'cols'=>'int', 'rows'=>'int', 'bestfit='=>'bool'], 'Imagick::segmentImage' => ['bool', 'colorspace'=>'int', 'cluster_threshold'=>'float', 'smooth_threshold'=>'float', 'verbose='=>'bool'], 'Imagick::selectiveBlurImage' => ['void', 'radius'=>'float', 'sigma'=>'float', 'threshold'=>'float', 'CHANNEL'=>'int'], 'Imagick::separateImageChannel' => ['bool', 'channel'=>'int'], 'Imagick::sepiaToneImage' => ['bool', 'threshold'=>'float'], 'Imagick::setAntiAlias' => ['int', 'antialias'=>'bool'], 'Imagick::setBackgroundColor' => ['bool', 'background'=>'mixed'], 'Imagick::setColorspace' => ['bool', 'colorspace'=>'int'], 'Imagick::setCompression' => ['bool', 'compression'=>'int'], 'Imagick::setCompressionQuality' => ['bool', 'quality'=>'int'], 'Imagick::setFilename' => ['bool', 'filename'=>'string'], 'Imagick::setFirstIterator' => ['bool'], 'Imagick::setFont' => ['bool', 'font'=>'string'], 'Imagick::setFormat' => ['bool', 'format'=>'string'], 'Imagick::setGravity' => ['bool', 'gravity'=>'int'], 'Imagick::setImage' => ['bool', 'replace'=>'imagick'], 'Imagick::setImageAlpha' => ['bool', 'alpha'=>'float'], 'Imagick::setImageAlphaChannel' => ['bool', 'mode'=>'int'], 'Imagick::setImageArtifact' => ['bool', 'artifact'=>'string', 'value'=>'string'], 'Imagick::setImageAttribute' => ['void', 'key'=>'string', 'value'=>'string'], 'Imagick::setImageBackgroundColor' => ['bool', 'background'=>'mixed'], 'Imagick::setImageBias' => ['bool', 'bias'=>'float'], 'Imagick::setImageBiasQuantum' => ['void', 'bias'=>'string'], 'Imagick::setImageBluePrimary' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setImageBorderColor' => ['bool', 'border'=>'mixed'], 'Imagick::setImageChannelDepth' => ['bool', 'channel'=>'int', 'depth'=>'int'], 'Imagick::setImageChannelMask' => ['', 'channel'=>'int'], 'Imagick::setImageClipMask' => ['bool', 'clip_mask'=>'imagick'], 'Imagick::setImageColormapColor' => ['bool', 'index'=>'int', 'color'=>'imagickpixel'], 'Imagick::setImageColorspace' => ['bool', 'colorspace'=>'int'], 'Imagick::setImageCompose' => ['bool', 'compose'=>'int'], 'Imagick::setImageCompression' => ['bool', 'compression'=>'int'], 'Imagick::setImageCompressionQuality' => ['bool', 'quality'=>'int'], 'Imagick::setImageDelay' => ['bool', 'delay'=>'int'], 'Imagick::setImageDepth' => ['bool', 'depth'=>'int'], 'Imagick::setImageDispose' => ['bool', 'dispose'=>'int'], 'Imagick::setImageExtent' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::setImageFilename' => ['bool', 'filename'=>'string'], 'Imagick::setImageFormat' => ['bool', 'format'=>'string'], 'Imagick::setImageGamma' => ['bool', 'gamma'=>'float'], 'Imagick::setImageGravity' => ['bool', 'gravity'=>'int'], 'Imagick::setImageGreenPrimary' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setImageIndex' => ['bool', 'index'=>'int'], 'Imagick::setImageInterlaceScheme' => ['bool', 'interlace_scheme'=>'int'], 'Imagick::setImageInterpolateMethod' => ['bool', 'method'=>'int'], 'Imagick::setImageIterations' => ['bool', 'iterations'=>'int'], 'Imagick::setImageMatte' => ['bool', 'matte'=>'bool'], 'Imagick::setImageMatteColor' => ['bool', 'matte'=>'mixed'], 'Imagick::setImageOpacity' => ['bool', 'opacity'=>'float'], 'Imagick::setImageOrientation' => ['bool', 'orientation'=>'int'], 'Imagick::setImagePage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::setImageProfile' => ['bool', 'name'=>'string', 'profile'=>'string'], 'Imagick::setImageProgressMonitor' => ['', 'filename'=>''], 'Imagick::setImageProperty' => ['bool', 'name'=>'string', 'value'=>'string'], 'Imagick::setImageRedPrimary' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setImageRenderingIntent' => ['bool', 'rendering_intent'=>'int'], 'Imagick::setImageResolution' => ['bool', 'x_resolution'=>'float', 'y_resolution'=>'float'], 'Imagick::setImageScene' => ['bool', 'scene'=>'int'], 'Imagick::setImageTicksPerSecond' => ['bool', 'ticks_per_second'=>'int'], 'Imagick::setImageType' => ['bool', 'image_type'=>'int'], 'Imagick::setImageUnits' => ['bool', 'units'=>'int'], 'Imagick::setImageVirtualPixelMethod' => ['bool', 'method'=>'int'], 'Imagick::setImageWhitePoint' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setInterlaceScheme' => ['bool', 'interlace_scheme'=>'int'], 'Imagick::setIteratorIndex' => ['bool', 'index'=>'int'], 'Imagick::setLastIterator' => ['bool'], 'Imagick::setOption' => ['bool', 'key'=>'string', 'value'=>'string'], 'Imagick::setPage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::setPointSize' => ['bool', 'point_size'=>'float'], 'Imagick::setProgressMonitor' => ['void', 'callback'=>'callable'], 'Imagick::setRegistry' => ['void', 'key'=>'string', 'value'=>'string'], 'Imagick::setResolution' => ['bool', 'x_resolution'=>'float', 'y_resolution'=>'float'], 'Imagick::setResourceLimit' => ['bool', 'type'=>'int', 'limit'=>'int'], 'Imagick::setSamplingFactors' => ['bool', 'factors'=>'array'], 'Imagick::setSize' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::setSizeOffset' => ['bool', 'columns'=>'int', 'rows'=>'int', 'offset'=>'int'], 'Imagick::setType' => ['bool', 'image_type'=>'int'], 'Imagick::shadeImage' => ['bool', 'gray'=>'bool', 'azimuth'=>'float', 'elevation'=>'float'], 'Imagick::shadowImage' => ['bool', 'opacity'=>'float', 'sigma'=>'float', 'x'=>'int', 'y'=>'int'], 'Imagick::sharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::shaveImage' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::shearImage' => ['bool', 'background'=>'mixed', 'x_shear'=>'float', 'y_shear'=>'float'], 'Imagick::sigmoidalContrastImage' => ['bool', 'sharpen'=>'bool', 'alpha'=>'float', 'beta'=>'float', 'channel='=>'int'], 'Imagick::similarityImage' => ['Imagick', 'imagick'=>'Imagick', '&bestMatch'=>'array', '&similarity'=>'float', 'similarity_threshold'=>'float', 'metric'=>'int'], 'Imagick::sketchImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float'], 'Imagick::smushImages' => ['Imagick', 'stack'=>'string', 'offset'=>'string'], 'Imagick::solarizeImage' => ['bool', 'threshold'=>'int'], 'Imagick::sparseColorImage' => ['bool', 'sparse_method'=>'int', 'arguments'=>'array', 'channel='=>'int'], 'Imagick::spliceImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::spreadImage' => ['bool', 'radius'=>'float'], 'Imagick::statisticImage' => ['void', 'type'=>'int', 'width'=>'int', 'height'=>'int', 'CHANNEL='=>'string'], 'Imagick::steganoImage' => ['Imagick', 'watermark_wand'=>'imagick', 'offset'=>'int'], 'Imagick::stereoImage' => ['bool', 'offset_wand'=>'imagick'], 'Imagick::stripImage' => ['bool'], 'Imagick::subImageMatch' => ['Imagick', 'Imagick'=>'Imagick', '&w_offset='=>'array', '&w_similarity='=>'float'], 'Imagick::swirlImage' => ['bool', 'degrees'=>'float'], 'Imagick::textureImage' => ['bool', 'texture_wand'=>'imagick'], 'Imagick::thresholdImage' => ['bool', 'threshold'=>'float', 'channel='=>'int'], 'Imagick::thumbnailImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'bestfit='=>'bool', 'fill='=>'bool', 'legacy='=>'bool'], 'Imagick::tintImage' => ['bool', 'tint'=>'mixed', 'opacity'=>'mixed'], 'Imagick::transformImage' => ['Imagick', 'crop'=>'string', 'geometry'=>'string'], 'Imagick::transformImageColorspace' => ['bool', 'colorspace'=>'int'], 'Imagick::transparentPaintImage' => ['bool', 'target'=>'mixed', 'alpha'=>'float', 'fuzz'=>'float', 'invert'=>'bool'], 'Imagick::transposeImage' => ['bool'], 'Imagick::transverseImage' => ['bool'], 'Imagick::trimImage' => ['bool', 'fuzz'=>'float'], 'Imagick::uniqueImageColors' => ['bool'], 'Imagick::unsharpMaskImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'amount'=>'float', 'threshold'=>'float', 'channel='=>'int'], 'Imagick::valid' => ['bool'], 'Imagick::vignetteImage' => ['bool', 'blackpoint'=>'float', 'whitepoint'=>'float', 'x'=>'int', 'y'=>'int'], 'Imagick::waveImage' => ['bool', 'amplitude'=>'float', 'length'=>'float'], 'Imagick::whiteThresholdImage' => ['bool', 'threshold'=>'mixed'], 'Imagick::writeImage' => ['bool', 'filename='=>'string'], 'Imagick::writeImageFile' => ['bool', 'filehandle'=>'resource'], 'Imagick::writeImages' => ['bool', 'filename'=>'string', 'adjoin'=>'bool'], 'Imagick::writeImagesFile' => ['bool', 'filehandle'=>'resource'], 'ImagickDraw::__construct' => ['void'], 'ImagickDraw::affine' => ['bool', 'affine'=>'array'], 'ImagickDraw::annotation' => ['bool', 'x'=>'float', 'y'=>'float', 'text'=>'string'], 'ImagickDraw::arc' => ['bool', 'sx'=>'float', 'sy'=>'float', 'ex'=>'float', 'ey'=>'float', 'sd'=>'float', 'ed'=>'float'], 'ImagickDraw::bezier' => ['bool', 'coordinates'=>'array'], 'ImagickDraw::circle' => ['bool', 'ox'=>'float', 'oy'=>'float', 'px'=>'float', 'py'=>'float'], 'ImagickDraw::clear' => ['bool'], 'ImagickDraw::clone' => ['ImagickDraw'], 'ImagickDraw::color' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'int'], 'ImagickDraw::comment' => ['bool', 'comment'=>'string'], 'ImagickDraw::composite' => ['bool', 'compose'=>'int', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float', 'compositewand'=>'imagick'], 'ImagickDraw::destroy' => ['bool'], 'ImagickDraw::ellipse' => ['bool', 'ox'=>'float', 'oy'=>'float', 'rx'=>'float', 'ry'=>'float', 'start'=>'float', 'end'=>'float'], 'ImagickDraw::getBorderColor' => ['ImagickPixel'], 'ImagickDraw::getClipPath' => ['string|false'], 'ImagickDraw::getClipRule' => ['int'], 'ImagickDraw::getClipUnits' => ['int'], 'ImagickDraw::getDensity' => ['?string'], 'ImagickDraw::getFillColor' => ['ImagickPixel'], 'ImagickDraw::getFillOpacity' => ['float'], 'ImagickDraw::getFillRule' => ['int'], 'ImagickDraw::getFont' => ['string|false'], 'ImagickDraw::getFontFamily' => ['string|false'], 'ImagickDraw::getFontResolution' => ['array'], 'ImagickDraw::getFontSize' => ['float'], 'ImagickDraw::getFontStretch' => ['int'], 'ImagickDraw::getFontStyle' => ['int'], 'ImagickDraw::getFontWeight' => ['int'], 'ImagickDraw::getGravity' => ['int'], 'ImagickDraw::getOpacity' => ['float'], 'ImagickDraw::getStrokeAntialias' => ['bool'], 'ImagickDraw::getStrokeColor' => ['ImagickPixel'], 'ImagickDraw::getStrokeDashArray' => ['array'], 'ImagickDraw::getStrokeDashOffset' => ['float'], 'ImagickDraw::getStrokeLineCap' => ['int'], 'ImagickDraw::getStrokeLineJoin' => ['int'], 'ImagickDraw::getStrokeMiterLimit' => ['int'], 'ImagickDraw::getStrokeOpacity' => ['float'], 'ImagickDraw::getStrokeWidth' => ['float'], 'ImagickDraw::getTextAlignment' => ['int'], 'ImagickDraw::getTextAntialias' => ['bool'], 'ImagickDraw::getTextDecoration' => ['int'], 'ImagickDraw::getTextDirection' => ['bool'], 'ImagickDraw::getTextEncoding' => ['string'], 'ImagickDraw::getTextInterlineSpacing' => ['float'], 'ImagickDraw::getTextInterwordSpacing' => ['float'], 'ImagickDraw::getTextKerning' => ['float'], 'ImagickDraw::getTextUnderColor' => ['ImagickPixel'], 'ImagickDraw::getVectorGraphics' => ['string'], 'ImagickDraw::line' => ['bool', 'sx'=>'float', 'sy'=>'float', 'ex'=>'float', 'ey'=>'float'], 'ImagickDraw::matte' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'int'], 'ImagickDraw::pathClose' => ['bool'], 'ImagickDraw::pathCurveToAbsolute' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToQuadraticBezierAbsolute' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToQuadraticBezierRelative' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToQuadraticBezierSmoothAbsolute' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToQuadraticBezierSmoothRelative' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToRelative' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToSmoothAbsolute' => ['bool', 'x2'=>'float', 'y2'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToSmoothRelative' => ['bool', 'x2'=>'float', 'y2'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathEllipticArcAbsolute' => ['bool', 'rx'=>'float', 'ry'=>'float', 'x_axis_rotation'=>'float', 'large_arc_flag'=>'bool', 'sweep_flag'=>'bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathEllipticArcRelative' => ['bool', 'rx'=>'float', 'ry'=>'float', 'x_axis_rotation'=>'float', 'large_arc_flag'=>'bool', 'sweep_flag'=>'bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathFinish' => ['bool'], 'ImagickDraw::pathLineToAbsolute' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathLineToHorizontalAbsolute' => ['bool', 'x'=>'float'], 'ImagickDraw::pathLineToHorizontalRelative' => ['bool', 'x'=>'float'], 'ImagickDraw::pathLineToRelative' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathLineToVerticalAbsolute' => ['bool', 'y'=>'float'], 'ImagickDraw::pathLineToVerticalRelative' => ['bool', 'y'=>'float'], 'ImagickDraw::pathMoveToAbsolute' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathMoveToRelative' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathStart' => ['bool'], 'ImagickDraw::point' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::polygon' => ['bool', 'coordinates'=>'array'], 'ImagickDraw::polyline' => ['bool', 'coordinates'=>'array'], 'ImagickDraw::pop' => ['bool'], 'ImagickDraw::popClipPath' => ['bool'], 'ImagickDraw::popDefs' => ['bool'], 'ImagickDraw::popPattern' => ['bool'], 'ImagickDraw::push' => ['bool'], 'ImagickDraw::pushClipPath' => ['bool', 'clip_mask_id'=>'string'], 'ImagickDraw::pushDefs' => ['bool'], 'ImagickDraw::pushPattern' => ['bool', 'pattern_id'=>'string', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'ImagickDraw::rectangle' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float'], 'ImagickDraw::render' => ['bool'], 'ImagickDraw::resetVectorGraphics' => ['void'], 'ImagickDraw::rotate' => ['bool', 'degrees'=>'float'], 'ImagickDraw::roundRectangle' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'rx'=>'float', 'ry'=>'float'], 'ImagickDraw::scale' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::setBorderColor' => ['bool', 'color'=>'ImagickPixel|string'], 'ImagickDraw::setClipPath' => ['bool', 'clip_mask'=>'string'], 'ImagickDraw::setClipRule' => ['bool', 'fill_rule'=>'int'], 'ImagickDraw::setClipUnits' => ['bool', 'clip_units'=>'int'], 'ImagickDraw::setDensity' => ['bool', 'density_string'=>'string'], 'ImagickDraw::setFillAlpha' => ['bool', 'opacity'=>'float'], 'ImagickDraw::setFillColor' => ['bool', 'fill_pixel'=>'ImagickPixel|string'], 'ImagickDraw::setFillOpacity' => ['bool', 'fillopacity'=>'float'], 'ImagickDraw::setFillPatternURL' => ['bool', 'fill_url'=>'string'], 'ImagickDraw::setFillRule' => ['bool', 'fill_rule'=>'int'], 'ImagickDraw::setFont' => ['bool', 'font_name'=>'string'], 'ImagickDraw::setFontFamily' => ['bool', 'font_family'=>'string'], 'ImagickDraw::setFontResolution' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::setFontSize' => ['bool', 'pointsize'=>'float'], 'ImagickDraw::setFontStretch' => ['bool', 'fontstretch'=>'int'], 'ImagickDraw::setFontStyle' => ['bool', 'style'=>'int'], 'ImagickDraw::setFontWeight' => ['bool', 'font_weight'=>'int'], 'ImagickDraw::setGravity' => ['bool', 'gravity'=>'int'], 'ImagickDraw::setOpacity' => ['void', 'opacity'=>'float'], 'ImagickDraw::setResolution' => ['void', 'x_resolution'=>'float', 'y_resolution'=>'float'], 'ImagickDraw::setStrokeAlpha' => ['bool', 'opacity'=>'float'], 'ImagickDraw::setStrokeAntialias' => ['bool', 'stroke_antialias'=>'bool'], 'ImagickDraw::setStrokeColor' => ['bool', 'stroke_pixel'=>'ImagickPixel|string'], 'ImagickDraw::setStrokeDashArray' => ['bool', 'dasharray'=>'array'], 'ImagickDraw::setStrokeDashOffset' => ['bool', 'dash_offset'=>'float'], 'ImagickDraw::setStrokeLineCap' => ['bool', 'linecap'=>'int'], 'ImagickDraw::setStrokeLineJoin' => ['bool', 'linejoin'=>'int'], 'ImagickDraw::setStrokeMiterLimit' => ['bool', 'miterlimit'=>'int'], 'ImagickDraw::setStrokeOpacity' => ['bool', 'stroke_opacity'=>'float'], 'ImagickDraw::setStrokePatternURL' => ['bool', 'stroke_url'=>'string'], 'ImagickDraw::setStrokeWidth' => ['bool', 'stroke_width'=>'float'], 'ImagickDraw::setTextAlignment' => ['bool', 'alignment'=>'int'], 'ImagickDraw::setTextAntialias' => ['bool', 'antialias'=>'bool'], 'ImagickDraw::setTextDecoration' => ['bool', 'decoration'=>'int'], 'ImagickDraw::setTextDirection' => ['bool', 'direction'=>'int'], 'ImagickDraw::setTextEncoding' => ['bool', 'encoding'=>'string'], 'ImagickDraw::setTextInterlineSpacing' => ['void', 'spacing'=>'float'], 'ImagickDraw::setTextInterwordSpacing' => ['void', 'spacing'=>'float'], 'ImagickDraw::setTextKerning' => ['void', 'kerning'=>'float'], 'ImagickDraw::setTextUnderColor' => ['bool', 'under_color'=>'ImagickPixel|string'], 'ImagickDraw::setVectorGraphics' => ['bool', 'xml'=>'string'], 'ImagickDraw::setViewbox' => ['bool', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int'], 'ImagickDraw::skewX' => ['bool', 'degrees'=>'float'], 'ImagickDraw::skewY' => ['bool', 'degrees'=>'float'], 'ImagickDraw::translate' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickKernel::addKernel' => ['void', 'ImagickKernel'=>'ImagickKernel'], 'ImagickKernel::addUnityKernel' => ['void'], 'ImagickKernel::fromBuiltin' => ['ImagickKernel', 'kernelType'=>'string', 'kernelString'=>'string'], 'ImagickKernel::fromMatrix' => ['ImagickKernel', 'matrix'=>'array', 'origin='=>'array'], 'ImagickKernel::getMatrix' => ['array'], 'ImagickKernel::scale' => ['void'], 'ImagickKernel::separate' => ['array'], 'ImagickKernel::seperate' => ['void'], 'ImagickPixel::__construct' => ['void', 'color='=>'string'], 'ImagickPixel::clear' => ['bool'], 'ImagickPixel::clone' => ['void'], 'ImagickPixel::destroy' => ['bool'], 'ImagickPixel::getColor' => ['array', 'normalized='=>'bool'], 'ImagickPixel::getColorAsString' => ['string'], 'ImagickPixel::getColorCount' => ['int'], 'ImagickPixel::getColorQuantum' => ['mixed'], 'ImagickPixel::getColorValue' => ['float', 'color'=>'int'], 'ImagickPixel::getColorValueQuantum' => ['mixed'], 'ImagickPixel::getHSL' => ['array'], 'ImagickPixel::getIndex' => ['int'], 'ImagickPixel::isPixelSimilar' => ['bool', 'color'=>'ImagickPixel', 'fuzz'=>'float'], 'ImagickPixel::isPixelSimilarQuantum' => ['bool', 'color'=>'string', 'fuzz='=>'string'], 'ImagickPixel::isSimilar' => ['bool', 'color'=>'imagickpixel', 'fuzz'=>'float'], 'ImagickPixel::setColor' => ['bool', 'color'=>'string'], 'ImagickPixel::setcolorcount' => ['void', 'colorCount'=>'string'], 'ImagickPixel::setColorFromPixel' => ['bool', 'srcPixel'=>'ImagickPixel'], 'ImagickPixel::setColorValue' => ['bool', 'color'=>'int', 'value'=>'float'], 'ImagickPixel::setColorValueQuantum' => ['void', 'color'=>'int', 'value'=>'mixed'], 'ImagickPixel::setHSL' => ['bool', 'hue'=>'float', 'saturation'=>'float', 'luminosity'=>'float'], 'ImagickPixel::setIndex' => ['void', 'index'=>'int'], 'ImagickPixelIterator::__construct' => ['void', 'wand'=>'imagick'], 'ImagickPixelIterator::clear' => ['bool'], 'ImagickPixelIterator::current' => ['mixed'], 'ImagickPixelIterator::destroy' => ['bool'], 'ImagickPixelIterator::getCurrentIteratorRow' => ['array'], 'ImagickPixelIterator::getIteratorRow' => ['int'], 'ImagickPixelIterator::getNextIteratorRow' => ['array'], 'ImagickPixelIterator::getpixeliterator' => ['', 'Imagick'=>'Imagick'], 'ImagickPixelIterator::getpixelregioniterator' => ['', 'Imagick'=>'Imagick', 'x'=>'', 'y'=>'', 'columns'=>'', 'rows'=>''], 'ImagickPixelIterator::getPreviousIteratorRow' => ['array'], 'ImagickPixelIterator::key' => ['int|string'], 'ImagickPixelIterator::newPixelIterator' => ['bool', 'wand'=>'imagick'], 'ImagickPixelIterator::newPixelRegionIterator' => ['bool', 'wand'=>'imagick', 'x'=>'int', 'y'=>'int', 'columns'=>'int', 'rows'=>'int'], 'ImagickPixelIterator::next' => ['void'], 'ImagickPixelIterator::resetIterator' => ['bool'], 'ImagickPixelIterator::rewind' => ['void'], 'ImagickPixelIterator::setIteratorFirstRow' => ['bool'], 'ImagickPixelIterator::setIteratorLastRow' => ['bool'], 'ImagickPixelIterator::setIteratorRow' => ['bool', 'row'=>'int'], 'ImagickPixelIterator::syncIterator' => ['bool'], 'ImagickPixelIterator::valid' => ['bool'], 'imap_8bit' => ['string|false', 'text'=>'string'], 'imap_alerts' => ['array|false'], 'imap_append' => ['bool', 'stream_id'=>'resource', 'folder'=>'string', 'message'=>'string', 'options='=>'string', 'internal_date='=>'string'], 'imap_base64' => ['string|false', 'text'=>'string'], 'imap_binary' => ['string|false', 'text'=>'string'], 'imap_body' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'options='=>'int'], 'imap_bodystruct' => ['stdClass|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'section'=>'string'], 'imap_check' => ['stdClass|false', 'stream_id'=>'resource'], 'imap_clearflag_full' => ['bool', 'stream_id'=>'resource', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], 'imap_close' => ['bool', 'stream_id'=>'resource', 'options='=>'int'], 'imap_create' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_createmailbox' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_delete' => ['bool', 'stream_id'=>'resource', 'msg_no'=>'int', 'options='=>'int'], 'imap_deletemailbox' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_errors' => ['array|false'], 'imap_expunge' => ['bool', 'stream_id'=>'resource'], 'imap_fetch_overview' => ['array|false', 'stream_id'=>'resource', 'sequence'=>'string', 'options='=>'int'], 'imap_fetchbody' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'section'=>'string', 'options='=>'int'], 'imap_fetchheader' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'options='=>'int'], 'imap_fetchmime' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'section'=>'string', 'options='=>'int'], 'imap_fetchstructure' => ['stdClass|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'options='=>'int'], 'imap_fetchtext' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'options='=>'int'], 'imap_gc' => ['bool', 'stream_id'=>'resource', 'flags'=>'int'], 'imap_get_quota' => ['array|false', 'stream_id'=>'resource', 'qroot'=>'string'], 'imap_get_quotaroot' => ['array|false', 'stream_id'=>'resource', 'mbox'=>'string'], 'imap_getacl' => ['array|false', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_getmailboxes' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_getsubscribed' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_header' => ['stdClass|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'from_length='=>'int', 'subject_length='=>'int', 'default_host='=>'string'], 'imap_headerinfo' => ['stdClass|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'from_length='=>'int', 'subject_length='=>'int', 'default_host='=>'string|null'], 'imap_headers' => ['array|false', 'stream_id'=>'resource'], 'imap_last_error' => ['string|false'], 'imap_list' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_listmailbox' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_listscan' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string', 'content'=>'string'], 'imap_listsubscribed' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_lsub' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_mail' => ['bool', 'to'=>'string', 'subject'=>'string', 'message'=>'string', 'additional_headers='=>'string', 'cc='=>'string', 'bcc='=>'string', 'rpath='=>'string'], 'imap_mail_compose' => ['string|false', 'envelope'=>'array', 'body'=>'array'], 'imap_mail_copy' => ['bool', 'stream_id'=>'resource', 'msglist'=>'string', 'mailbox'=>'string', 'options='=>'int'], 'imap_mail_move' => ['bool', 'stream_id'=>'resource', 'sequence'=>'string', 'mailbox'=>'string', 'options='=>'int'], 'imap_mailboxmsginfo' => ['stdClass|false', 'stream_id'=>'resource'], 'imap_mime_header_decode' => ['array|false', 'string'=>'string'], 'imap_msgno' => ['int|false', 'stream_id'=>'resource', 'unique_msg_id'=>'int'], 'imap_mutf7_to_utf8' => ['string|false', 'in'=>'string'], 'imap_num_msg' => ['int|false', 'stream_id'=>'resource'], 'imap_num_recent' => ['int|false', 'stream_id'=>'resource'], 'imap_open' => ['resource|false', 'mailbox'=>'string', 'user'=>'string', 'password'=>'string', 'options='=>'int', 'n_retries='=>'int', 'params='=>'?array'], 'imap_ping' => ['bool', 'stream_id'=>'resource'], 'imap_qprint' => ['string|false', 'text'=>'string'], 'imap_rename' => ['bool', 'stream_id'=>'resource', 'old_name'=>'string', 'new_name'=>'string'], 'imap_renamemailbox' => ['bool', 'stream_id'=>'resource', 'old_name'=>'string', 'new_name'=>'string'], 'imap_reopen' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string', 'options='=>'int', 'n_retries='=>'int'], 'imap_rfc822_parse_adrlist' => ['array', 'address_string'=>'string', 'default_host'=>'string'], 'imap_rfc822_parse_headers' => ['stdClass', 'headers'=>'string', 'default_host='=>'string'], 'imap_rfc822_write_address' => ['string|false', 'mailbox'=>'?string', 'host'=>'?string', 'personal'=>'?string'], 'imap_savebody' => ['bool', 'stream_id'=>'resource', 'file'=>'string|resource', 'msg_no'=>'int', 'section='=>'string', 'options='=>'int'], 'imap_scan' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string', 'content'=>'string'], 'imap_scanmailbox' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string', 'content'=>'string'], 'imap_search' => ['array|false', 'stream_id'=>'resource', 'criteria'=>'string', 'options='=>'int', 'charset='=>'string'], 'imap_set_quota' => ['bool', 'stream_id'=>'resource', 'qroot'=>'string', 'mailbox_size'=>'int'], 'imap_setacl' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string', 'id'=>'string', 'rights'=>'string'], 'imap_setflag_full' => ['bool', 'stream_id'=>'resource', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], 'imap_sort' => ['array|false', 'stream_id'=>'resource', 'criteria'=>'int', 'reverse'=>'int', 'options='=>'int', 'search_criteria='=>'string', 'charset='=>'string'], 'imap_status' => ['stdClass|false', 'stream_id'=>'resource', 'mailbox'=>'string', 'options'=>'int'], 'imap_subscribe' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_thread' => ['array|false', 'stream_id'=>'resource', 'options='=>'int'], 'imap_timeout' => ['int|bool', 'timeout_type'=>'int', 'timeout='=>'int'], 'imap_uid' => ['int|false', 'stream_id'=>'resource', 'msg_no'=>'int'], 'imap_undelete' => ['bool', 'stream_id'=>'resource', 'msg_no'=>'int', 'flags='=>'int'], 'imap_unsubscribe' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_utf7_decode' => ['string|false', 'buf'=>'string'], 'imap_utf7_encode' => ['string', 'buf'=>'string'], 'imap_utf8' => ['string', 'mime_encoded_text'=>'string'], 'imap_utf8_to_mutf7' => ['string|false', 'in'=>'string'], 'implode' => ['string', 'glue'=>'string', 'pieces'=>'array'], 'implode\'1' => ['string', 'pieces'=>'array'], 'import_request_variables' => ['bool', 'types'=>'string', 'prefix='=>'string'], 'in_array' => ['bool', 'needle'=>'mixed', 'haystack'=>'array', 'strict='=>'bool'], 'inclued_get_data' => ['array'], 'inet_ntop' => ['string|false', 'in_addr'=>'string'], 'inet_pton' => ['string|false', 'ip_address'=>'string'], 'InfiniteIterator::__construct' => ['void', 'iterator'=>'Iterator'], 'InfiniteIterator::current' => ['mixed'], 'InfiniteIterator::getInnerIterator' => ['Traversable'], 'InfiniteIterator::key' => ['bool|float|int|string'], 'InfiniteIterator::next' => ['void'], 'InfiniteIterator::rewind' => ['void'], 'InfiniteIterator::valid' => ['bool'], 'inflate_add' => ['string|false', 'context'=>'resource', 'encoded_data'=>'string', 'flush_mode='=>'int'], 'inflate_get_read_len' => ['int|false', 'resource'=>'resource'], 'inflate_get_status' => ['int|false', 'resource'=>'resource'], 'inflate_init' => ['resource|false', 'encoding'=>'int', 'options='=>'array'], 'ingres_autocommit' => ['bool', 'link'=>'resource'], 'ingres_autocommit_state' => ['bool', 'link'=>'resource'], 'ingres_charset' => ['string', 'link'=>'resource'], 'ingres_close' => ['bool', 'link'=>'resource'], 'ingres_commit' => ['bool', 'link'=>'resource'], 'ingres_connect' => ['resource', 'database='=>'string', 'username='=>'string', 'password='=>'string', 'options='=>'array'], 'ingres_cursor' => ['string', 'result'=>'resource'], 'ingres_errno' => ['int', 'link='=>'resource'], 'ingres_error' => ['string', 'link='=>'resource'], 'ingres_errsqlstate' => ['string', 'link='=>'resource'], 'ingres_escape_string' => ['string', 'link'=>'resource', 'source_string'=>'string'], 'ingres_execute' => ['bool', 'result'=>'resource', 'params='=>'array', 'types='=>'string'], 'ingres_fetch_array' => ['array', 'result'=>'resource', 'result_type='=>'int'], 'ingres_fetch_assoc' => ['array', 'result'=>'resource'], 'ingres_fetch_object' => ['object', 'result'=>'resource', 'result_type='=>'int'], 'ingres_fetch_proc_return' => ['int', 'result'=>'resource'], 'ingres_fetch_row' => ['array', 'result'=>'resource'], 'ingres_field_length' => ['int', 'result'=>'resource', 'index'=>'int'], 'ingres_field_name' => ['string', 'result'=>'resource', 'index'=>'int'], 'ingres_field_nullable' => ['bool', 'result'=>'resource', 'index'=>'int'], 'ingres_field_precision' => ['int', 'result'=>'resource', 'index'=>'int'], 'ingres_field_scale' => ['int', 'result'=>'resource', 'index'=>'int'], 'ingres_field_type' => ['string', 'result'=>'resource', 'index'=>'int'], 'ingres_free_result' => ['bool', 'result'=>'resource'], 'ingres_next_error' => ['bool', 'link='=>'resource'], 'ingres_num_fields' => ['int', 'result'=>'resource'], 'ingres_num_rows' => ['int', 'result'=>'resource'], 'ingres_pconnect' => ['resource', 'database='=>'string', 'username='=>'string', 'password='=>'string', 'options='=>'array'], 'ingres_prepare' => ['mixed', 'link'=>'resource', 'query'=>'string'], 'ingres_query' => ['mixed', 'link'=>'resource', 'query'=>'string', 'params='=>'array', 'types='=>'string'], 'ingres_result_seek' => ['bool', 'result'=>'resource', 'position'=>'int'], 'ingres_rollback' => ['bool', 'link'=>'resource'], 'ingres_set_environment' => ['bool', 'link'=>'resource', 'options'=>'array'], 'ingres_unbuffered_query' => ['mixed', 'link'=>'resource', 'query'=>'string', 'params='=>'array', 'types='=>'string'], 'ini_alter' => ['string|false', 'varname'=>'string', 'newvalue'=>'string'], 'ini_get' => ['string|false', 'varname'=>'string'], 'ini_get_all' => ['array|false', 'extension='=>'?string', 'details='=>'bool'], 'ini_restore' => ['void', 'varname'=>'string'], 'ini_set' => ['string|false', 'varname'=>'string', 'newvalue'=>'string'], 'inotify_add_watch' => ['int', 'inotify_instance'=>'resource', 'pathname'=>'string', 'mask'=>'int'], 'inotify_init' => ['resource|false'], 'inotify_queue_len' => ['int', 'inotify_instance'=>'resource'], 'inotify_read' => ['array|false', 'inotify_instance'=>'resource'], 'inotify_rm_watch' => ['bool', 'inotify_instance'=>'resource', 'watch_descriptor'=>'int'], 'intdiv' => ['int', 'numerator'=>'int', 'divisor'=>'int'], 'interface_exists' => ['bool', 'classname'=>'string', 'autoload='=>'bool'], 'intl_error_name' => ['string', 'error_code'=>'int'], 'intl_get_error_code' => ['int'], 'intl_get_error_message' => ['string'], 'intl_is_failure' => ['bool', 'error_code'=>'int'], 'IntlBreakIterator::__construct' => ['void'], 'IntlBreakIterator::createCharacterInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::createCodePointInstance' => ['IntlCodePointBreakIterator'], 'IntlBreakIterator::createLineInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::createSentenceInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::createTitleInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::createWordInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::current' => ['int'], 'IntlBreakIterator::first' => ['int'], 'IntlBreakIterator::following' => ['int', 'offset'=>'int'], 'IntlBreakIterator::getErrorCode' => ['int'], 'IntlBreakIterator::getErrorMessage' => ['string'], 'IntlBreakIterator::getLocale' => ['string', 'locale_type'=>'string'], 'IntlBreakIterator::getPartsIterator' => ['IntlPartsIterator', 'key_type='=>'int'], 'IntlBreakIterator::getText' => ['string'], 'IntlBreakIterator::isBoundary' => ['bool', 'offset'=>'int'], 'IntlBreakIterator::last' => ['int'], 'IntlBreakIterator::next' => ['int', 'offset='=>'int'], 'IntlBreakIterator::preceding' => ['int', 'offset'=>'int'], 'IntlBreakIterator::previous' => ['int'], 'IntlBreakIterator::setText' => ['bool', 'text'=>'string'], 'intlcal_add' => ['bool', 'calendar'=>'IntlCalendar', 'field'=>'int', 'amount'=>'int'], 'intlcal_after' => ['bool', 'calendar'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_before' => ['bool', 'calendar'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_clear' => ['bool', 'calendar'=>'IntlCalendar', 'field='=>'int'], 'intlcal_create_instance' => ['IntlCalendar', 'timeZone='=>'mixed', 'locale='=>'string'], 'intlcal_equals' => ['bool', 'calendar'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_field_difference' => ['int', 'calendar'=>'IntlCalendar', 'when'=>'float', 'field'=>'int'], 'intlcal_from_date_time' => ['IntlCalendar', 'dateTime'=>'DateTime|string'], 'intlcal_get' => ['mixed', 'calendar'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_actual_maximum' => ['int', 'calendar'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_actual_minimum' => ['int', 'calendar'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_available_locales' => ['array'], 'intlcal_get_day_of_week_type' => ['int', 'calendar'=>'IntlCalendar', 'dayOfWeek'=>'int'], 'intlcal_get_first_day_of_week' => ['int', 'calendar'=>'IntlCalendar'], 'intlcal_get_greatest_minimum' => ['int', 'calendar'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_keyword_values_for_locale' => ['Iterator|false', 'key'=>'string', 'locale'=>'string', 'commonlyUsed'=>'bool'], 'intlcal_get_least_maximum' => ['int', 'calendar'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_locale' => ['string', 'calendar'=>'IntlCalendar', 'localeType'=>'int'], 'intlcal_get_maximum' => ['int|false', 'calendar'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_minimal_days_in_first_week' => ['int', 'calendar'=>'IntlCalendar'], 'intlcal_get_minimum' => ['int', 'calendar'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_now' => ['float'], 'intlcal_get_repeated_wall_time_option' => ['int', 'calendar'=>'IntlCalendar'], 'intlcal_get_skipped_wall_time_option' => ['int', 'calendar'=>'IntlCalendar'], 'intlcal_get_time' => ['float', 'calendar'=>'IntlCalendar'], 'intlcal_get_time_zone' => ['IntlTimeZone', 'calendar'=>'IntlCalendar'], 'intlcal_get_type' => ['string', 'calendar'=>'IntlCalendar'], 'intlcal_get_weekend_transition' => ['int', 'calendar'=>'IntlCalendar', 'dayOfWeek'=>'string'], 'intlcal_in_daylight_time' => ['bool', 'calendar'=>'IntlCalendar'], 'intlcal_is_equivalent_to' => ['bool', 'calendar'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_is_lenient' => ['bool', 'calendar'=>'IntlCalendar'], 'intlcal_is_set' => ['bool', 'calendar'=>'IntlCalendar', 'field'=>'int'], 'intlcal_is_weekend' => ['bool', 'calendar'=>'IntlCalendar', 'date='=>'float'], 'intlcal_roll' => ['bool', 'calendar'=>'IntlCalendar', 'field'=>'int', 'amountOrUpOrDown'=>'mixed'], 'intlcal_set' => ['bool', 'calendar'=>'IntlCalendar', 'field'=>'int', 'value'=>'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', 'isLenient'=>'bool'], 'intlcal_set_repeated_wall_time_option' => ['bool', 'calendar'=>'IntlCalendar', 'wallTimeOption'=>'int'], 'intlcal_set_skipped_wall_time_option' => ['bool', 'calendar'=>'IntlCalendar', 'wallTimeOption'=>'int'], 'intlcal_set_time' => ['bool', 'calendar'=>'IntlCalendar', 'date'=>'float'], 'intlcal_set_time_zone' => ['bool', 'calendar'=>'IntlCalendar', 'timeZone'=>'mixed'], 'intlcal_to_date_time' => ['DateTime|false', 'calendar'=>'IntlCalendar'], 'IntlCalendar::__construct' => ['void'], 'IntlCalendar::add' => ['bool', 'field'=>'int', 'amount'=>'int'], 'IntlCalendar::after' => ['bool', 'other'=>'IntlCalendar'], 'IntlCalendar::before' => ['bool', 'other'=>'IntlCalendar'], 'IntlCalendar::clear' => ['bool', 'field='=>'int'], 'IntlCalendar::createInstance' => ['IntlCalendar', 'timeZone='=>'mixed', 'locale='=>'string'], 'IntlCalendar::equals' => ['bool', 'other'=>'IntlCalendar'], 'IntlCalendar::fieldDifference' => ['int', 'when'=>'float', 'field'=>'int'], 'IntlCalendar::fromDateTime' => ['IntlCalendar', 'dateTime'=>'DateTime|string'], 'IntlCalendar::get' => ['int', 'field'=>'int'], 'IntlCalendar::getActualMaximum' => ['int', 'field'=>'int'], 'IntlCalendar::getActualMinimum' => ['int', 'field'=>'int'], 'IntlCalendar::getAvailableLocales' => ['array'], 'IntlCalendar::getDayOfWeekType' => ['int', 'dayOfWeek'=>'int'], 'IntlCalendar::getErrorCode' => ['int'], 'IntlCalendar::getErrorMessage' => ['string'], 'IntlCalendar::getFirstDayOfWeek' => ['int'], 'IntlCalendar::getGreatestMinimum' => ['int', 'field'=>'int'], 'IntlCalendar::getKeywordValuesForLocale' => ['Iterator|false', 'key'=>'string', 'locale'=>'string', 'commonlyUsed'=>'bool'], 'IntlCalendar::getLeastMaximum' => ['int', 'field'=>'int'], 'IntlCalendar::getLocale' => ['string', 'localeType'=>'int'], 'IntlCalendar::getMaximum' => ['int|false', 'field'=>'int'], 'IntlCalendar::getMinimalDaysInFirstWeek' => ['int'], 'IntlCalendar::getMinimum' => ['int', 'field'=>'int'], 'IntlCalendar::getNow' => ['float'], 'IntlCalendar::getRepeatedWallTimeOption' => ['int'], 'IntlCalendar::getSkippedWallTimeOption' => ['int'], 'IntlCalendar::getTime' => ['float'], 'IntlCalendar::getTimeZone' => ['IntlTimeZone'], 'IntlCalendar::getType' => ['string'], 'IntlCalendar::getWeekendTransition' => ['int', 'dayOfWeek'=>'string'], 'IntlCalendar::inDaylightTime' => ['bool'], 'IntlCalendar::isEquivalentTo' => ['bool', 'other'=>'IntlCalendar'], 'IntlCalendar::isLenient' => ['bool'], 'IntlCalendar::isSet' => ['bool', 'field'=>'int'], 'IntlCalendar::isWeekend' => ['bool', 'date='=>'float'], 'IntlCalendar::roll' => ['bool', 'field'=>'int', 'amountOrUpOrDown'=>'mixed'], 'IntlCalendar::set' => ['bool', 'field'=>'int', 'value'=>'int'], 'IntlCalendar::set\'1' => ['bool', 'year'=>'int', 'month'=>'int', 'dayOfMonth='=>'int', 'hour='=>'int', 'minute='=>'int', 'second='=>'int'], 'IntlCalendar::setFirstDayOfWeek' => ['bool', 'dayOfWeek'=>'int'], 'IntlCalendar::setLenient' => ['bool', 'isLenient'=>'string'], 'IntlCalendar::setMinimalDaysInFirstWeek' => ['bool', 'minimalDays'=>'int'], 'IntlCalendar::setRepeatedWallTimeOption' => ['bool', 'wallTimeOption'=>'int'], 'IntlCalendar::setSkippedWallTimeOption' => ['bool', 'wallTimeOption'=>'int'], 'IntlCalendar::setTime' => ['bool', 'date'=>'float'], 'IntlCalendar::setTimeZone' => ['bool', 'timeZone'=>'mixed'], 'IntlCalendar::toDateTime' => ['DateTime|false'], 'IntlChar::charAge' => ['array', 'char'=>'int|string'], 'IntlChar::charDigitValue' => ['int', 'codepoint'=>'mixed'], 'IntlChar::charDirection' => ['int', 'codepoint'=>'mixed'], 'IntlChar::charFromName' => ['?int', 'name'=>'string', 'namechoice='=>'int'], 'IntlChar::charMirror' => ['mixed', 'codepoint'=>'mixed'], 'IntlChar::charName' => ['string', 'char'=>'int|string', 'namechoice='=>'int'], 'IntlChar::charType' => ['int', 'codepoint'=>'mixed'], 'IntlChar::chr' => ['string', 'codepoint'=>'mixed'], 'IntlChar::digit' => ['int|false', 'char'=>'int|string', 'radix='=>'int'], 'IntlChar::enumCharNames' => ['void', 'start'=>'mixed', 'limit'=>'mixed', 'callback'=>'callable', 'nameChoice='=>'int'], 'IntlChar::enumCharTypes' => ['void', 'cb='=>'callable'], 'IntlChar::foldCase' => ['int|string', 'char'=>'int|string', 'options='=>'int'], 'IntlChar::forDigit' => ['int', 'digit'=>'int', 'radix'=>'int'], 'IntlChar::getBidiPairedBracket' => ['mixed', 'codepoint'=>'mixed'], 'IntlChar::getBlockCode' => ['int', 'char'=>'int|string'], 'IntlChar::getCombiningClass' => ['int', 'codepoint'=>'mixed'], 'IntlChar::getFC_NFKC_Closure' => ['string', 'char'=>'int|string'], 'IntlChar::getIntPropertyMaxValue' => ['int', 'property'=>'int'], 'IntlChar::getIntPropertyMinValue' => ['int', 'property'=>'int'], 'IntlChar::getIntPropertyMxValue' => ['int', 'property'=>'int'], 'IntlChar::getIntPropertyValue' => ['int', 'char'=>'int|string', 'property'=>'int'], 'IntlChar::getNumericValue' => ['float', 'char'=>'int|string'], 'IntlChar::getPropertyEnum' => ['int', 'alias'=>'string'], 'IntlChar::getPropertyName' => ['string|false', 'property'=>'int', 'namechoice='=>'int'], 'IntlChar::getPropertyValueEnum' => ['int', 'property'=>'int', 'name'=>'string'], 'IntlChar::getPropertyValueName' => ['string|false', 'prop'=>'int', 'value'=>'int', 'namechoice='=>'int'], 'IntlChar::getUnicodeVersion' => ['array'], 'IntlChar::hasBinaryProperty' => ['bool', 'char'=>'int|string', 'property'=>'int'], 'IntlChar::isalnum' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isalpha' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isbase' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isblank' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::iscntrl' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isdefined' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isdigit' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isgraph' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isIDIgnorable' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isIDPart' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isIDStart' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isISOControl' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isJavaIDPart' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isJavaIDStart' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isJavaSpaceChar' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::islower' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isMirrored' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isprint' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::ispunct' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isspace' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::istitle' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isUAlphabetic' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isULowercase' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isupper' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isUUppercase' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isUWhiteSpace' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isWhitespace' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isxdigit' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::ord' => ['int', 'character'=>'mixed'], 'IntlChar::tolower' => ['mixed', 'codepoint'=>'mixed'], 'IntlChar::totitle' => ['mixed', 'codepoint'=>'mixed'], 'IntlChar::toupper' => ['mixed', 'codepoint'=>'mixed'], 'IntlCodePointBreakIterator::__construct' => ['void'], 'IntlCodePointBreakIterator::createCharacterInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlCodePointBreakIterator::createCodePointInstance' => ['IntlCodePointBreakIterator'], 'IntlCodePointBreakIterator::createLineInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlCodePointBreakIterator::createSentenceInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlCodePointBreakIterator::createTitleInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlCodePointBreakIterator::createWordInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlCodePointBreakIterator::current' => ['int'], 'IntlCodePointBreakIterator::first' => ['int'], 'IntlCodePointBreakIterator::following' => ['int', 'offset'=>'string'], 'IntlCodePointBreakIterator::getErrorCode' => ['int'], 'IntlCodePointBreakIterator::getErrorMessage' => ['string'], 'IntlCodePointBreakIterator::getLastCodePoint' => ['int'], 'IntlCodePointBreakIterator::getLocale' => ['string', 'locale_type'=>'string'], 'IntlCodePointBreakIterator::getPartsIterator' => ['IntlPartsIterator', 'key_type='=>'string'], 'IntlCodePointBreakIterator::getText' => ['string'], 'IntlCodePointBreakIterator::isBoundary' => ['bool', 'offset'=>'string'], 'IntlCodePointBreakIterator::last' => ['int'], 'IntlCodePointBreakIterator::next' => ['int', 'offset='=>'string'], 'IntlCodePointBreakIterator::preceding' => ['int', 'offset'=>'string'], 'IntlCodePointBreakIterator::previous' => ['int'], 'IntlCodePointBreakIterator::setText' => ['bool', 'text'=>'string'], 'IntlDateFormatter::__construct' => ['void', 'locale'=>'?string', 'datetype'=>'?int', 'timetype'=>'?int', 'timezone='=>'null|string|IntlTimeZone|DateTimeZone', 'calendar='=>'null|int|IntlCalendar', 'pattern='=>'string'], 'IntlDateFormatter::create' => ['IntlDateFormatter|false', 'locale'=>'?string', 'datetype'=>'?int', 'timetype'=>'?int', 'timezone='=>'null|string|IntlTimeZone|DateTimeZone', 'calendar='=>'int|IntlCalendar', 'pattern='=>'string'], 'IntlDateFormatter::format' => ['string|false', 'args'=>''], 'IntlDateFormatter::formatObject' => ['string|false', 'object'=>'object', 'format='=>'mixed', 'locale='=>'string'], 'IntlDateFormatter::getCalendar' => ['int'], 'IntlDateFormatter::getCalendarObject' => ['IntlCalendar'], 'IntlDateFormatter::getDateType' => ['int'], 'IntlDateFormatter::getErrorCode' => ['int'], 'IntlDateFormatter::getErrorMessage' => ['string'], 'IntlDateFormatter::getLocale' => ['string|false'], 'IntlDateFormatter::getPattern' => ['string'], 'IntlDateFormatter::getTimeType' => ['int'], 'IntlDateFormatter::getTimeZone' => ['IntlTimeZone|false'], 'IntlDateFormatter::getTimeZoneId' => ['string'], 'IntlDateFormatter::isLenient' => ['bool'], 'IntlDateFormatter::localtime' => ['array', 'text_to_parse'=>'string', '&w_parse_pos='=>'int'], 'IntlDateFormatter::parse' => ['int|false', 'text_to_parse'=>'string', '&rw_parse_pos='=>'int'], 'IntlDateFormatter::setCalendar' => ['bool', 'calendar'=>''], 'IntlDateFormatter::setLenient' => ['bool', 'lenient'=>'bool'], 'IntlDateFormatter::setPattern' => ['bool', 'pattern'=>'string'], 'IntlDateFormatter::setTimeZone' => ['bool', 'timezone'=>''], 'IntlDateFormatter::setTimeZoneId' => ['bool', 'zone'=>'string', 'fmt='=>'IntlDateFormatter'], 'IntlException::__clone' => ['void'], 'IntlException::__construct' => ['void'], 'IntlException::__toString' => ['string'], 'IntlException::__wakeup' => ['void'], 'IntlException::getCode' => ['int'], 'IntlException::getFile' => ['string'], 'IntlException::getLine' => ['int'], 'IntlException::getMessage' => ['string'], 'IntlException::getPrevious' => ['?Throwable'], 'IntlException::getTrace' => ['list>'], 'IntlException::getTraceAsString' => ['string'], 'intlgregcal_create_instance' => ['IntlGregorianCalendar', 'timeZone='=>'mixed', 'locale='=>'string'], 'intlgregcal_get_gregorian_change' => ['float', 'object'=>'IntlGregorianCalendar'], 'intlgregcal_is_leap_year' => ['bool', 'year'=>'int'], 'intlgregcal_set_gregorian_change' => ['void', 'object'=>'IntlGregorianCalendar', 'change'=>'float'], 'IntlGregorianCalendar::__construct' => ['void'], 'IntlGregorianCalendar::add' => ['bool', 'field'=>'int', 'amount'=>'int'], 'IntlGregorianCalendar::after' => ['bool', 'other'=>'IntlCalendar'], 'IntlGregorianCalendar::before' => ['bool', 'other'=>'IntlCalendar'], 'IntlGregorianCalendar::clear' => ['bool', 'field='=>'int'], 'IntlGregorianCalendar::createInstance' => ['IntlGregorianCalendar', 'timeZone='=>'mixed', 'locale='=>'string'], 'IntlGregorianCalendar::equals' => ['bool', 'other'=>'IntlCalendar'], 'IntlGregorianCalendar::fieldDifference' => ['int', 'when'=>'float', 'field'=>'int'], 'IntlGregorianCalendar::fromDateTime' => ['IntlCalendar', 'dateTime'=>'DateTime|string'], 'IntlGregorianCalendar::get' => ['int', 'field'=>'int'], 'IntlGregorianCalendar::getActualMaximum' => ['int', 'field'=>'int'], 'IntlGregorianCalendar::getActualMinimum' => ['int', 'field'=>'int'], 'IntlGregorianCalendar::getAvailableLocales' => ['array'], 'IntlGregorianCalendar::getDayOfWeekType' => ['int', 'dayOfWeek'=>'int'], 'IntlGregorianCalendar::getErrorCode' => ['int'], 'IntlGregorianCalendar::getErrorMessage' => ['string'], 'IntlGregorianCalendar::getFirstDayOfWeek' => ['int'], 'IntlGregorianCalendar::getGreatestMinimum' => ['int', 'field'=>'int'], 'IntlGregorianCalendar::getGregorianChange' => ['float'], 'IntlGregorianCalendar::getKeywordValuesForLocale' => ['Iterator', 'key'=>'string', 'locale'=>'string', 'commonlyUsed'=>'bool'], 'IntlGregorianCalendar::getLeastMaximum' => ['int', 'field'=>'int'], 'IntlGregorianCalendar::getLocale' => ['string', 'localeType'=>'int'], 'IntlGregorianCalendar::getMaximum' => ['int', 'field'=>'int'], 'IntlGregorianCalendar::getMinimalDaysInFirstWeek' => ['int'], 'IntlGregorianCalendar::getMinimum' => ['int', 'field'=>'int'], 'IntlGregorianCalendar::getNow' => ['float'], 'IntlGregorianCalendar::getRepeatedWallTimeOption' => ['int'], 'IntlGregorianCalendar::getSkippedWallTimeOption' => ['int'], 'IntlGregorianCalendar::getTime' => ['float'], 'IntlGregorianCalendar::getTimeZone' => ['IntlTimeZone'], 'IntlGregorianCalendar::getType' => ['string'], 'IntlGregorianCalendar::getWeekendTransition' => ['int', 'dayOfWeek'=>'string'], 'IntlGregorianCalendar::inDaylightTime' => ['bool'], 'IntlGregorianCalendar::isEquivalentTo' => ['bool', 'other'=>'IntlCalendar'], 'IntlGregorianCalendar::isLeapYear' => ['bool', 'year'=>'int'], 'IntlGregorianCalendar::isLenient' => ['bool'], 'IntlGregorianCalendar::isSet' => ['bool', 'field'=>'int'], 'IntlGregorianCalendar::isWeekend' => ['bool', 'date='=>'float'], 'IntlGregorianCalendar::roll' => ['bool', 'field'=>'int', 'amountOrUpOrDown'=>'mixed'], 'IntlGregorianCalendar::set' => ['bool', 'field'=>'int', 'value'=>'int'], 'IntlGregorianCalendar::set\'1' => ['bool', 'year'=>'int', 'month'=>'int', 'dayOfMonth='=>'int', 'hour='=>'int', 'minute='=>'int', 'second='=>'int'], 'IntlGregorianCalendar::setFirstDayOfWeek' => ['bool', 'dayOfWeek'=>'int'], 'IntlGregorianCalendar::setGregorianChange' => ['bool', 'date'=>'float'], 'IntlGregorianCalendar::setLenient' => ['bool', 'isLenient'=>'string'], 'IntlGregorianCalendar::setMinimalDaysInFirstWeek' => ['bool', 'minimalDays'=>'int'], 'IntlGregorianCalendar::setRepeatedWallTimeOption' => ['bool', 'wallTimeOption'=>'int'], 'IntlGregorianCalendar::setSkippedWallTimeOption' => ['bool', 'wallTimeOption'=>'int'], 'IntlGregorianCalendar::setTime' => ['bool', 'date'=>'float'], 'IntlGregorianCalendar::setTimeZone' => ['bool', 'timeZone'=>'mixed'], 'IntlGregorianCalendar::toDateTime' => ['DateTime'], 'IntlIterator::__construct' => ['void'], 'IntlIterator::current' => ['mixed'], 'IntlIterator::key' => ['string'], 'IntlIterator::next' => ['void'], 'IntlIterator::rewind' => ['void'], 'IntlIterator::valid' => ['bool'], 'IntlPartsIterator::getBreakIterator' => ['IntlBreakIterator'], 'IntlRuleBasedBreakIterator::__construct' => ['void', 'rules'=>'string', 'areCompiled='=>'string'], 'IntlRuleBasedBreakIterator::createCharacterInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlRuleBasedBreakIterator::createCodePointInstance' => ['IntlCodePointBreakIterator'], 'IntlRuleBasedBreakIterator::createLineInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlRuleBasedBreakIterator::createSentenceInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlRuleBasedBreakIterator::createTitleInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlRuleBasedBreakIterator::createWordInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlRuleBasedBreakIterator::current' => ['int'], 'IntlRuleBasedBreakIterator::first' => ['int'], 'IntlRuleBasedBreakIterator::following' => ['int', 'offset'=>'int'], 'IntlRuleBasedBreakIterator::getBinaryRules' => ['string'], 'IntlRuleBasedBreakIterator::getErrorCode' => ['int'], 'IntlRuleBasedBreakIterator::getErrorMessage' => ['string'], 'IntlRuleBasedBreakIterator::getLocale' => ['string', 'locale_type'=>'string'], 'IntlRuleBasedBreakIterator::getPartsIterator' => ['IntlPartsIterator', 'key_type='=>'int'], 'IntlRuleBasedBreakIterator::getRules' => ['string'], 'IntlRuleBasedBreakIterator::getRuleStatus' => ['int'], 'IntlRuleBasedBreakIterator::getRuleStatusVec' => ['array'], 'IntlRuleBasedBreakIterator::getText' => ['string'], 'IntlRuleBasedBreakIterator::isBoundary' => ['bool', 'offset'=>'int'], 'IntlRuleBasedBreakIterator::last' => ['int'], 'IntlRuleBasedBreakIterator::next' => ['int', 'offset='=>'int'], 'IntlRuleBasedBreakIterator::preceding' => ['int', 'offset'=>'int'], 'IntlRuleBasedBreakIterator::previous' => ['int'], 'IntlRuleBasedBreakIterator::setText' => ['bool', 'text'=>'string'], 'IntlTimeZone::countEquivalentIDs' => ['int|false', 'zoneId'=>'string'], 'IntlTimeZone::createDefault' => ['IntlTimeZone'], 'IntlTimeZone::createEnumeration' => ['IntlIterator|false', 'countryOrRawOffset='=>'mixed'], 'IntlTimeZone::createTimeZone' => ['IntlTimeZone|false', 'zoneId'=>'string'], 'IntlTimeZone::createTimeZoneIDEnumeration' => ['IntlIterator|false', 'zoneType'=>'int', 'region='=>'string', 'rawOffset='=>'int'], 'IntlTimeZone::fromDateTimeZone' => ['?IntlTimeZone', 'zoneId'=>'DateTimeZone'], 'IntlTimeZone::getCanonicalID' => ['string|false', 'zoneId'=>'string', '&w_isSystemID='=>'bool'], 'IntlTimeZone::getDisplayName' => ['string|false', 'isDaylight='=>'bool', 'style='=>'int', 'locale='=>'string'], 'IntlTimeZone::getDSTSavings' => ['int'], 'IntlTimeZone::getEquivalentID' => ['string|false', 'zoneId'=>'string', 'index'=>'int'], 'IntlTimeZone::getErrorCode' => ['int'], 'IntlTimeZone::getErrorMessage' => ['string'], 'IntlTimeZone::getGMT' => ['IntlTimeZone'], 'IntlTimeZone::getID' => ['string'], 'IntlTimeZone::getIDForWindowsID' => ['string', 'timezone'=>'string', 'region='=>'string'], 'IntlTimeZone::getOffset' => ['int', 'date'=>'float', 'local'=>'bool', '&w_rawOffset'=>'int', '&w_dstOffset'=>'int'], 'IntlTimeZone::getRawOffset' => ['int'], 'IntlTimeZone::getRegion' => ['string|false', 'zoneId'=>'string'], 'IntlTimeZone::getTZDataVersion' => ['string'], 'IntlTimeZone::getUnknown' => ['IntlTimeZone'], 'IntlTimeZone::getWindowsID' => ['string|false', 'timezone'=>'string'], 'IntlTimeZone::hasSameRules' => ['bool', 'otherTimeZone'=>'IntlTimeZone'], 'IntlTimeZone::toDateTimeZone' => ['DateTimeZone|false'], 'IntlTimeZone::useDaylightTime' => ['bool'], 'intltz_count_equivalent_ids' => ['int', 'zoneId'=>'string'], 'intltz_create_enumeration' => ['IntlIterator', 'countryOrRawOffset'=>'mixed'], 'intltz_create_time_zone' => ['IntlTimeZone', 'zoneId'=>'string'], 'intltz_from_date_time_zone' => ['IntlTimeZone', 'zoneId'=>'DateTimeZone'], 'intltz_get_canonical_id' => ['string', 'zoneId'=>'string', '&isSystemID'=>'bool'], 'intltz_get_display_name' => ['string', 'object'=>'IntlTimeZone', 'isDaylight'=>'bool', 'style'=>'int', 'locale'=>'string'], 'intltz_get_dst_savings' => ['int', 'object'=>'IntlTimeZone'], 'intltz_get_equivalent_id' => ['string', 'zoneId'=>'string', 'index'=>'int'], 'intltz_get_error_code' => ['int', 'object'=>'IntlTimeZone'], 'intltz_get_error_message' => ['string', 'object'=>'IntlTimeZone'], 'intltz_get_id' => ['string', 'object'=>'IntlTimeZone'], 'intltz_get_offset' => ['int', 'object'=>'IntlTimeZone', 'date'=>'float', 'local'=>'bool', '&rawOffset'=>'int', '&dstOffset'=>'int'], 'intltz_get_raw_offset' => ['int', 'object'=>'IntlTimeZone'], 'intltz_get_tz_data_version' => ['string', 'object'=>'IntlTimeZone'], 'intltz_getGMT' => ['IntlTimeZone'], 'intltz_has_same_rules' => ['bool', 'object'=>'IntlTimeZone', 'otherTimeZone'=>'IntlTimeZone'], 'intltz_to_date_time_zone' => ['DateTimeZone', 'object'=>'IntlTimeZone'], 'intltz_use_daylight_time' => ['bool', 'object'=>'IntlTimeZone'], 'intlz_create_default' => ['IntlTimeZone'], 'intval' => ['int', 'var'=>'mixed', 'base='=>'int'], 'InvalidArgumentException::__clone' => ['void'], 'InvalidArgumentException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?InvalidArgumentException'], 'InvalidArgumentException::__toString' => ['string'], 'InvalidArgumentException::getCode' => ['int'], 'InvalidArgumentException::getFile' => ['string'], 'InvalidArgumentException::getLine' => ['int'], 'InvalidArgumentException::getMessage' => ['string'], 'InvalidArgumentException::getPrevious' => ['Throwable|InvalidArgumentException|null'], 'InvalidArgumentException::getTrace' => ['list>'], 'InvalidArgumentException::getTraceAsString' => ['string'], 'ip2long' => ['int|false', 'ip_address'=>'string'], 'iptcembed' => ['string|bool', 'iptcdata'=>'string', 'jpeg_file_name'=>'string', 'spool='=>'int'], 'iptcparse' => ['array|false', 'iptcdata'=>'string'], 'is_a' => ['bool', 'object_or_string'=>'object|string', 'class_name'=>'string', 'allow_string='=>'bool'], 'is_array' => ['bool', 'value'=>'mixed'], 'is_bool' => ['bool', 'value'=>'mixed'], 'is_callable' => ['bool', 'value'=>'callable|mixed', 'syntax_only='=>'bool', '&w_callable_name='=>'string'], 'is_countable' => ['bool', 'value'=>'mixed'], 'is_dir' => ['bool', 'filename'=>'string'], 'is_double' => ['bool', 'value'=>'mixed'], 'is_executable' => ['bool', 'filename'=>'string'], 'is_file' => ['bool', 'filename'=>'string'], 'is_finite' => ['bool', 'number'=>'float'], 'is_float' => ['bool', 'value'=>'mixed'], 'is_infinite' => ['bool', 'number'=>'float'], 'is_int' => ['bool', 'value'=>'mixed'], 'is_integer' => ['bool', 'value'=>'mixed'], 'is_iterable' => ['bool', 'value'=>'mixed'], 'is_link' => ['bool', 'filename'=>'string'], 'is_long' => ['bool', 'value'=>'mixed'], 'is_nan' => ['bool', 'number'=>'float'], 'is_null' => ['bool', 'value'=>'mixed'], 'is_numeric' => ['bool', 'value'=>'mixed'], 'is_object' => ['bool', 'value'=>'mixed'], 'is_readable' => ['bool', 'filename'=>'string'], 'is_real' => ['bool', 'value'=>'mixed'], 'is_resource' => ['bool', 'value'=>'mixed'], 'is_scalar' => ['bool', 'value'=>'mixed'], 'is_soap_fault' => ['bool', 'object'=>'mixed'], 'is_string' => ['bool', 'value'=>'mixed'], 'is_subclass_of' => ['bool', 'object_or_string'=>'object|string', 'class_name'=>'string', 'allow_string='=>'bool'], 'is_tainted' => ['bool', 'string'=>'string'], 'is_uploaded_file' => ['bool', 'path'=>'string'], 'is_writable' => ['bool', 'filename'=>'string'], 'is_writeable' => ['bool', 'filename'=>'string'], 'isset' => ['bool', 'value'=>'mixed', '...rest='=>'mixed'], 'Iterator::current' => ['mixed'], 'Iterator::key' => ['mixed'], 'Iterator::next' => ['void'], 'Iterator::rewind' => ['void'], 'Iterator::valid' => ['bool'], 'iterator_apply' => ['int', 'it'=>'Traversable', 'function'=>'callable(mixed):bool', 'params='=>'array'], 'iterator_count' => ['int', 'it'=>'Traversable'], 'iterator_to_array' => ['array', 'it'=>'Traversable', 'use_keys='=>'bool'], 'IteratorAggregate::getIterator' => ['Traversable'], 'IteratorIterator::__construct' => ['void', 'it'=>'Traversable'], 'IteratorIterator::current' => ['mixed'], 'IteratorIterator::getInnerIterator' => ['Traversable'], 'IteratorIterator::key' => ['mixed'], 'IteratorIterator::next' => ['void'], 'IteratorIterator::rewind' => ['void'], 'IteratorIterator::valid' => ['bool'], 'java_last_exception_clear' => ['void'], 'java_last_exception_get' => ['object'], 'java_reload' => ['array', 'new_jarpath'=>'string'], 'java_require' => ['array', 'new_classpath'=>'string'], 'java_set_encoding' => ['array', 'encoding'=>'string'], 'java_set_ignore_case' => ['void', 'ignore'=>'bool'], 'java_throw_exceptions' => ['void', 'throw'=>'bool'], 'JavaException::getCause' => ['object'], 'jddayofweek' => ['mixed', 'juliandaycount'=>'int', 'mode='=>'int'], 'jdmonthname' => ['string', 'juliandaycount'=>'int', 'mode'=>'int'], 'jdtofrench' => ['string', 'juliandaycount'=>'int'], 'jdtogregorian' => ['string', 'juliandaycount'=>'int'], 'jdtojewish' => ['string', 'juliandaycount'=>'int', 'hebrew='=>'bool', 'fl='=>'int'], 'jdtojulian' => ['string', 'juliandaycount'=>'int'], 'jdtounix' => ['int|false', 'jday'=>'int'], 'jewishtojd' => ['int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'jobqueue_license_info' => ['array'], 'join' => ['string', 'glue'=>'string', 'pieces'=>'array'], 'join\'1' => ['string', 'pieces'=>'array'], 'jpeg2wbmp' => ['bool', 'jpegname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'], 'json_decode' => ['mixed', 'json'=>'string', 'assoc='=>'bool', 'depth='=>'int', 'options='=>'int'], 'json_encode' => ['string|false', 'data'=>'mixed', 'options='=>'int', 'depth='=>'int'], 'json_last_error' => ['int'], 'json_last_error_msg' => ['string'], 'JsonException::__clone' => ['void'], 'JsonException::__construct' => ['void'], 'JsonException::__toString' => ['string'], 'JsonException::__wakeup' => ['void'], 'JsonException::getCode' => ['int'], 'JsonException::getFile' => ['string'], 'JsonException::getLine' => ['int'], 'JsonException::getMessage' => ['string'], 'JsonException::getPrevious' => ['?Throwable'], 'JsonException::getTrace' => ['list>'], 'JsonException::getTraceAsString' => ['string'], 'JsonIncrementalParser::__construct' => ['void', 'depth'=>'', 'options'=>''], 'JsonIncrementalParser::get' => ['', 'options'=>''], 'JsonIncrementalParser::getError' => [''], 'JsonIncrementalParser::parse' => ['', 'json'=>''], 'JsonIncrementalParser::parseFile' => ['', 'filename'=>''], 'JsonIncrementalParser::reset' => [''], 'JsonSerializable::jsonSerialize' => ['mixed'], 'Judy::__construct' => ['void', 'judy_type'=>'int'], 'Judy::__destruct' => ['void'], 'Judy::byCount' => ['int', 'nth_index'=>'int'], 'Judy::count' => ['int', 'index_start='=>'int', 'index_end='=>'int'], 'Judy::first' => ['mixed', 'index='=>'mixed'], 'Judy::firstEmpty' => ['mixed', 'index='=>'mixed'], 'Judy::free' => ['int'], 'Judy::getType' => ['int'], 'Judy::last' => ['mixed', 'index='=>'string'], 'Judy::lastEmpty' => ['mixed', 'index='=>'int'], '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::prev' => ['mixed', 'index'=>'mixed'], 'Judy::prevEmpty' => ['mixed', 'index'=>'mixed'], 'Judy::size' => ['int'], 'judy_type' => ['int', 'array'=>'judy'], 'judy_version' => ['string'], 'juliantojd' => ['int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'kadm5_chpass_principal' => ['bool', 'handle'=>'resource', 'principal'=>'string', 'password'=>'string'], 'kadm5_create_principal' => ['bool', 'handle'=>'resource', 'principal'=>'string', 'password='=>'string', 'options='=>'array'], 'kadm5_delete_principal' => ['bool', 'handle'=>'resource', 'principal'=>'string'], 'kadm5_destroy' => ['bool', 'handle'=>'resource'], 'kadm5_flush' => ['bool', 'handle'=>'resource'], 'kadm5_get_policies' => ['array', 'handle'=>'resource'], 'kadm5_get_principal' => ['array', 'handle'=>'resource', 'principal'=>'string'], 'kadm5_get_principals' => ['array', 'handle'=>'resource'], 'kadm5_init_with_password' => ['resource', 'admin_server'=>'string', 'realm'=>'string', 'principal'=>'string', 'password'=>'string'], 'kadm5_modify_principal' => ['bool', 'handle'=>'resource', 'principal'=>'string', 'options'=>'array'], 'key' => ['int|string|null', 'array'=>'array|object'], 'key_exists' => ['bool', 'key'=>'string|int', 'search'=>'array'], 'krsort' => ['bool', '&rw_array'=>'array', 'sort_flags='=>'int'], 'ksort' => ['bool', '&rw_array'=>'array', 'sort_flags='=>'int'], 'KTaglib_ID3v2_AttachedPictureFrame::getDescription' => ['string'], 'KTaglib_ID3v2_AttachedPictureFrame::getMimeType' => ['string'], 'KTaglib_ID3v2_AttachedPictureFrame::getType' => ['int'], 'KTaglib_ID3v2_AttachedPictureFrame::savePicture' => ['bool', 'filename'=>'string'], 'KTaglib_ID3v2_AttachedPictureFrame::setMimeType' => ['string', 'type'=>'string'], 'KTaglib_ID3v2_AttachedPictureFrame::setPicture' => ['', 'filename'=>'string'], 'KTaglib_ID3v2_AttachedPictureFrame::setType' => ['', 'type'=>'int'], 'KTaglib_ID3v2_Frame::__toString' => ['string'], 'KTaglib_ID3v2_Frame::getDescription' => ['string'], 'KTaglib_ID3v2_Frame::getMimeType' => ['string'], 'KTaglib_ID3v2_Frame::getSize' => ['int'], 'KTaglib_ID3v2_Frame::getType' => ['int'], 'KTaglib_ID3v2_Frame::savePicture' => ['bool', 'filename'=>'string'], 'KTaglib_ID3v2_Frame::setMimeType' => ['string', 'type'=>'string'], 'KTaglib_ID3v2_Frame::setPicture' => ['void', 'filename'=>'string'], 'KTaglib_ID3v2_Frame::setType' => ['void', 'type'=>'int'], 'KTaglib_ID3v2_Tag::addFrame' => ['bool', 'frame'=>'KTaglib_ID3v2_Frame'], 'KTaglib_ID3v2_Tag::getFrameList' => ['array'], 'KTaglib_MPEG_AudioProperties::getBitrate' => ['int'], 'KTaglib_MPEG_AudioProperties::getChannels' => ['int'], 'KTaglib_MPEG_AudioProperties::getLayer' => ['int'], 'KTaglib_MPEG_AudioProperties::getLength' => ['int'], 'KTaglib_MPEG_AudioProperties::getSampleBitrate' => ['int'], 'KTaglib_MPEG_AudioProperties::getVersion' => ['int'], 'KTaglib_MPEG_AudioProperties::isCopyrighted' => ['bool'], 'KTaglib_MPEG_AudioProperties::isOriginal' => ['bool'], 'KTaglib_MPEG_AudioProperties::isProtectionEnabled' => ['bool'], 'KTaglib_MPEG_File::getAudioProperties' => ['KTaglib_MPEG_File'], 'KTaglib_MPEG_File::getID3v1Tag' => ['KTaglib_ID3v1_Tag', 'create='=>'bool'], 'KTaglib_MPEG_File::getID3v2Tag' => ['KTaglib_ID3v2_Tag', 'create='=>'bool'], 'KTaglib_Tag::getAlbum' => ['string'], 'KTaglib_Tag::getArtist' => ['string'], 'KTaglib_Tag::getComment' => ['string'], 'KTaglib_Tag::getGenre' => ['string'], 'KTaglib_Tag::getTitle' => ['string'], 'KTaglib_Tag::getTrack' => ['int'], 'KTaglib_Tag::getYear' => ['int'], 'KTaglib_Tag::isEmpty' => ['bool'], 'labelcacheObj::freeCache' => ['bool'], 'labelObj::__construct' => ['void'], 'labelObj::convertToString' => ['string'], 'labelObj::deleteStyle' => ['int', 'index'=>'int'], 'labelObj::free' => ['void'], 'labelObj::getBinding' => ['string', 'labelbinding'=>'mixed'], 'labelObj::getExpressionString' => ['string'], 'labelObj::getStyle' => ['styleObj', 'index'=>'int'], 'labelObj::getTextString' => ['string'], 'labelObj::moveStyleDown' => ['int', 'index'=>'int'], 'labelObj::moveStyleUp' => ['int', 'index'=>'int'], 'labelObj::removeBinding' => ['int', 'labelbinding'=>'mixed'], 'labelObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'labelObj::setBinding' => ['int', 'labelbinding'=>'mixed', 'value'=>'string'], 'labelObj::setExpression' => ['int', 'expression'=>'string'], 'labelObj::setText' => ['int', 'text'=>'string'], 'labelObj::updateFromString' => ['int', 'snippet'=>'string'], 'Lapack::eigenValues' => ['array', 'a'=>'array', 'left='=>'array', 'right='=>'array'], 'Lapack::identity' => ['array', 'n'=>'int'], 'Lapack::leastSquaresByFactorisation' => ['array', 'a'=>'array', 'b'=>'array'], 'Lapack::leastSquaresBySVD' => ['array', 'a'=>'array', 'b'=>'array'], 'Lapack::pseudoInverse' => ['array', 'a'=>'array'], 'Lapack::singularValues' => ['array', 'a'=>'array'], 'Lapack::solveLinearEquation' => ['array', 'a'=>'array', 'b'=>'array'], 'layerObj::addFeature' => ['int', 'shape'=>'shapeObj'], 'layerObj::applySLD' => ['int', 'sldxml'=>'string', 'namedlayer'=>'string'], 'layerObj::applySLDURL' => ['int', 'sldurl'=>'string', 'namedlayer'=>'string'], 'layerObj::clearProcessing' => ['void'], 'layerObj::close' => ['void'], 'layerObj::convertToString' => ['string'], 'layerObj::draw' => ['int', 'image'=>'imageObj'], 'layerObj::drawQuery' => ['int', 'image'=>'imageObj'], 'layerObj::free' => ['void'], 'layerObj::generateSLD' => ['string'], 'layerObj::getClass' => ['classObj', 'classIndex'=>'int'], 'layerObj::getClassIndex' => ['int', 'shape'=>'', 'classgroup'=>'', 'numclasses'=>''], 'layerObj::getExtent' => ['rectObj'], 'layerObj::getFilterString' => ['?string'], 'layerObj::getGridIntersectionCoordinates' => ['array'], 'layerObj::getItems' => ['array'], 'layerObj::getMetaData' => ['int', 'name'=>'string'], 'layerObj::getNumResults' => ['int'], 'layerObj::getProcessing' => ['array'], 'layerObj::getProjection' => ['string'], 'layerObj::getResult' => ['resultObj', 'index'=>'int'], 'layerObj::getResultsBounds' => ['rectObj'], 'layerObj::getShape' => ['shapeObj', 'result'=>'resultObj'], 'layerObj::getWMSFeatureInfoURL' => ['string', 'clickX'=>'int', 'clickY'=>'int', 'featureCount'=>'int', 'infoFormat'=>'string'], 'layerObj::isVisible' => ['bool'], 'layerObj::moveclassdown' => ['int', 'index'=>'int'], 'layerObj::moveclassup' => ['int', 'index'=>'int'], 'layerObj::ms_newLayerObj' => ['layerObj', 'map'=>'mapObj', 'layer'=>'layerObj'], 'layerObj::nextShape' => ['shapeObj'], 'layerObj::open' => ['int'], 'layerObj::queryByAttributes' => ['int', 'qitem'=>'string', 'qstring'=>'string', 'mode'=>'int'], 'layerObj::queryByFeatures' => ['int', 'slayer'=>'int'], 'layerObj::queryByPoint' => ['int', 'point'=>'pointObj', 'mode'=>'int', 'buffer'=>'float'], 'layerObj::queryByRect' => ['int', 'rect'=>'rectObj'], 'layerObj::queryByShape' => ['int', 'shape'=>'shapeObj'], 'layerObj::removeClass' => ['?classObj', 'index'=>'int'], 'layerObj::removeMetaData' => ['int', 'name'=>'string'], 'layerObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'layerObj::setConnectionType' => ['int', 'connectiontype'=>'int', 'plugin_library'=>'string'], 'layerObj::setFilter' => ['int', 'expression'=>'string'], 'layerObj::setMetaData' => ['int', 'name'=>'string', 'value'=>'string'], 'layerObj::setProjection' => ['int', 'proj_params'=>'string'], 'layerObj::setWKTProjection' => ['int', 'proj_params'=>'string'], 'layerObj::updateFromString' => ['int', 'snippet'=>'string'], 'lcfirst' => ['string', 'string'=>'string'], 'lcg_value' => ['float'], 'lchgrp' => ['bool', 'filename'=>'string', 'group'=>'string|int'], 'lchown' => ['bool', 'filename'=>'string', 'user'=>'string|int'], 'ldap_8859_to_t61' => ['string', 'value'=>'string'], 'ldap_add' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'serverctrls='=>'array'], 'ldap_add_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'serverctrls='=>'array'], 'ldap_bind' => ['bool', 'link_identifier'=>'resource', 'bind_rdn='=>'string|null', 'bind_password='=>'string|null'], 'ldap_bind_ext' => ['resource|false', 'link_identifier'=>'resource', 'bind_rdn='=>'string|null', 'bind_password='=>'string|null', 'serverctrls='=>'array'], 'ldap_close' => ['bool', 'link_identifier'=>'resource'], 'ldap_compare' => ['bool|int', 'link_identifier'=>'resource', 'dn'=>'string', 'attr'=>'string', 'value'=>'string'], 'ldap_connect' => ['resource|false', 'host='=>'string', 'port='=>'int', 'wallet='=>'string', 'wallet_passwd='=>'string', 'authmode='=>'int'], 'ldap_control_paged_result' => ['bool', 'link_identifier'=>'resource', 'pagesize'=>'int', 'iscritical='=>'bool', 'cookie='=>'string'], 'ldap_control_paged_result_response' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', '&w_cookie'=>'string', '&w_estimated'=>'int'], 'ldap_count_entries' => ['int|false', 'link_identifier'=>'resource', 'result'=>'resource'], 'ldap_delete' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string'], 'ldap_delete_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'serverctrls='=>'array'], 'ldap_dn2ufn' => ['string', 'dn'=>'string'], 'ldap_err2str' => ['string', 'errno'=>'int'], 'ldap_errno' => ['int', 'link_identifier'=>'resource'], 'ldap_error' => ['string', 'link_identifier'=>'resource'], 'ldap_escape' => ['string', 'value'=>'string', 'ignore='=>'string', 'flags='=>'int'], 'ldap_exop' => ['mixed', 'link'=>'resource', 'reqoid'=>'string', 'reqdata='=>'string', 'serverctrls='=>'array|null', '&w_retdata='=>'string', '&w_retoid='=>'string'], 'ldap_exop_passwd' => ['mixed', 'link'=>'resource', 'user='=>'string', 'oldpw='=>'string', 'newpw='=>'string', 'serverctrls='=>'array'], 'ldap_exop_refresh' => ['int|false', 'link'=>'resource', 'dn'=>'string', 'ttl'=>'int'], 'ldap_exop_whoami' => ['string|false', 'link'=>'resource'], 'ldap_explode_dn' => ['array|false', 'dn'=>'string', 'with_attrib'=>'int'], 'ldap_first_attribute' => ['string|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_first_entry' => ['resource|false', 'link_identifier'=>'resource', 'result_identifier'=>'resource'], 'ldap_first_reference' => ['resource|false', 'link_identifier'=>'resource', 'result_identifier'=>'resource'], 'ldap_free_result' => ['bool', 'result_identifier'=>'resource'], 'ldap_get_attributes' => ['array|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_get_dn' => ['string|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_get_entries' => ['array|false', 'link_identifier'=>'resource', 'result_identifier'=>'resource'], 'ldap_get_option' => ['bool', 'link_identifier'=>'resource', 'option'=>'int', '&w_retval'=>'mixed'], 'ldap_get_values' => ['array|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource', 'attribute'=>'string'], 'ldap_get_values_len' => ['array|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource', 'attribute'=>'string'], 'ldap_list' => ['resource|false', 'link'=>'resource|array', 'base_dn'=>'string', 'filter'=>'string', 'attrs='=>'array', 'attrsonly='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'], 'ldap_mod_add' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array'], 'ldap_mod_add_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'serverctrls='=>'array'], 'ldap_mod_del' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array'], 'ldap_mod_del_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'serverctrls='=>'array'], 'ldap_mod_replace' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array'], 'ldap_mod_replace_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'serverctrls='=>'array'], 'ldap_modify' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array'], 'ldap_modify_batch' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'modifications'=>'array'], 'ldap_next_attribute' => ['string|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_next_entry' => ['resource|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_next_reference' => ['resource|false', 'link_identifier'=>'resource', 'reference_entry_identifier'=>'resource'], 'ldap_parse_exop' => ['bool', 'link'=>'resource', 'result'=>'resource', '&w_retdata='=>'string', '&w_retoid='=>'string'], 'ldap_parse_reference' => ['bool', 'link_identifier'=>'resource', 'reference_entry_identifier'=>'resource', 'referrals'=>'array'], 'ldap_parse_result' => ['bool', 'link_identifier'=>'resource', 'result'=>'resource', '&w_errcode'=>'int', '&w_matcheddn='=>'string', '&w_errmsg='=>'string', '&w_referrals='=>'array', '&w_serverctrls='=>'array'], 'ldap_read' => ['resource|false', 'link'=>'resource|array', 'base_dn'=>'string', 'filter'=>'string', 'attrs='=>'array', 'attrsonly='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'], 'ldap_rename' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'newrdn'=>'string', 'newparent'=>'string', 'deleteoldrdn'=>'bool'], 'ldap_rename_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'newrdn'=>'string', 'newparent'=>'string', 'deleteoldrdn'=>'bool', 'serverctrls='=>'array'], 'ldap_sasl_bind' => ['bool', 'link_identifier'=>'resource', 'binddn='=>'string', 'password='=>'string', 'sasl_mech='=>'string', 'sasl_realm='=>'string', 'sasl_authc_id='=>'string', 'sasl_authz_id='=>'string', 'props='=>'string'], 'ldap_search' => ['resource|false', 'link_identifier'=>'resource|resource[]', 'base_dn'=>'string', 'filter'=>'string', 'attrs='=>'array', 'attrsonly='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'], 'ldap_set_option' => ['bool', 'link_identifier'=>'resource|null', 'option'=>'int', 'newval'=>'mixed'], 'ldap_set_rebind_proc' => ['bool', 'link_identifier'=>'resource', 'callback'=>'string'], 'ldap_sort' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', 'sortfilter'=>'string'], 'ldap_start_tls' => ['bool', 'link_identifier'=>'resource'], 'ldap_t61_to_8859' => ['string', 'value'=>'string'], 'ldap_unbind' => ['bool', 'link_identifier'=>'resource'], 'leak' => ['', 'num_bytes'=>'int'], 'leak_variable' => ['', 'variable'=>'', 'leak_data'=>'bool'], 'legendObj::convertToString' => ['string'], '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'], 'LengthException::__toString' => ['string'], 'LengthException::getCode' => ['int'], 'LengthException::getFile' => ['string'], 'LengthException::getLine' => ['int'], 'LengthException::getMessage' => ['string'], 'LengthException::getPrevious' => ['Throwable|LengthException|null'], 'LengthException::getTrace' => ['list>'], 'LengthException::getTraceAsString' => ['string'], 'LevelDB::__construct' => ['void', 'name'=>'string', 'options='=>'array', 'read_options='=>'array', 'write_options='=>'array'], 'LevelDB::close' => [''], 'LevelDB::compactRange' => ['', 'start'=>'', 'limit'=>''], 'LevelDB::delete' => ['bool', 'key'=>'string', 'write_options='=>'array'], 'LevelDB::destroy' => ['', 'name'=>'', 'options='=>'array'], 'LevelDB::get' => ['bool|string', 'key'=>'string', 'read_options='=>'array'], 'LevelDB::getApproximateSizes' => ['', 'start'=>'', 'limit'=>''], 'LevelDB::getIterator' => ['LevelDBIterator', 'options='=>'array'], 'LevelDB::getProperty' => ['mixed', 'name'=>'string'], 'LevelDB::getSnapshot' => ['LevelDBSnapshot'], 'LevelDB::put' => ['', 'key'=>'string', 'value'=>'string', 'write_options='=>'array'], 'LevelDB::repair' => ['', 'name'=>'', 'options='=>'array'], 'LevelDB::set' => ['', 'key'=>'string', 'value'=>'string', 'write_options='=>'array'], 'LevelDB::write' => ['', 'batch'=>'LevelDBWriteBatch', 'write_options='=>'array'], 'LevelDBIterator::__construct' => ['void', 'db'=>'LevelDB', 'read_options='=>'array'], 'LevelDBIterator::current' => ['mixed'], 'LevelDBIterator::destroy' => [''], 'LevelDBIterator::getError' => [''], 'LevelDBIterator::key' => ['int|string'], 'LevelDBIterator::last' => [''], 'LevelDBIterator::next' => ['void'], 'LevelDBIterator::prev' => [''], 'LevelDBIterator::rewind' => ['void'], 'LevelDBIterator::seek' => ['', 'key'=>''], 'LevelDBIterator::valid' => ['bool'], 'LevelDBSnapshot::__construct' => ['void', 'db'=>'LevelDB'], 'LevelDBSnapshot::release' => [''], 'LevelDBWriteBatch::__construct' => ['void', 'name'=>'', 'options='=>'array', 'read_options='=>'array', 'write_options='=>'array'], 'LevelDBWriteBatch::clear' => [''], 'LevelDBWriteBatch::delete' => ['', 'key'=>'', 'write_options='=>'array'], 'LevelDBWriteBatch::put' => ['', 'key'=>'', 'value'=>'', 'write_options='=>'array'], 'LevelDBWriteBatch::set' => ['', 'key'=>'', 'value'=>'', 'write_options='=>'array'], 'levenshtein' => ['int', 'string1'=>'string', 'string2'=>'string'], 'levenshtein\'1' => ['int', 'string1'=>'string', 'string2'=>'string', 'cost_ins'=>'int', 'cost_rep'=>'int', 'cost_del'=>'int'], 'libxml_clear_errors' => ['void'], 'libxml_disable_entity_loader' => ['bool', 'disable='=>'bool'], 'libxml_get_errors' => ['array'], 'libxml_get_last_error' => ['LibXMLError|false'], 'libxml_set_external_entity_loader' => ['bool', 'resolver_function'=>'callable'], 'libxml_set_streams_context' => ['void', 'streams_context'=>'resource'], 'libxml_use_internal_errors' => ['bool', 'use_errors='=>'bool'], 'LimitIterator::__construct' => ['void', 'iterator'=>'Iterator', 'offset='=>'int', 'count='=>'int'], 'LimitIterator::current' => ['mixed'], 'LimitIterator::getInnerIterator' => ['Iterator'], 'LimitIterator::getPosition' => ['int'], 'LimitIterator::key' => ['mixed'], 'LimitIterator::next' => ['void'], 'LimitIterator::rewind' => ['void'], 'LimitIterator::seek' => ['int', 'position'=>'int'], 'LimitIterator::valid' => ['bool'], 'lineObj::__construct' => ['void'], 'lineObj::add' => ['int', 'point'=>'pointObj'], 'lineObj::addXY' => ['int', 'x'=>'float', 'y'=>'float', 'm'=>'float'], 'lineObj::addXYZ' => ['int', 'x'=>'float', 'y'=>'float', 'z'=>'float', 'm'=>'float'], 'lineObj::ms_newLineObj' => ['lineObj'], 'lineObj::point' => ['pointObj', 'i'=>'int'], 'lineObj::project' => ['int', 'in'=>'projectionObj', 'out'=>'projectionObj'], 'link' => ['bool', 'target'=>'string', 'link'=>'string'], 'linkinfo' => ['int|false', 'filename'=>'string'], 'litespeed_request_headers' => ['array'], 'litespeed_response_headers' => ['array'], 'Locale::acceptFromHttp' => ['string|false', 'header'=>'string'], 'Locale::canonicalize' => ['string', 'locale'=>'string'], 'Locale::composeLocale' => ['string', 'subtags'=>'array'], 'Locale::filterMatches' => ['bool', 'langtag'=>'string', 'locale'=>'string', 'canonicalize='=>'bool'], 'Locale::getAllVariants' => ['array', 'locale'=>'string'], 'Locale::getDefault' => ['string'], 'Locale::getDisplayLanguage' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'Locale::getDisplayName' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'Locale::getDisplayRegion' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'Locale::getDisplayScript' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'Locale::getDisplayVariant' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'Locale::getKeywords' => ['array|false', 'locale'=>'string'], 'Locale::getPrimaryLanguage' => ['string', 'locale'=>'string'], 'Locale::getRegion' => ['string', 'locale'=>'string'], 'Locale::getScript' => ['string', 'locale'=>'string'], 'Locale::lookup' => ['string', 'langtag'=>'array', 'locale'=>'string', 'canonicalize='=>'bool', 'default='=>'string'], 'Locale::parseLocale' => ['array', 'locale'=>'string'], 'Locale::setDefault' => ['bool', 'locale'=>'string'], 'locale_accept_from_http' => ['string|false', 'header'=>'string'], 'locale_canonicalize' => ['string', 'arg1'=>'string'], 'locale_compose' => ['string|false', 'subtags'=>'array'], 'locale_filter_matches' => ['bool', 'langtag'=>'string', 'locale'=>'string', 'canonicalize='=>'bool'], 'locale_get_all_variants' => ['array', 'locale'=>'string'], 'locale_get_default' => ['string'], 'locale_get_display_language' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'locale_get_display_name' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'locale_get_display_region' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'locale_get_display_script' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'locale_get_display_variant' => ['string', 'locale'=>'string', 'in_locale='=>'string'], 'locale_get_keywords' => ['array|false', 'locale'=>'string'], 'locale_get_primary_language' => ['string', 'locale'=>'string'], 'locale_get_region' => ['string', 'locale'=>'string'], 'locale_get_script' => ['string', 'locale'=>'string'], 'locale_lookup' => ['string', 'langtag'=>'array', 'locale'=>'string', 'canonicalize='=>'bool', 'default='=>'string'], 'locale_parse' => ['array', 'locale'=>'string'], 'locale_set_default' => ['bool', 'locale'=>'string'], 'localeconv' => ['array'], 'localtime' => ['array', 'timestamp='=>'int', 'associative_array='=>'bool'], 'log' => ['float', 'number'=>'float', 'base='=>'float'], 'log10' => ['float', 'number'=>'float'], 'log1p' => ['float', 'number'=>'float'], 'LogicException::__clone' => ['void'], 'LogicException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?LogicException'], 'LogicException::__toString' => ['string'], 'LogicException::getCode' => ['int'], 'LogicException::getFile' => ['string'], 'LogicException::getLine' => ['int'], 'LogicException::getMessage' => ['string'], 'LogicException::getPrevious' => ['Throwable|LogicException|null'], 'LogicException::getTrace' => ['list>'], 'LogicException::getTraceAsString' => ['string'], 'long2ip' => ['string', 'proper_address'=>'string|int'], 'lstat' => ['array|false', 'filename'=>'string'], 'ltrim' => ['string', 'string'=>'string', 'character_mask='=>'string'], 'Lua::__call' => ['mixed', 'lua_func'=>'callable', 'args='=>'array', 'use_self='=>'int'], 'Lua::__construct' => ['void', 'lua_script_file'=>'string'], 'Lua::assign' => ['?Lua', 'name'=>'string', 'value'=>'mixed'], 'Lua::call' => ['mixed', 'lua_func'=>'callable', 'args='=>'array', 'use_self='=>'int'], 'Lua::eval' => ['mixed', 'statements'=>'string'], 'Lua::getVersion' => ['string'], 'Lua::include' => ['mixed', 'file'=>'string'], 'Lua::registerCallback' => ['Lua|null|false', 'name'=>'string', 'function'=>'callable'], 'LuaClosure::__invoke' => ['void', 'arg'=>'mixed', '...args='=>'mixed'], 'lzf_compress' => ['string', 'data'=>'string'], 'lzf_decompress' => ['string', 'data'=>'string'], 'lzf_optimized_for' => ['int'], 'm_checkstatus' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_completeauthorizations' => ['int', 'conn'=>'resource', 'array'=>'int'], 'm_connect' => ['int', 'conn'=>'resource'], 'm_connectionerror' => ['string', 'conn'=>'resource'], 'm_deletetrans' => ['bool', 'conn'=>'resource', 'identifier'=>'int'], 'm_destroyconn' => ['bool', 'conn'=>'resource'], 'm_destroyengine' => ['void'], 'm_getcell' => ['string', 'conn'=>'resource', 'identifier'=>'int', 'column'=>'string', 'row'=>'int'], 'm_getcellbynum' => ['string', 'conn'=>'resource', 'identifier'=>'int', 'column'=>'int', 'row'=>'int'], 'm_getcommadelimited' => ['string', 'conn'=>'resource', 'identifier'=>'int'], 'm_getheader' => ['string', 'conn'=>'resource', 'identifier'=>'int', 'column_num'=>'int'], 'm_initconn' => ['resource'], 'm_initengine' => ['int', 'location'=>'string'], 'm_iscommadelimited' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_maxconntimeout' => ['bool', 'conn'=>'resource', 'secs'=>'int'], 'm_monitor' => ['int', 'conn'=>'resource'], 'm_numcolumns' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_numrows' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_parsecommadelimited' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_responsekeys' => ['array', 'conn'=>'resource', 'identifier'=>'int'], 'm_responseparam' => ['string', 'conn'=>'resource', 'identifier'=>'int', 'key'=>'string'], 'm_returnstatus' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_setblocking' => ['int', 'conn'=>'resource', 'tf'=>'int'], 'm_setdropfile' => ['int', 'conn'=>'resource', 'directory'=>'string'], 'm_setip' => ['int', 'conn'=>'resource', 'host'=>'string', 'port'=>'int'], 'm_setssl' => ['int', 'conn'=>'resource', 'host'=>'string', 'port'=>'int'], 'm_setssl_cafile' => ['int', 'conn'=>'resource', 'cafile'=>'string'], 'm_setssl_files' => ['int', 'conn'=>'resource', 'sslkeyfile'=>'string', 'sslcertfile'=>'string'], 'm_settimeout' => ['int', 'conn'=>'resource', 'seconds'=>'int'], 'm_sslcert_gen_hash' => ['string', 'filename'=>'string'], 'm_transactionssent' => ['int', 'conn'=>'resource'], 'm_transinqueue' => ['int', 'conn'=>'resource'], 'm_transkeyval' => ['int', 'conn'=>'resource', 'identifier'=>'int', 'key'=>'string', 'value'=>'string'], 'm_transnew' => ['int', 'conn'=>'resource'], 'm_transsend' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_uwait' => ['int', 'microsecs'=>'int'], 'm_validateidentifier' => ['int', 'conn'=>'resource', 'tf'=>'int'], 'm_verifyconnection' => ['bool', 'conn'=>'resource', 'tf'=>'int'], 'm_verifysslcert' => ['bool', 'conn'=>'resource', 'tf'=>'int'], 'magic_quotes_runtime' => ['bool', 'new_setting'=>'bool'], 'mail' => ['bool', 'to'=>'string', 'subject'=>'string', 'message'=>'string', 'additional_headers='=>'string|array|null', 'additional_parameters='=>'string'], 'mailparse_determine_best_xfer_encoding' => ['string', 'fp'=>'resource'], 'mailparse_msg_create' => ['resource'], 'mailparse_msg_extract_part' => ['void', 'mimemail'=>'resource', 'msgbody'=>'string', 'callbackfunc='=>'callable'], 'mailparse_msg_extract_part_file' => ['string', 'mimemail'=>'resource', 'filename'=>'mixed', 'callbackfunc='=>'callable'], 'mailparse_msg_extract_whole_part_file' => ['string', 'mimemail'=>'resource', 'filename'=>'string', 'callbackfunc='=>'callable'], 'mailparse_msg_free' => ['bool', 'mimemail'=>'resource'], 'mailparse_msg_get_part' => ['resource', 'mimemail'=>'resource', 'mimesection'=>'string'], 'mailparse_msg_get_part_data' => ['array', 'mimemail'=>'resource'], 'mailparse_msg_get_structure' => ['array', 'mimemail'=>'resource'], 'mailparse_msg_parse' => ['bool', 'mimemail'=>'resource', 'data'=>'string'], 'mailparse_msg_parse_file' => ['resource|false', 'filename'=>'string'], 'mailparse_rfc822_parse_addresses' => ['array', 'addresses'=>'string'], 'mailparse_stream_encode' => ['bool', 'sourcefp'=>'resource', 'destfp'=>'resource', 'encoding'=>'string'], 'mailparse_uudecode_all' => ['array', 'fp'=>'resource'], 'mapObj::__construct' => ['void', 'map_file_name'=>'string', 'new_map_path'=>'string'], 'mapObj::appendOutputFormat' => ['int', 'outputFormat'=>'outputformatObj'], 'mapObj::applyconfigoptions' => ['int'], 'mapObj::applySLD' => ['int', 'sldxml'=>'string'], 'mapObj::applySLDURL' => ['int', 'sldurl'=>'string'], 'mapObj::convertToString' => ['string'], 'mapObj::draw' => ['?imageObj'], 'mapObj::drawLabelCache' => ['int', 'image'=>'imageObj'], 'mapObj::drawLegend' => ['imageObj'], 'mapObj::drawQuery' => ['?imageObj'], 'mapObj::drawReferenceMap' => ['imageObj'], 'mapObj::drawScaleBar' => ['imageObj'], 'mapObj::embedLegend' => ['int', 'image'=>'imageObj'], 'mapObj::embedScalebar' => ['int', 'image'=>'imageObj'], 'mapObj::free' => ['void'], 'mapObj::generateSLD' => ['string'], 'mapObj::getAllGroupNames' => ['array'], 'mapObj::getAllLayerNames' => ['array'], 'mapObj::getColorbyIndex' => ['colorObj', 'iCloIndex'=>'int'], 'mapObj::getConfigOption' => ['string', 'key'=>'string'], 'mapObj::getLabel' => ['labelcacheMemberObj', 'index'=>'int'], 'mapObj::getLayer' => ['layerObj', 'index'=>'int'], 'mapObj::getLayerByName' => ['layerObj', 'layer_name'=>'string'], 'mapObj::getLayersDrawingOrder' => ['array'], 'mapObj::getLayersIndexByGroup' => ['array', 'groupname'=>'string'], 'mapObj::getMetaData' => ['int', 'name'=>'string'], 'mapObj::getNumSymbols' => ['int'], 'mapObj::getOutputFormat' => ['?outputformatObj', 'index'=>'int'], 'mapObj::getProjection' => ['string'], 'mapObj::getSymbolByName' => ['int', 'symbol_name'=>'string'], 'mapObj::getSymbolObjectById' => ['symbolObj', 'symbolid'=>'int'], 'mapObj::loadMapContext' => ['int', 'filename'=>'string', 'unique_layer_name'=>'bool'], 'mapObj::loadOWSParameters' => ['int', 'request'=>'OwsrequestObj', 'version'=>'string'], 'mapObj::moveLayerDown' => ['int', 'layerindex'=>'int'], 'mapObj::moveLayerUp' => ['int', 'layerindex'=>'int'], 'mapObj::ms_newMapObjFromString' => ['mapObj', 'map_file_string'=>'string', 'new_map_path'=>'string'], 'mapObj::offsetExtent' => ['int', 'x'=>'float', 'y'=>'float'], 'mapObj::owsDispatch' => ['int', 'request'=>'OwsrequestObj'], 'mapObj::prepareImage' => ['imageObj'], 'mapObj::prepareQuery' => ['void'], 'mapObj::processLegendTemplate' => ['string', 'params'=>'array'], 'mapObj::processQueryTemplate' => ['string', 'params'=>'array', 'generateimages'=>'bool'], 'mapObj::processTemplate' => ['string', 'params'=>'array', 'generateimages'=>'bool'], 'mapObj::queryByFeatures' => ['int', 'slayer'=>'int'], 'mapObj::queryByIndex' => ['int', 'layerindex'=>'', 'tileindex'=>'', 'shapeindex'=>'', 'addtoquery'=>''], 'mapObj::queryByPoint' => ['int', 'point'=>'pointObj', 'mode'=>'int', 'buffer'=>'float'], 'mapObj::queryByRect' => ['int', 'rect'=>'rectObj'], 'mapObj::queryByShape' => ['int', 'shape'=>'shapeObj'], 'mapObj::removeLayer' => ['layerObj', 'nIndex'=>'int'], 'mapObj::removeMetaData' => ['int', 'name'=>'string'], 'mapObj::removeOutputFormat' => ['int', 'name'=>'string'], 'mapObj::save' => ['int', 'filename'=>'string'], 'mapObj::saveMapContext' => ['int', 'filename'=>'string'], 'mapObj::saveQuery' => ['int', 'filename'=>'string', 'results'=>'int'], 'mapObj::scaleExtent' => ['int', 'zoomfactor'=>'float', 'minscaledenom'=>'float', 'maxscaledenom'=>'float'], 'mapObj::selectOutputFormat' => ['int', 'type'=>'string'], 'mapObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'mapObj::setCenter' => ['int', 'center'=>'pointObj'], 'mapObj::setConfigOption' => ['int', 'key'=>'string', 'value'=>'string'], 'mapObj::setExtent' => ['void', 'minx'=>'float', 'miny'=>'float', 'maxx'=>'float', 'maxy'=>'float'], 'mapObj::setFontSet' => ['int', 'fileName'=>'string'], 'mapObj::setMetaData' => ['int', 'name'=>'string', 'value'=>'string'], 'mapObj::setProjection' => ['int', 'proj_params'=>'string', 'bSetUnitsAndExtents'=>'bool'], 'mapObj::setRotation' => ['int', 'rotation_angle'=>'float'], 'mapObj::setSize' => ['int', 'width'=>'int', 'height'=>'int'], 'mapObj::setSymbolSet' => ['int', 'fileName'=>'string'], 'mapObj::setWKTProjection' => ['int', 'proj_params'=>'string', 'bSetUnitsAndExtents'=>'bool'], 'mapObj::zoomPoint' => ['int', 'nZoomFactor'=>'int', 'oPixelPos'=>'pointObj', 'nImageWidth'=>'int', 'nImageHeight'=>'int', 'oGeorefExt'=>'rectObj'], 'mapObj::zoomRectangle' => ['int', 'oPixelExt'=>'rectObj', 'nImageWidth'=>'int', 'nImageHeight'=>'int', 'oGeorefExt'=>'rectObj'], 'mapObj::zoomScale' => ['int', 'nScaleDenom'=>'float', 'oPixelPos'=>'pointObj', 'nImageWidth'=>'int', 'nImageHeight'=>'int', 'oGeorefExt'=>'rectObj', 'oMaxGeorefExt'=>'rectObj'], 'max' => ['mixed', 'arg1'=>'non-empty-array'], 'max\'1' => ['mixed', 'arg1'=>'', 'arg2'=>'', '...args='=>''], 'maxdb::__construct' => ['void', 'host='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'maxdb::affected_rows' => ['int', 'link'=>''], 'maxdb::auto_commit' => ['bool', 'link'=>'', 'mode'=>'bool'], 'maxdb::change_user' => ['bool', 'link'=>'', 'user'=>'string', 'password'=>'string', 'database'=>'string'], 'maxdb::character_set_name' => ['string', 'link'=>''], 'maxdb::close' => ['bool', 'link'=>''], 'maxdb::commit' => ['bool', 'link'=>''], 'maxdb::disable_reads_from_master' => ['', 'link'=>''], 'maxdb::errno' => ['int', 'link'=>''], 'maxdb::error' => ['string', 'link'=>''], 'maxdb::field_count' => ['int', 'link'=>''], 'maxdb::get_host_info' => ['string', 'link'=>''], 'maxdb::info' => ['string', 'link'=>''], 'maxdb::insert_id' => ['', 'link'=>''], 'maxdb::kill' => ['bool', 'link'=>'', 'processid'=>'int'], 'maxdb::more_results' => ['bool', 'link'=>''], 'maxdb::multi_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb::next_result' => ['bool', 'link'=>''], 'maxdb::num_rows' => ['int', 'result'=>''], 'maxdb::options' => ['bool', 'link'=>'', 'option'=>'int', 'value'=>''], 'maxdb::ping' => ['bool', 'link'=>''], 'maxdb::prepare' => ['maxdb_stmt', 'link'=>'', 'query'=>'string'], 'maxdb::protocol_version' => ['string', 'link'=>''], 'maxdb::query' => ['', 'link'=>'', 'query'=>'string', 'resultmode='=>'int'], 'maxdb::real_connect' => ['bool', 'link'=>'', 'hostname='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'maxdb::real_escape_string' => ['string', 'link'=>'', 'escapestr'=>'string'], 'maxdb::real_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb::rollback' => ['bool', 'link'=>''], 'maxdb::rpl_query_type' => ['int', 'link'=>''], 'maxdb::select_db' => ['bool', 'link'=>'', 'dbname'=>'string'], 'maxdb::send_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb::server_info' => ['string', 'link'=>''], 'maxdb::server_version' => ['int', 'link'=>''], 'maxdb::sqlstate' => ['string', 'link'=>''], 'maxdb::ssl_set' => ['bool', 'link'=>'', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'maxdb::stat' => ['string', 'link'=>''], 'maxdb::stmt_init' => ['object', 'link'=>''], 'maxdb::store_result' => ['bool', 'link'=>''], 'maxdb::thread_id' => ['int', 'link'=>''], 'maxdb::use_result' => ['resource', 'link'=>''], 'maxdb::warning_count' => ['int', 'link'=>''], 'maxdb_affected_rows' => ['int', 'link'=>'resource'], 'maxdb_autocommit' => ['bool', 'link'=>'', 'mode'=>'bool'], 'maxdb_change_user' => ['bool', 'link'=>'', 'user'=>'string', 'password'=>'string', 'database'=>'string'], 'maxdb_character_set_name' => ['string', 'link'=>''], 'maxdb_close' => ['bool', 'link'=>''], 'maxdb_commit' => ['bool', 'link'=>''], 'maxdb_connect' => ['resource', 'host='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'maxdb_connect_errno' => ['int'], 'maxdb_connect_error' => ['string'], 'maxdb_data_seek' => ['bool', 'result'=>'', 'offset'=>'int'], 'maxdb_debug' => ['void', 'debug'=>'string'], 'maxdb_disable_reads_from_master' => ['', 'link'=>''], 'maxdb_disable_rpl_parse' => ['bool', 'link'=>'resource'], 'maxdb_dump_debug_info' => ['bool', 'link'=>'resource'], 'maxdb_embedded_connect' => ['resource', 'dbname='=>'string'], 'maxdb_enable_reads_from_master' => ['bool', 'link'=>'resource'], 'maxdb_enable_rpl_parse' => ['bool', 'link'=>'resource'], 'maxdb_errno' => ['int', 'link'=>'resource'], 'maxdb_error' => ['string', 'link'=>'resource'], 'maxdb_fetch_array' => ['', 'result'=>'', 'resulttype='=>'int'], 'maxdb_fetch_assoc' => ['array', 'result'=>''], 'maxdb_fetch_field' => ['', 'result'=>''], 'maxdb_fetch_field_direct' => ['', 'result'=>'', 'fieldnr'=>'int'], 'maxdb_fetch_fields' => ['', 'result'=>''], 'maxdb_fetch_lengths' => ['array', 'result'=>'resource'], 'maxdb_fetch_object' => ['object', 'result'=>'object'], 'maxdb_fetch_row' => ['', 'result'=>''], 'maxdb_field_count' => ['int', 'link'=>''], 'maxdb_field_seek' => ['bool', 'result'=>'', 'fieldnr'=>'int'], 'maxdb_field_tell' => ['int', 'result'=>'resource'], 'maxdb_free_result' => ['', 'result'=>''], 'maxdb_get_client_info' => ['string'], 'maxdb_get_client_version' => ['int'], 'maxdb_get_host_info' => ['string', 'link'=>'resource'], 'maxdb_get_proto_info' => ['string', 'link'=>'resource'], 'maxdb_get_server_info' => ['string', 'link'=>'resource'], 'maxdb_get_server_version' => ['int', 'link'=>'resource'], 'maxdb_info' => ['string', 'link'=>'resource'], 'maxdb_init' => ['resource'], 'maxdb_insert_id' => ['mixed', 'link'=>'resource'], 'maxdb_kill' => ['bool', 'link'=>'', 'processid'=>'int'], 'maxdb_master_query' => ['bool', 'link'=>'resource', 'query'=>'string'], 'maxdb_more_results' => ['bool', 'link'=>'resource'], 'maxdb_multi_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb_next_result' => ['bool', 'link'=>'resource'], 'maxdb_num_fields' => ['int', 'result'=>'resource'], 'maxdb_num_rows' => ['int', 'result'=>'resource'], 'maxdb_options' => ['bool', 'link'=>'', 'option'=>'int', 'value'=>''], 'maxdb_ping' => ['bool', 'link'=>''], 'maxdb_prepare' => ['maxdb_stmt', 'link'=>'', 'query'=>'string'], 'maxdb_query' => ['', 'link'=>'', 'query'=>'string', 'resultmode='=>'int'], 'maxdb_real_connect' => ['bool', 'link'=>'', 'hostname='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'maxdb_real_escape_string' => ['string', 'link'=>'', 'escapestr'=>'string'], 'maxdb_real_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb_report' => ['bool', 'flags'=>'int'], 'maxdb_result::current_field' => ['int', 'result'=>''], 'maxdb_result::data_seek' => ['bool', 'result'=>'', 'offset'=>'int'], 'maxdb_result::fetch_array' => ['', 'result'=>'', 'resulttype='=>'int'], 'maxdb_result::fetch_assoc' => ['array', 'result'=>''], 'maxdb_result::fetch_field' => ['', 'result'=>''], 'maxdb_result::fetch_field_direct' => ['', 'result'=>'', 'fieldnr'=>'int'], 'maxdb_result::fetch_fields' => ['', 'result'=>''], 'maxdb_result::fetch_object' => ['object', 'result'=>'object'], 'maxdb_result::fetch_row' => ['', 'result'=>''], 'maxdb_result::field_count' => ['int', 'result'=>''], 'maxdb_result::field_seek' => ['bool', 'result'=>'', 'fieldnr'=>'int'], 'maxdb_result::free' => ['', 'result'=>''], 'maxdb_result::lengths' => ['array', 'result'=>''], 'maxdb_rollback' => ['bool', 'link'=>''], 'maxdb_rpl_parse_enabled' => ['int', 'link'=>'resource'], 'maxdb_rpl_probe' => ['bool', 'link'=>'resource'], 'maxdb_rpl_query_type' => ['int', 'link'=>''], 'maxdb_select_db' => ['bool', 'link'=>'resource', 'dbname'=>'string'], 'maxdb_send_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb_server_end' => ['void'], 'maxdb_server_init' => ['bool', 'server='=>'array', 'groups='=>'array'], 'maxdb_sqlstate' => ['string', 'link'=>'resource'], 'maxdb_ssl_set' => ['bool', 'link'=>'', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'maxdb_stat' => ['string', 'link'=>''], 'maxdb_stmt::affected_rows' => ['int', 'stmt'=>''], 'maxdb_stmt::bind_param' => ['bool', 'stmt'=>'', 'types'=>'string', '&...rw_var'=>''], 'maxdb_stmt::bind_param\'1' => ['bool', 'stmt'=>'', 'types'=>'string', '&rw_var'=>'array'], 'maxdb_stmt::bind_result' => ['bool', 'stmt'=>'', '&w_var1'=>'', '&...w_vars='=>''], 'maxdb_stmt::close' => ['bool', 'stmt'=>''], 'maxdb_stmt::close_long_data' => ['bool', 'stmt'=>'', 'param_nr'=>'int'], 'maxdb_stmt::data_seek' => ['bool', 'statement'=>'', 'offset'=>'int'], 'maxdb_stmt::errno' => ['int', 'stmt'=>''], 'maxdb_stmt::error' => ['string', 'stmt'=>''], 'maxdb_stmt::execute' => ['bool', 'stmt'=>''], 'maxdb_stmt::fetch' => ['bool', 'stmt'=>''], 'maxdb_stmt::free_result' => ['', 'stmt'=>''], 'maxdb_stmt::num_rows' => ['int', 'stmt'=>''], 'maxdb_stmt::param_count' => ['int', 'stmt'=>''], 'maxdb_stmt::prepare' => ['', 'stmt'=>'', 'query'=>'string'], 'maxdb_stmt::reset' => ['bool', 'stmt'=>''], 'maxdb_stmt::result_metadata' => ['resource', 'stmt'=>''], 'maxdb_stmt::send_long_data' => ['bool', 'stmt'=>'', 'param_nr'=>'int', 'data'=>'string'], 'maxdb_stmt::stmt_send_long_data' => ['bool', 'param_nr'=>'int', 'data'=>'string'], 'maxdb_stmt::store_result' => ['bool'], 'maxdb_stmt_affected_rows' => ['int', 'stmt'=>'resource'], 'maxdb_stmt_bind_param' => ['bool', 'stmt'=>'', 'types'=>'string', 'var1'=>'', '...args='=>'', 'var='=>'array'], 'maxdb_stmt_bind_result' => ['bool', 'stmt'=>'', '&w_var1'=>'', '&...w_vars='=>''], 'maxdb_stmt_close' => ['bool', 'stmt'=>''], 'maxdb_stmt_close_long_data' => ['bool', 'stmt'=>'', 'param_nr'=>'int'], 'maxdb_stmt_data_seek' => ['bool', 'statement'=>'', 'offset'=>'int'], 'maxdb_stmt_errno' => ['int', 'stmt'=>'resource'], 'maxdb_stmt_error' => ['string', 'stmt'=>'resource'], 'maxdb_stmt_execute' => ['bool', 'stmt'=>''], 'maxdb_stmt_fetch' => ['bool', 'stmt'=>''], 'maxdb_stmt_free_result' => ['', 'stmt'=>''], 'maxdb_stmt_init' => ['object', 'link'=>''], 'maxdb_stmt_num_rows' => ['int', 'stmt'=>'resource'], 'maxdb_stmt_param_count' => ['int', 'stmt'=>'resource'], 'maxdb_stmt_prepare' => ['', 'stmt'=>'', 'query'=>'string'], 'maxdb_stmt_reset' => ['bool', 'stmt'=>''], 'maxdb_stmt_result_metadata' => ['resource', 'stmt'=>''], 'maxdb_stmt_send_long_data' => ['bool', 'stmt'=>'', 'param_nr'=>'int', 'data'=>'string'], 'maxdb_stmt_sqlstate' => ['string', 'stmt'=>'resource'], 'maxdb_stmt_store_result' => ['bool', 'stmt'=>''], 'maxdb_store_result' => ['bool', 'link'=>''], 'maxdb_thread_id' => ['int', 'link'=>'resource'], 'maxdb_thread_safe' => ['bool'], 'maxdb_use_result' => ['resource', 'link'=>''], 'maxdb_warning_count' => ['int', 'link'=>'resource'], 'mb_check_encoding' => ['bool', 'var='=>'string', 'encoding='=>'string'], 'mb_chr' => ['string|false', 'cp'=>'int', 'encoding='=>'string'], 'mb_convert_case' => ['string|false', 'sourcestring'=>'string', 'mode'=>'int', 'encoding='=>'string'], 'mb_convert_encoding' => ['string', 'val'=>'string', 'to_encoding'=>'string', 'from_encoding='=>'mixed'], 'mb_convert_encoding\'1' => ['array', 'val'=>'array', 'to_encoding'=>'string', 'from_encoding='=>'mixed'], 'mb_convert_kana' => ['string|false', 'string'=>'string', 'option='=>'string', 'encoding='=>'string'], 'mb_convert_variables' => ['string|false', 'to_encoding'=>'string', 'from_encoding'=>'array|string', '&rw_vars'=>'string|array|object', '&...rw_vars='=>'string|array|object'], 'mb_decode_mimeheader' => ['string', 'string'=>'string'], 'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string', 'is_hex='=>'bool'], 'mb_detect_encoding' => ['string|false', 'string'=>'string', 'encoding_list='=>'mixed', 'strict='=>'bool'], 'mb_detect_order' => ['bool|list', 'encoding_list='=>'mixed'], 'mb_encode_mimeheader' => ['string|false', 'string'=>'string', 'charset='=>'string', 'transfer_encoding='=>'string', 'linefeed='=>'string', 'indent='=>'int'], 'mb_encode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string', 'is_hex='=>'bool'], 'mb_encoding_aliases' => ['list|false', 'encoding'=>'string'], 'mb_ereg' => ['int|false', 'pattern'=>'string', 'string'=>'string', '&w_registers='=>'array'], 'mb_ereg_match' => ['bool', 'pattern'=>'string', 'string'=>'string', 'option='=>'string'], 'mb_ereg_replace' => ['string|false', 'pattern'=>'string', 'replacement'=>'string', 'string'=>'string', 'option='=>'string'], 'mb_ereg_replace_callback' => ['string|false', 'pattern'=>'string', 'callback'=>'callable', 'string'=>'string', 'option='=>'string'], 'mb_ereg_search' => ['bool', 'pattern='=>'string', 'option='=>'string'], 'mb_ereg_search_getpos' => ['int'], 'mb_ereg_search_getregs' => ['string[]|false'], 'mb_ereg_search_init' => ['bool', 'string'=>'string', 'pattern='=>'string', 'option='=>'string'], 'mb_ereg_search_pos' => ['int[]|false', 'pattern='=>'string', 'option='=>'string'], 'mb_ereg_search_regs' => ['string[]|false', 'pattern='=>'string', 'option='=>'string'], 'mb_ereg_search_setpos' => ['bool', 'position'=>'int'], 'mb_eregi' => ['int|false', 'pattern'=>'string', 'string'=>'string', '&w_registers='=>'array'], 'mb_eregi_replace' => ['string|false', 'pattern'=>'string', 'replacement'=>'string', 'string'=>'string', 'option='=>'string'], 'mb_get_info' => ['array|mixed', 'type='=>'string'], 'mb_http_input' => ['string|false', 'type='=>'string'], 'mb_http_output' => ['string|bool', 'encoding='=>'string'], 'mb_internal_encoding' => ['string|bool', 'encoding='=>'string'], 'mb_language' => ['string|bool', 'language='=>'string'], 'mb_list_encodings' => ['list'], 'mb_ord' => ['int|false', 'string'=>'string', 'enc='=>'string'], 'mb_output_handler' => ['string', 'contents'=>'string', 'status'=>'int'], 'mb_parse_str' => ['bool', 'encoded_string'=>'string', '&w_result='=>'array'], 'mb_preferred_mime_name' => ['string|false', 'encoding'=>'string'], 'mb_regex_encoding' => ['string|bool', 'encoding='=>'string'], 'mb_regex_set_options' => ['string', 'options='=>'string'], 'mb_scrub' => ['string|false', 'string'=>'string', 'enc='=>'string'], 'mb_send_mail' => ['bool', 'to'=>'string', 'subject'=>'string', 'message'=>'string', 'additional_headers='=>'string|array', 'additional_parameter='=>'string'], 'mb_split' => ['list', 'pattern'=>'string', 'string'=>'string', 'limit='=>'int'], 'mb_strcut' => ['string', 'str'=>'string', 'start'=>'int', 'length='=>'?int', 'encoding='=>'string'], 'mb_strimwidth' => ['string|false', 'string'=>'string', 'start'=>'int', 'width'=>'int', 'trimmarker='=>'string', 'encoding='=>'string'], 'mb_stripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strlen' => ['int|false', 'string'=>'string', 'encoding='=>'string'], 'mb_strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_strrchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strrichr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strtolower' => ['string|false', 'string'=>'string', 'encoding='=>'string'], 'mb_strtoupper' => ['string|false', 'string'=>'string', 'encoding='=>'string'], 'mb_strwidth' => ['int|false', 'string'=>'string', 'encoding='=>'string'], 'mb_substitute_character' => ['bool|int|string', 'substchar='=>'mixed'], 'mb_substr' => ['string|false', 'string'=>'string', 'start'=>'int', 'length='=>'?int', 'encoding='=>'string'], 'mb_substr_count' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'encoding='=>'string'], 'mcrypt_cbc' => ['string', 'cipher'=>'string|int', 'key'=>'string', 'data'=>'string', 'mode'=>'int', 'iv='=>'string'], 'mcrypt_cfb' => ['string', 'cipher'=>'string|int', 'key'=>'string', 'data'=>'string', 'mode'=>'int', 'iv='=>'string'], 'mcrypt_create_iv' => ['string|false', 'size'=>'int', 'source='=>'int'], 'mcrypt_decrypt' => ['string', 'cipher'=>'string', 'key'=>'string', 'data'=>'string', 'mode'=>'string', 'iv='=>'string'], 'mcrypt_ecb' => ['string', 'cipher'=>'string|int', 'key'=>'string', 'data'=>'string', 'mode'=>'int', 'iv='=>'string'], 'mcrypt_enc_get_algorithms_name' => ['string', 'td'=>'resource'], 'mcrypt_enc_get_block_size' => ['int', 'td'=>'resource'], 'mcrypt_enc_get_iv_size' => ['int', 'td'=>'resource'], 'mcrypt_enc_get_key_size' => ['int', 'td'=>'resource'], 'mcrypt_enc_get_modes_name' => ['string', 'td'=>'resource'], 'mcrypt_enc_get_supported_key_sizes' => ['array', 'td'=>'resource'], 'mcrypt_enc_is_block_algorithm' => ['bool', 'td'=>'resource'], 'mcrypt_enc_is_block_algorithm_mode' => ['bool', 'td'=>'resource'], 'mcrypt_enc_is_block_mode' => ['bool', 'td'=>'resource'], 'mcrypt_enc_self_test' => ['int|false', 'td'=>'resource'], 'mcrypt_encrypt' => ['string', 'cipher'=>'string', 'key'=>'string', 'data'=>'string', 'mode'=>'string', 'iv='=>'string'], 'mcrypt_generic' => ['string', 'td'=>'resource', 'data'=>'string'], 'mcrypt_generic_deinit' => ['bool', 'td'=>'resource'], 'mcrypt_generic_end' => ['bool', 'td'=>'resource'], 'mcrypt_generic_init' => ['int|false', 'td'=>'resource', 'key'=>'string', 'iv'=>'string'], 'mcrypt_get_block_size' => ['int', 'cipher'=>'int|string', 'module'=>'string'], 'mcrypt_get_cipher_name' => ['string|false', 'cipher'=>'int|string'], 'mcrypt_get_iv_size' => ['int|false', 'cipher'=>'int|string', 'module'=>'string'], 'mcrypt_get_key_size' => ['int', 'cipher'=>'int|string', 'module'=>'string'], 'mcrypt_list_algorithms' => ['array', 'lib_dir='=>'string'], 'mcrypt_list_modes' => ['array', 'lib_dir='=>'string'], 'mcrypt_module_close' => ['bool', 'td'=>'resource'], 'mcrypt_module_get_algo_block_size' => ['int', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_get_algo_key_size' => ['int', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_get_supported_key_sizes' => ['array', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_is_block_algorithm' => ['bool', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_is_block_algorithm_mode' => ['bool', 'mode'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_is_block_mode' => ['bool', 'mode'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_open' => ['resource|false', 'cipher'=>'string', 'cipher_directory'=>'string', 'mode'=>'string', 'mode_directory'=>'string'], 'mcrypt_module_self_test' => ['bool', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_ofb' => ['string', 'cipher'=>'int|string', 'key'=>'string', 'data'=>'string', 'mode'=>'int', 'iv='=>'string'], 'md5' => ['string', 'string'=>'string', 'raw_output='=>'bool'], 'md5_file' => ['string|false', 'filename'=>'string', 'raw_output='=>'bool'], 'mdecrypt_generic' => ['string', 'td'=>'resource', 'data'=>'string'], 'Memcache::add' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'Memcache::addServer' => ['bool', 'host'=>'string', 'port='=>'int', 'persistent='=>'bool', 'weight='=>'int', 'timeout='=>'int', 'retry_interval='=>'int', 'status='=>'bool', 'failure_callback='=>'callable', 'timeoutms='=>'int'], 'Memcache::append' => [''], 'Memcache::cas' => [''], 'Memcache::close' => ['bool'], 'Memcache::connect' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'Memcache::decrement' => ['int', 'key'=>'string', 'value='=>'int'], 'Memcache::delete' => ['bool', 'key'=>'string', 'timeout='=>'int'], 'Memcache::findServer' => [''], 'Memcache::flush' => ['bool'], 'Memcache::get' => ['string|array|false', 'key'=>'string', 'flags='=>'array', 'keys='=>'array'], 'Memcache::get\'1' => ['array', 'key'=>'string[]', 'flags='=>'int[]'], 'Memcache::getExtendedStats' => ['array', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'Memcache::getServerStatus' => ['int', 'host'=>'string', 'port='=>'int'], 'Memcache::getStats' => ['array', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'Memcache::getVersion' => ['string'], 'Memcache::increment' => ['int', 'key'=>'string', 'value='=>'int'], 'Memcache::pconnect' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'Memcache::prepend' => ['string'], 'Memcache::replace' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'Memcache::set' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'Memcache::setCompressThreshold' => ['bool', 'threshold'=>'int', 'min_savings='=>'float'], 'Memcache::setFailureCallback' => [''], 'Memcache::setServerParams' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'int', 'retry_interval='=>'int', 'status='=>'bool', 'failure_callback='=>'callable'], 'memcache_add' => ['bool', 'memcache_obj'=>'Memcache', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'memcache_add_server' => ['bool', 'memcache_obj'=>'Memcache', 'host'=>'string', 'port='=>'int', 'persistent='=>'bool', 'weight='=>'int', 'timeout='=>'int', 'retry_interval='=>'int', 'status='=>'bool', 'failure_callback='=>'callable', 'timeoutms='=>'int'], 'memcache_append' => ['', 'memcache_obj'=>'Memcache'], 'memcache_cas' => ['', 'memcache_obj'=>'Memcache'], 'memcache_close' => ['bool', 'memcache_obj'=>'Memcache'], 'memcache_connect' => ['Memcache|false', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'memcache_debug' => ['bool', 'on_off'=>'bool'], 'memcache_decrement' => ['int', 'memcache_obj'=>'Memcache', 'key'=>'string', 'value='=>'int'], 'memcache_delete' => ['bool', 'memcache_obj'=>'Memcache', 'key'=>'string', 'timeout='=>'int'], 'memcache_flush' => ['bool', 'memcache_obj'=>'Memcache'], 'memcache_get' => ['string', 'memcache_obj'=>'Memcache', 'key'=>'string', 'flags='=>'int'], 'memcache_get\'1' => ['array', 'memcache_obj'=>'Memcache', 'key'=>'string[]', 'flags='=>'int[]'], 'memcache_get_extended_stats' => ['array', 'memcache_obj'=>'Memcache', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'memcache_get_server_status' => ['int', 'memcache_obj'=>'Memcache', 'host'=>'string', 'port='=>'int'], 'memcache_get_stats' => ['array', 'memcache_obj'=>'Memcache', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'memcache_get_version' => ['string', 'memcache_obj'=>'Memcache'], 'memcache_increment' => ['int', 'memcache_obj'=>'Memcache', 'key'=>'string', 'value='=>'int'], 'memcache_pconnect' => ['Memcache|false', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'memcache_prepend' => ['string', 'memcache_obj'=>'Memcache'], 'memcache_replace' => ['bool', 'memcache_obj'=>'Memcache', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'memcache_set' => ['bool', 'memcache_obj'=>'Memcache', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'memcache_set_compress_threshold' => ['bool', 'memcache_obj'=>'Memcache', 'threshold'=>'int', 'min_savings='=>'float'], 'memcache_set_failure_callback' => ['', 'memcache_obj'=>'Memcache'], 'memcache_set_server_params' => ['bool', 'memcache_obj'=>'Memcache', 'host'=>'string', 'port='=>'int', 'timeout='=>'int', 'retry_interval='=>'int', 'status='=>'bool', 'failure_callback='=>'callable'], 'Memcached::__construct' => ['void', 'persistent_id='=>'mixed|string', 'on_new_object_cb='=>'mixed'], 'Memcached::add' => ['bool', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::addByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::addServer' => ['bool', 'host'=>'string', 'port'=>'int', 'weight='=>'int'], 'Memcached::addServers' => ['bool', 'servers'=>'array'], 'Memcached::append' => ['bool', 'key'=>'string', 'value'=>'string'], 'Memcached::appendByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'string'], 'Memcached::cas' => ['bool', 'cas_token'=>'float', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::casByKey' => ['bool', 'cas_token'=>'float', 'server_key'=>'string', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::decrement' => ['int|false', 'key'=>'string', 'offset='=>'int', 'initial_value='=>'int', 'expiry='=>'int'], 'Memcached::decrementByKey' => ['int|false', 'server_key'=>'string', 'key'=>'string', 'offset='=>'int', 'initial_value='=>'int', 'expiry='=>'int'], 'Memcached::delete' => ['bool', 'key'=>'string', 'time='=>'int'], 'Memcached::deleteByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'time='=>'int'], 'Memcached::deleteMulti' => ['array', 'keys'=>'array', 'time='=>'int'], 'Memcached::deleteMultiByKey' => ['bool', 'server_key'=>'string', 'keys'=>'array', 'time='=>'int'], 'Memcached::fetch' => ['array|false'], 'Memcached::fetchAll' => ['array|false'], 'Memcached::flush' => ['bool', 'delay='=>'int'], 'Memcached::flushBuffers' => [''], 'Memcached::get' => ['mixed|false', 'key'=>'string', 'cache_cb='=>'?callable', 'flags='=>'int'], 'Memcached::getAllKeys' => ['array|false'], 'Memcached::getByKey' => ['mixed|false', 'server_key'=>'string', 'key'=>'string', 'value_cb='=>'?callable', 'flags='=>'int'], 'Memcached::getDelayed' => ['bool', 'keys'=>'array', 'with_cas='=>'bool', 'value_cb='=>'callable'], 'Memcached::getDelayedByKey' => ['bool', 'server_key'=>'string', 'keys'=>'array', 'with_cas='=>'bool', 'value_cb='=>'?callable'], 'Memcached::getLastDisconnectedServer' => [''], 'Memcached::getLastErrorCode' => [''], 'Memcached::getLastErrorErrno' => [''], 'Memcached::getLastErrorMessage' => [''], 'Memcached::getMulti' => ['array|false', 'keys'=>'array', 'flags='=>'int'], 'Memcached::getMultiByKey' => ['array|false', 'server_key'=>'string', 'keys'=>'array', 'flags='=>'int'], 'Memcached::getOption' => ['mixed|false', 'option'=>'int'], 'Memcached::getResultCode' => ['int'], 'Memcached::getResultMessage' => ['string'], 'Memcached::getServerByKey' => ['array', 'server_key'=>'string'], 'Memcached::getServerList' => ['array'], 'Memcached::getStats' => ['array', 'type='=>'?string'], 'Memcached::getVersion' => ['array'], 'Memcached::increment' => ['int|false', 'key'=>'string', 'offset='=>'int', 'initial_value='=>'int', 'expiry='=>'int'], 'Memcached::incrementByKey' => ['int|false', 'server_key'=>'string', 'key'=>'string', 'offset='=>'int', 'initial_value='=>'int', 'expiry='=>'int'], 'Memcached::isPersistent' => ['bool'], 'Memcached::isPristine' => ['bool'], 'Memcached::prepend' => ['bool', 'key'=>'string', 'value'=>'string'], 'Memcached::prependByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'string'], 'Memcached::quit' => ['bool'], 'Memcached::replace' => ['bool', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::replaceByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::resetServerList' => ['bool'], 'Memcached::set' => ['bool', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::setBucket' => ['', 'host_map'=>'array', 'forward_map'=>'array', 'replicas'=>''], 'Memcached::setByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::setEncodingKey' => ['', 'key'=>''], 'Memcached::setMulti' => ['bool', 'items'=>'array', 'expiration='=>'int'], 'Memcached::setMultiByKey' => ['bool', 'server_key'=>'string', 'items'=>'array', 'expiration='=>'int'], 'Memcached::setOption' => ['bool', 'option'=>'int', 'value'=>'mixed'], 'Memcached::setOptions' => ['bool', 'options'=>'array'], 'Memcached::setSaslAuthData' => ['void', 'username'=>'string', 'password'=>'string'], 'Memcached::touch' => ['bool', 'key'=>'string', 'expiration'=>'int'], 'Memcached::touchByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'expiration'=>'int'], 'MemcachePool::add' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'MemcachePool::addServer' => ['bool', 'host'=>'string', 'port='=>'int', 'persistent='=>'bool', 'weight='=>'int', 'timeout='=>'int', 'retry_interval='=>'int', 'status='=>'bool', 'failure_callback='=>'?callable', 'timeoutms='=>'int'], 'MemcachePool::append' => [''], 'MemcachePool::cas' => [''], 'MemcachePool::close' => ['bool'], 'MemcachePool::connect' => ['bool', 'host'=>'string', 'port'=>'int', 'timeout='=>'int'], 'MemcachePool::decrement' => ['int|false', 'key'=>'', 'value='=>'int|mixed'], 'MemcachePool::delete' => ['bool', 'key'=>'', 'timeout='=>'int|mixed'], 'MemcachePool::findServer' => [''], 'MemcachePool::flush' => ['bool'], 'MemcachePool::get' => ['array|string|false', 'key'=>'array|string', '&flags='=>'array|int'], 'MemcachePool::getExtendedStats' => ['array|false', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'MemcachePool::getServerStatus' => ['int', 'host'=>'string', 'port='=>'int'], 'MemcachePool::getStats' => ['array|false', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'MemcachePool::getVersion' => ['string|false'], 'MemcachePool::increment' => ['int|false', 'key'=>'', 'value='=>'int|mixed'], 'MemcachePool::prepend' => ['string'], 'MemcachePool::replace' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'MemcachePool::set' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'MemcachePool::setCompressThreshold' => ['bool', 'thresold'=>'int', 'min_saving='=>'float'], 'MemcachePool::setFailureCallback' => [''], 'MemcachePool::setServerParams' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'int', 'retry_interval='=>'int', 'status='=>'bool', 'failure_callback='=>'?callable'], 'memory_get_peak_usage' => ['int', 'real_usage='=>'bool'], 'memory_get_usage' => ['int', 'real_usage='=>'bool'], 'MessageFormatter::__construct' => ['void', 'locale'=>'string', 'pattern'=>'string'], 'MessageFormatter::create' => ['MessageFormatter', 'locale'=>'string', 'pattern'=>'string'], 'MessageFormatter::format' => ['false|string', 'args'=>'array'], 'MessageFormatter::formatMessage' => ['false|string', 'locale'=>'string', 'pattern'=>'string', 'args'=>'array'], 'MessageFormatter::getErrorCode' => ['int'], 'MessageFormatter::getErrorMessage' => ['string'], 'MessageFormatter::getLocale' => ['string'], 'MessageFormatter::getPattern' => ['string'], 'MessageFormatter::parse' => ['array|false', 'value'=>'string'], 'MessageFormatter::parseMessage' => ['array|false', 'locale'=>'string', 'pattern'=>'string', 'source'=>'string'], 'MessageFormatter::setPattern' => ['bool', 'pattern'=>'string'], 'metaphone' => ['string|false', 'text'=>'string', 'phones='=>'int'], 'method_exists' => ['bool', 'object'=>'object|class-string', 'method'=>'string'], 'mhash' => ['string', 'hash'=>'int', 'data'=>'string', 'key='=>'string'], 'mhash_count' => ['int'], 'mhash_get_block_size' => ['int|false', 'hash'=>'int'], 'mhash_get_hash_name' => ['string|false', 'hash'=>'int'], 'mhash_keygen_s2k' => ['string|false', 'hash'=>'int', 'input_password'=>'string', 'salt'=>'string', 'bytes'=>'int'], 'microtime' => ['string', 'get_as_float='=>'false'], 'microtime\'1' => ['float', 'get_as_float='=>'true'], 'mime_content_type' => ['string|false', 'filename_or_stream'=>'string|resource'], 'min' => ['mixed', 'arg1'=>'non-empty-array'], 'min\'1' => ['mixed', 'arg1'=>'', 'arg2'=>'', '...args='=>''], 'ming_keypress' => ['int', 'char'=>'string'], 'ming_setcubicthreshold' => ['void', 'threshold'=>'int'], 'ming_setscale' => ['void', 'scale'=>'float'], 'ming_setswfcompression' => ['void', 'level'=>'int'], 'ming_useconstants' => ['void', 'use'=>'int'], 'ming_useswfversion' => ['void', 'version'=>'int'], 'mkdir' => ['bool', 'pathname'=>'string', 'mode='=>'int', 'recursive='=>'bool', 'context='=>'resource'], 'mktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'money_format' => ['string', 'format'=>'string', 'value'=>'float'], 'Mongo::__construct' => ['void', 'server='=>'string', 'options='=>'array', 'driver_options='=>'array'], 'Mongo::__get' => ['MongoDB', 'dbname'=>'string'], 'Mongo::__toString' => ['string'], 'Mongo::close' => ['bool'], 'Mongo::connect' => ['bool'], 'Mongo::connectUtil' => ['bool'], 'Mongo::dropDB' => ['array', 'db'=>'mixed'], 'Mongo::forceError' => ['bool'], 'Mongo::getConnections' => ['array'], 'Mongo::getHosts' => ['array'], 'Mongo::getPoolSize' => ['int'], 'Mongo::getReadPreference' => ['array'], 'Mongo::getSlave' => ['?string'], 'Mongo::getSlaveOkay' => ['bool'], 'Mongo::getWriteConcern' => ['array'], 'Mongo::killCursor' => ['', 'server_hash'=>'string', 'id'=>'MongoInt64|int'], 'Mongo::lastError' => ['?array'], 'Mongo::listDBs' => ['array'], 'Mongo::pairConnect' => ['bool'], 'Mongo::pairPersistConnect' => ['bool', 'username='=>'string', 'password='=>'string'], 'Mongo::persistConnect' => ['bool', 'username='=>'string', 'password='=>'string'], 'Mongo::poolDebug' => ['array'], 'Mongo::prevError' => ['array'], 'Mongo::resetError' => ['array'], 'Mongo::selectCollection' => ['MongoCollection', 'db'=>'string', 'collection'=>'string'], 'Mongo::selectDB' => ['MongoDB', 'name'=>'string'], 'Mongo::setPoolSize' => ['bool', 'size'=>'int'], 'Mongo::setReadPreference' => ['bool', 'readPreference'=>'string', 'tags='=>'array'], 'Mongo::setSlaveOkay' => ['bool', 'ok='=>'bool'], 'Mongo::switchSlave' => ['string'], 'MongoBinData::__construct' => ['void', 'data'=>'string', 'type='=>'int'], 'MongoBinData::__toString' => ['string'], 'MongoClient::__construct' => ['void', 'server='=>'string', 'options='=>'array', 'driver_options='=>'array'], 'MongoClient::__get' => ['MongoDB', 'dbname'=>'string'], 'MongoClient::__toString' => ['string'], 'MongoClient::close' => ['bool', 'connection='=>'bool|string'], 'MongoClient::connect' => ['bool'], 'MongoClient::dropDB' => ['array', 'db'=>'mixed'], 'MongoClient::getConnections' => ['array'], 'MongoClient::getHosts' => ['array'], 'MongoClient::getReadPreference' => ['array'], 'MongoClient::getWriteConcern' => ['array'], 'MongoClient::killCursor' => ['bool', 'server_hash'=>'string', 'id'=>'int|MongoInt64'], 'MongoClient::listDBs' => ['array'], 'MongoClient::selectCollection' => ['MongoCollection', 'db'=>'string', 'collection'=>'string'], 'MongoClient::selectDB' => ['MongoDB', 'name'=>'string'], 'MongoClient::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags='=>'array'], 'MongoClient::setWriteConcern' => ['bool', 'w'=>'mixed', 'wtimeout='=>'int'], 'MongoClient::switchSlave' => ['string'], 'MongoCode::__construct' => ['void', 'code'=>'string', 'scope='=>'array'], 'MongoCode::__toString' => ['string'], 'MongoCollection::__construct' => ['void', 'db'=>'MongoDB', 'name'=>'string'], 'MongoCollection::__get' => ['MongoCollection', 'name'=>'string'], 'MongoCollection::__toString' => ['string'], 'MongoCollection::aggregate' => ['array', 'op'=>'array', 'op='=>'array', '...args='=>'array'], 'MongoCollection::aggregate\'1' => ['array', 'pipeline'=>'array', 'options='=>'array'], 'MongoCollection::aggregateCursor' => ['MongoCommandCursor', 'command'=>'array', 'options='=>'array'], 'MongoCollection::batchInsert' => ['array|bool', 'a'=>'array', 'options='=>'array'], 'MongoCollection::count' => ['int', 'query='=>'array', 'limit='=>'int', 'skip='=>'int'], 'MongoCollection::createDBRef' => ['array', 'a'=>'array'], 'MongoCollection::createIndex' => ['array', 'keys'=>'array', 'options='=>'array'], 'MongoCollection::deleteIndex' => ['array', 'keys'=>'string|array'], 'MongoCollection::deleteIndexes' => ['array'], 'MongoCollection::distinct' => ['array|false', 'key'=>'string', 'query='=>'array'], 'MongoCollection::drop' => ['array'], 'MongoCollection::ensureIndex' => ['bool', 'keys'=>'array', 'options='=>'array'], 'MongoCollection::find' => ['MongoCursor', 'query='=>'array', 'fields='=>'array'], 'MongoCollection::findAndModify' => ['array', 'query'=>'array', 'update='=>'array', 'fields='=>'array', 'options='=>'array'], 'MongoCollection::findOne' => ['?array', 'query='=>'array', 'fields='=>'array'], 'MongoCollection::getDBRef' => ['array', 'ref'=>'array'], 'MongoCollection::getIndexInfo' => ['array'], 'MongoCollection::getName' => ['string'], 'MongoCollection::getReadPreference' => ['array'], 'MongoCollection::getSlaveOkay' => ['bool'], 'MongoCollection::getWriteConcern' => ['array'], 'MongoCollection::group' => ['array', 'keys'=>'mixed', 'initial'=>'array', 'reduce'=>'MongoCode', 'options='=>'array'], 'MongoCollection::insert' => ['bool|array', 'a'=>'array|object', 'options='=>'array'], 'MongoCollection::parallelCollectionScan' => ['MongoCommandCursor[]', 'num_cursors'=>'int'], 'MongoCollection::remove' => ['bool|array', 'criteria='=>'array', 'options='=>'array'], 'MongoCollection::save' => ['bool|array', 'a'=>'array|object', 'options='=>'array'], 'MongoCollection::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags='=>'array'], 'MongoCollection::setSlaveOkay' => ['bool', 'ok='=>'bool'], 'MongoCollection::setWriteConcern' => ['bool', 'w'=>'mixed', 'wtimeout='=>'int'], 'MongoCollection::toIndexString' => ['string', 'keys'=>'mixed'], 'MongoCollection::update' => ['bool', 'criteria'=>'array', 'newobj'=>'array', 'options='=>'array'], 'MongoCollection::validate' => ['array', 'scan_data='=>'bool'], 'MongoCommandCursor::__construct' => ['void', 'connection'=>'MongoClient', 'ns'=>'string', 'command'=>'array'], 'MongoCommandCursor::batchSize' => ['MongoCommandCursor', 'batchSize'=>'int'], 'MongoCommandCursor::createFromDocument' => ['MongoCommandCursor', 'connection'=>'MongoClient', 'hash'=>'string', 'document'=>'array'], 'MongoCommandCursor::current' => ['array'], 'MongoCommandCursor::dead' => ['bool'], 'MongoCommandCursor::getReadPreference' => ['array'], 'MongoCommandCursor::info' => ['array'], 'MongoCommandCursor::key' => ['int'], 'MongoCommandCursor::next' => ['void'], 'MongoCommandCursor::rewind' => ['array'], 'MongoCommandCursor::setReadPreference' => ['MongoCommandCursor', 'read_preference'=>'string', 'tags='=>'array'], 'MongoCommandCursor::timeout' => ['MongoCommandCursor', 'ms'=>'int'], 'MongoCommandCursor::valid' => ['bool'], 'MongoCursor::__construct' => ['void', 'connection'=>'MongoClient', 'ns'=>'string', 'query='=>'array', 'fields='=>'array'], 'MongoCursor::addOption' => ['MongoCursor', 'key'=>'string', 'value'=>'mixed'], 'MongoCursor::awaitData' => ['MongoCursor', 'wait='=>'bool'], 'MongoCursor::batchSize' => ['MongoCursor', 'num'=>'int'], 'MongoCursor::count' => ['int', 'foundonly='=>'bool'], 'MongoCursor::current' => ['array'], 'MongoCursor::dead' => ['bool'], 'MongoCursor::doQuery' => ['void'], 'MongoCursor::explain' => ['array'], 'MongoCursor::fields' => ['MongoCursor', 'f'=>'array'], 'MongoCursor::getNext' => ['array'], 'MongoCursor::getReadPreference' => ['array'], 'MongoCursor::hasNext' => ['bool'], 'MongoCursor::hint' => ['MongoCursor', 'key_pattern'=>'string|array|object'], 'MongoCursor::immortal' => ['MongoCursor', 'liveforever='=>'bool'], 'MongoCursor::info' => ['array'], 'MongoCursor::key' => ['string'], 'MongoCursor::limit' => ['MongoCursor', 'num'=>'int'], 'MongoCursor::maxTimeMS' => ['MongoCursor', 'ms'=>'int'], 'MongoCursor::next' => ['array'], 'MongoCursor::partial' => ['MongoCursor', 'okay='=>'bool'], 'MongoCursor::reset' => ['void'], 'MongoCursor::rewind' => ['void'], 'MongoCursor::setFlag' => ['MongoCursor', 'flag'=>'int', 'set='=>'bool'], 'MongoCursor::setReadPreference' => ['MongoCursor', 'read_preference'=>'string', 'tags='=>'array'], 'MongoCursor::skip' => ['MongoCursor', 'num'=>'int'], 'MongoCursor::slaveOkay' => ['MongoCursor', 'okay='=>'bool'], 'MongoCursor::snapshot' => ['MongoCursor'], 'MongoCursor::sort' => ['MongoCursor', 'fields'=>'array'], 'MongoCursor::tailable' => ['MongoCursor', 'tail='=>'bool'], 'MongoCursor::timeout' => ['MongoCursor', 'ms'=>'int'], 'MongoCursor::valid' => ['bool'], 'MongoCursorException::__clone' => ['void'], 'MongoCursorException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'MongoCursorException::__toString' => ['string'], 'MongoCursorException::__wakeup' => ['void'], 'MongoCursorException::getCode' => ['int'], 'MongoCursorException::getFile' => ['string'], 'MongoCursorException::getHost' => ['string'], 'MongoCursorException::getLine' => ['int'], 'MongoCursorException::getMessage' => ['string'], 'MongoCursorException::getPrevious' => ['Exception|Throwable'], 'MongoCursorException::getTrace' => ['list>'], 'MongoCursorException::getTraceAsString' => ['string'], 'MongoCursorInterface::__construct' => ['void'], 'MongoCursorInterface::batchSize' => ['MongoCursorInterface', 'batchSize'=>'int'], 'MongoCursorInterface::current' => ['mixed'], 'MongoCursorInterface::dead' => ['bool'], 'MongoCursorInterface::getReadPreference' => ['array'], 'MongoCursorInterface::info' => ['array'], 'MongoCursorInterface::key' => ['int|string'], 'MongoCursorInterface::next' => ['void'], 'MongoCursorInterface::rewind' => ['void'], 'MongoCursorInterface::setReadPreference' => ['MongoCursorInterface', 'read_preference'=>'string', 'tags='=>'array'], 'MongoCursorInterface::timeout' => ['MongoCursorInterface', 'ms'=>'int'], 'MongoCursorInterface::valid' => ['bool'], 'MongoDate::__construct' => ['void', 'second='=>'int', 'usecond='=>'int'], 'MongoDate::__toString' => ['string'], 'MongoDate::toDateTime' => ['DateTime'], 'MongoDB::__construct' => ['void', 'conn'=>'MongoClient', 'name'=>'string'], 'MongoDB::__get' => ['MongoCollection', 'name'=>'string'], 'MongoDB::__toString' => ['string'], 'MongoDB::authenticate' => ['array', 'username'=>'string', 'password'=>'string'], 'MongoDB::command' => ['array', 'command'=>'array'], 'MongoDB::createCollection' => ['MongoCollection', 'name'=>'string', 'capped='=>'bool', 'size='=>'int', 'max='=>'int'], 'MongoDB::createDBRef' => ['array', 'collection'=>'string', 'a'=>'mixed'], 'MongoDB::drop' => ['array'], 'MongoDB::dropCollection' => ['array', 'coll'=>'MongoCollection|string'], 'MongoDB::execute' => ['array', 'code'=>'MongoCode|string', 'args='=>'array'], 'MongoDB::forceError' => ['bool'], 'MongoDB::getCollectionInfo' => ['array', 'options='=>'array'], 'MongoDB::getCollectionNames' => ['array', 'options='=>'array'], 'MongoDB::getDBRef' => ['array', 'ref'=>'array'], 'MongoDB::getGridFS' => ['MongoGridFS', 'prefix='=>'string'], 'MongoDB::getProfilingLevel' => ['int'], 'MongoDB::getReadPreference' => ['array'], 'MongoDB::getSlaveOkay' => ['bool'], 'MongoDB::getWriteConcern' => ['array'], 'MongoDB::lastError' => ['array'], 'MongoDB::listCollections' => ['array'], 'MongoDB::prevError' => ['array'], 'MongoDB::repair' => ['array', 'preserve_cloned_files='=>'bool', 'backup_original_files='=>'bool'], 'MongoDB::resetError' => ['array'], 'MongoDB::selectCollection' => ['MongoCollection', 'name'=>'string'], 'MongoDB::setProfilingLevel' => ['int', 'level'=>'int'], 'MongoDB::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags='=>'array'], 'MongoDB::setSlaveOkay' => ['bool', 'ok='=>'bool'], 'MongoDB::setWriteConcern' => ['bool', 'w'=>'mixed', 'wtimeout='=>'int'], 'MongoDB\BSON\Binary::__construct' => ['void', 'data'=>'string', 'type'=>'int'], 'MongoDB\BSON\Binary::__toString' => ['string'], 'MongoDB\BSON\Binary::getData' => ['string'], 'MongoDB\BSON\Binary::getType' => ['int'], 'MongoDB\BSON\binary::jsonSerialize' => ['mixed'], 'MongoDB\BSON\binary::serialize' => ['string'], 'MongoDB\BSON\binary::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\binaryinterface::__toString' => ['string'], 'MongoDB\BSON\binaryinterface::getData' => ['string'], 'MongoDB\BSON\binaryinterface::getType' => ['int'], 'MongoDB\BSON\dbpointer::__construct' => ['void'], 'MongoDB\BSON\dbpointer::__toString' => ['string'], 'MongoDB\BSON\dbpointer::jsonSerialize' => ['mixed'], 'MongoDB\BSON\dbpointer::serialize' => ['string'], 'MongoDB\BSON\dbpointer::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\Decimal128::__construct' => ['void', 'value='=>'string'], 'MongoDB\BSON\Decimal128::__toString' => ['string'], 'MongoDB\BSON\decimal128::jsonSerialize' => ['mixed'], 'MongoDB\BSON\decimal128::serialize' => ['string'], 'MongoDB\BSON\decimal128::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\decimal128interface::__toString' => ['string'], 'MongoDB\BSON\fromJSON' => ['string', 'json'=>'string'], 'MongoDB\BSON\fromPHP' => ['string', 'value'=>'array|object'], 'MongoDB\BSON\int64::__construct' => ['void'], 'MongoDB\BSON\int64::__toString' => ['string'], 'MongoDB\BSON\int64::jsonSerialize' => ['mixed'], 'MongoDB\BSON\int64::serialize' => ['string'], 'MongoDB\BSON\int64::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\Javascript::__construct' => ['void', 'code'=>'string', 'scope='=>'array|object'], 'MongoDB\BSON\javascript::__toString' => ['string'], 'MongoDB\BSON\javascript::getCode' => ['string'], 'MongoDB\BSON\javascript::getScope' => ['?object'], 'MongoDB\BSON\javascript::jsonSerialize' => ['mixed'], 'MongoDB\BSON\javascript::serialize' => ['string'], 'MongoDB\BSON\javascript::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\javascriptinterface::__toString' => ['string'], 'MongoDB\BSON\javascriptinterface::getCode' => ['string'], 'MongoDB\BSON\javascriptinterface::getScope' => ['?object'], 'MongoDB\BSON\maxkey::__construct' => ['void'], 'MongoDB\BSON\maxkey::jsonSerialize' => ['mixed'], 'MongoDB\BSON\maxkey::serialize' => ['string'], 'MongoDB\BSON\maxkey::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\minkey::__construct' => ['void'], 'MongoDB\BSON\minkey::jsonSerialize' => ['mixed'], 'MongoDB\BSON\minkey::serialize' => ['string'], 'MongoDB\BSON\minkey::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\ObjectId::__construct' => ['void', 'id='=>'string'], 'MongoDB\BSON\ObjectId::__toString' => ['string'], 'MongoDB\BSON\objectid::getTimestamp' => ['int'], 'MongoDB\BSON\objectid::jsonSerialize' => ['mixed'], 'MongoDB\BSON\objectid::serialize' => ['string'], 'MongoDB\BSON\objectid::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\objectidinterface::__toString' => ['string'], 'MongoDB\BSON\objectidinterface::getTimestamp' => ['int'], 'MongoDB\BSON\Regex::__construct' => ['void', 'pattern'=>'string', 'flags='=>'string'], 'MongoDB\BSON\Regex::__toString' => ['string'], 'MongoDB\BSON\Regex::getFlags' => ['string'], 'MongoDB\BSON\Regex::getPattern' => ['string'], 'MongoDB\BSON\regex::jsonSerialize' => ['mixed'], 'MongoDB\BSON\regex::serialize' => ['string'], 'MongoDB\BSON\regex::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\regexinterface::__toString' => ['string'], 'MongoDB\BSON\regexinterface::getFlags' => ['string'], 'MongoDB\BSON\regexinterface::getPattern' => ['string'], 'MongoDB\BSON\Serializable::bsonSerialize' => ['array|object'], 'MongoDB\BSON\symbol::__construct' => ['void'], 'MongoDB\BSON\symbol::__toString' => ['string'], 'MongoDB\BSON\symbol::jsonSerialize' => ['mixed'], 'MongoDB\BSON\symbol::serialize' => ['string'], 'MongoDB\BSON\symbol::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\Timestamp::__construct' => ['void', 'increment'=>'int', 'timestamp'=>'int'], 'MongoDB\BSON\Timestamp::__toString' => ['string'], 'MongoDB\BSON\timestamp::getIncrement' => ['int'], 'MongoDB\BSON\timestamp::getTimestamp' => ['int'], 'MongoDB\BSON\timestamp::jsonSerialize' => ['mixed'], 'MongoDB\BSON\timestamp::serialize' => ['string'], 'MongoDB\BSON\timestamp::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\timestampinterface::__toString' => ['string'], 'MongoDB\BSON\timestampinterface::getIncrement' => ['int'], 'MongoDB\BSON\timestampinterface::getTimestamp' => ['int'], 'MongoDB\BSON\toJSON' => ['string', 'bson'=>'string'], 'MongoDB\BSON\toPHP' => ['object', 'bson'=>'string', 'typeMap'=>'array'], 'MongoDB\BSON\undefined::__construct' => ['void'], 'MongoDB\BSON\undefined::__toString' => ['string'], 'MongoDB\BSON\undefined::jsonSerialize' => ['mixed'], 'MongoDB\BSON\undefined::serialize' => ['string'], 'MongoDB\BSON\undefined::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\Unserializable::bsonUnserialize' => ['void', 'data'=>'array'], 'MongoDB\BSON\UTCDateTime::__construct' => ['void', 'milliseconds='=>'int|DateTimeInterface'], 'MongoDB\BSON\UTCDateTime::__toString' => ['string'], 'MongoDB\BSON\utcdatetime::jsonSerialize' => ['mixed'], 'MongoDB\BSON\utcdatetime::serialize' => ['string'], 'MongoDB\BSON\UTCDateTime::toDateTime' => ['DateTime'], 'MongoDB\BSON\utcdatetime::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\BSON\utcdatetimeinterface::__toString' => ['string'], 'MongoDB\BSON\utcdatetimeinterface::toDateTime' => ['DateTime'], 'MongoDB\Driver\BulkWrite::__construct' => ['void', 'ordered='=>'bool'], 'MongoDB\Driver\BulkWrite::count' => ['int'], 'MongoDB\Driver\BulkWrite::delete' => ['void', 'filter'=>'array|object', 'deleteOptions='=>'array'], 'MongoDB\Driver\BulkWrite::insert' => ['void|MongoDB\BSON\ObjectId', 'document'=>'array|object'], 'MongoDB\Driver\BulkWrite::update' => ['void', 'filter'=>'array|object', 'newObj'=>'array|object', 'updateOptions='=>'array'], 'MongoDB\Driver\Command::__construct' => ['void', 'document'=>'array|object'], 'MongoDB\Driver\Cursor::__construct' => ['void', 'server'=>'Server', 'responseDocument'=>'string'], 'MongoDB\Driver\Cursor::getId' => ['MongoDB\Driver\CursorId'], 'MongoDB\Driver\Cursor::getServer' => ['MongoDB\Driver\Server'], 'MongoDB\Driver\Cursor::isDead' => ['bool'], 'MongoDB\Driver\Cursor::setTypeMap' => ['void', 'typemap'=>'array'], 'MongoDB\Driver\Cursor::toArray' => ['array'], 'MongoDB\Driver\CursorId::__construct' => ['void', 'id'=>'string'], 'MongoDB\Driver\CursorId::__toString' => ['string'], 'MongoDB\Driver\CursorId::serialize' => ['string'], 'MongoDB\Driver\CursorId::unserialize' => ['void', 'serialized'=>'string'], 'mongodb\driver\exception\commandexception::getResultDocument' => ['object'], 'MongoDB\Driver\Exception\RuntimeException::__clone' => ['void'], 'MongoDB\Driver\Exception\RuntimeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?RuntimeException|?Throwable'], 'MongoDB\Driver\Exception\RuntimeException::__toString' => ['string'], 'MongoDB\Driver\Exception\RuntimeException::__wakeup' => ['void'], 'MongoDB\Driver\Exception\RuntimeException::getCode' => ['int'], 'MongoDB\Driver\Exception\RuntimeException::getFile' => ['string'], 'MongoDB\Driver\Exception\RuntimeException::getLine' => ['int'], 'MongoDB\Driver\Exception\RuntimeException::getMessage' => ['string'], 'MongoDB\Driver\Exception\RuntimeException::getPrevious' => ['RuntimeException|Throwable'], 'MongoDB\Driver\Exception\RuntimeException::getTrace' => ['list>'], 'MongoDB\Driver\Exception\RuntimeException::getTraceAsString' => ['string'], 'mongodb\driver\exception\runtimeexception::hasErrorLabel' => ['bool', 'errorLabel'=>'string'], 'MongoDB\Driver\Exception\WriteException::__clone' => ['void'], 'MongoDB\Driver\Exception\WriteException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?RuntimeException|?Throwable'], 'MongoDB\Driver\Exception\WriteException::__toString' => ['string'], 'MongoDB\Driver\Exception\WriteException::__wakeup' => ['void'], 'MongoDB\Driver\Exception\WriteException::getCode' => ['int'], 'MongoDB\Driver\Exception\WriteException::getFile' => ['string'], 'MongoDB\Driver\Exception\WriteException::getLine' => ['int'], 'MongoDB\Driver\Exception\WriteException::getMessage' => ['string'], 'MongoDB\Driver\Exception\WriteException::getPrevious' => ['RuntimeException|Throwable'], 'MongoDB\Driver\Exception\WriteException::getTrace' => ['list>'], 'MongoDB\Driver\Exception\WriteException::getTraceAsString' => ['string'], 'MongoDB\Driver\Exception\WriteException::getWriteResult' => ['MongoDB\Driver\WriteResult'], 'MongoDB\Driver\Manager::__construct' => ['void', 'uri'=>'string', 'options='=>'array', 'driverOptions='=>'array'], 'MongoDB\Driver\Manager::executeBulkWrite' => ['MongoDB\Driver\WriteResult', 'namespace'=>'string', 'bulk'=>'MongoDB\Driver\BulkWrite', 'writeConcern='=>'MongoDB\Driver\WriteConcern'], 'MongoDB\Driver\Manager::executeCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'readPreference='=>'MongoDB\Driver\ReadPreference'], 'MongoDB\Driver\Manager::executeDelete' => ['MongoDB\Driver\WriteResult', 'namespace'=>'string', 'filter'=>'array|object', 'deleteOptions='=>'array', 'writeConcern='=>'MongoDB\Driver\WriteConcern'], 'MongoDB\Driver\Manager::executeInsert' => ['MongoDB\Driver\WriteResult', 'namespace'=>'string', 'document'=>'array|object', 'writeConcern='=>'MongoDB\Driver\WriteConcern'], 'MongoDB\Driver\Manager::executeQuery' => ['MongoDB\Driver\Cursor', 'namespace'=>'string', 'query'=>'MongoDB\Driver\Query', 'readPreference='=>'MongoDB\Driver\ReadPreference'], 'mongodb\driver\manager::executeReadCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'array'], 'mongodb\driver\manager::executeReadWriteCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'array'], 'MongoDB\Driver\Manager::executeUpdate' => ['MongoDB\Driver\WriteResult', 'namespace'=>'string', 'filter'=>'array|object', 'newObj'=>'array|object', 'updateOptions='=>'array', 'writeConcern='=>'MongoDB\Driver\WriteConcern'], 'mongodb\driver\manager::executeWriteCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'array'], 'MongoDB\Driver\Manager::getReadConcern' => ['MongoDB\Driver\ReadConcern'], 'MongoDB\Driver\Manager::getReadPreference' => ['MongoDB\Driver\ReadPreference'], 'MongoDB\Driver\Manager::getServers' => ['MongoDB\Driver\Server[]'], 'MongoDB\Driver\Manager::getWriteConcern' => ['MongoDB\Driver\WriteConcern'], 'MongoDB\Driver\Manager::selectServer' => ['MongoDB\Driver\Server', 'readPreference'=>'MongoDB\Driver\ReadPreference'], 'mongodb\driver\manager::startSession' => ['MongoDB\Driver\Session', 'options='=>'array'], 'mongodb\driver\monitoring\commandfailedevent::getCommandName' => ['string'], 'mongodb\driver\monitoring\commandfailedevent::getDurationMicros' => ['int'], 'mongodb\driver\monitoring\commandfailedevent::getError' => ['Exception'], 'mongodb\driver\monitoring\commandfailedevent::getOperationId' => ['string'], 'mongodb\driver\monitoring\commandfailedevent::getReply' => ['object'], 'mongodb\driver\monitoring\commandfailedevent::getRequestId' => ['string'], 'mongodb\driver\monitoring\commandfailedevent::getServer' => ['MongoDB\Driver\Server'], 'mongodb\driver\monitoring\commandstartedevent::getCommand' => ['object'], 'mongodb\driver\monitoring\commandstartedevent::getCommandName' => ['string'], 'mongodb\driver\monitoring\commandstartedevent::getDatabaseName' => ['string'], 'mongodb\driver\monitoring\commandstartedevent::getOperationId' => ['string'], 'mongodb\driver\monitoring\commandstartedevent::getRequestId' => ['string'], 'mongodb\driver\monitoring\commandstartedevent::getServer' => ['MongoDB\Driver\Server'], 'mongodb\driver\monitoring\commandsubscriber::commandFailed' => ['void', 'event'=>'MongoDB\Driver\Monitoring\CommandFailedEvent'], 'mongodb\driver\monitoring\commandsubscriber::commandStarted' => ['void', 'event'=>'MongoDB\Driver\Monitoring\CommandStartedEvent'], 'mongodb\driver\monitoring\commandsubscriber::commandSucceeded' => ['void', 'event'=>'MongoDB\Driver\Monitoring\CommandSucceededEvent'], 'mongodb\driver\monitoring\commandsucceededevent::getCommandName' => ['string'], 'mongodb\driver\monitoring\commandsucceededevent::getDurationMicros' => ['int'], 'mongodb\driver\monitoring\commandsucceededevent::getOperationId' => ['string'], 'mongodb\driver\monitoring\commandsucceededevent::getReply' => ['object'], 'mongodb\driver\monitoring\commandsucceededevent::getRequestId' => ['string'], 'mongodb\driver\monitoring\commandsucceededevent::getServer' => ['MongoDB\Driver\Server'], 'MongoDB\Driver\Query::__construct' => ['void', 'filter'=>'array|object', 'queryOptions='=>'array'], 'MongoDB\Driver\ReadConcern::__construct' => ['void', 'level='=>'string'], 'MongoDB\Driver\ReadConcern::bsonSerialize' => ['object'], 'MongoDB\Driver\ReadConcern::getLevel' => ['?string'], 'MongoDB\Driver\ReadConcern::isDefault' => ['bool'], 'MongoDB\Driver\ReadConcern::serialize' => ['string'], 'MongoDB\Driver\ReadConcern::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\Driver\ReadPreference::__construct' => ['void', 'mode'=>'string|int', 'tagSets='=>'array', 'options='=>'array'], 'MongoDB\Driver\ReadPreference::bsonSerialize' => ['object'], 'MongoDB\Driver\ReadPreference::getHedge' => ['object|null'], 'MongoDB\Driver\ReadPreference::getMaxStalenessSeconds' => ['int'], 'MongoDB\Driver\ReadPreference::getMode' => ['int'], 'MongoDB\Driver\ReadPreference::getModeString' => ['string'], 'MongoDB\Driver\ReadPreference::getTagSets' => ['array'], 'MongoDB\Driver\ReadPreference::serialize' => ['string'], 'MongoDB\Driver\ReadPreference::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\Driver\Server::__construct' => ['void', 'host'=>'string', 'port'=>'string', 'options='=>'array', 'driverOptions='=>'array'], 'MongoDB\Driver\Server::executeBulkWrite' => ['MongoDB\Driver\WriteResult', 'namespace'=>'string', 'zwrite'=>'BulkWrite'], 'MongoDB\Driver\Server::executeCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command'], 'MongoDB\Driver\Server::executeQuery' => ['MongoDB\Driver\Cursor', 'namespace'=>'string', 'zquery'=>'Query'], 'mongodb\driver\server::executeReadCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'array'], 'mongodb\driver\server::executeReadWriteCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'array'], 'mongodb\driver\server::executeWriteCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'array'], 'MongoDB\Driver\Server::getHost' => ['string'], 'MongoDB\Driver\Server::getInfo' => ['array'], 'MongoDB\Driver\Server::getLatency' => ['int'], 'MongoDB\Driver\Server::getPort' => ['int'], 'MongoDB\Driver\Server::getState' => [''], 'MongoDB\Driver\Server::getTags' => ['array'], 'MongoDB\Driver\Server::getType' => ['int'], 'MongoDB\Driver\Server::isArbiter' => ['bool'], 'MongoDB\Driver\Server::isDelayed' => [''], 'MongoDB\Driver\Server::isHidden' => ['bool'], 'MongoDB\Driver\Server::isPassive' => ['bool'], 'MongoDB\Driver\Server::isPrimary' => ['bool'], 'MongoDB\Driver\Server::isSecondary' => ['bool'], 'mongodb\driver\session::__construct' => ['void'], 'mongodb\driver\session::abortTransaction' => ['void'], 'mongodb\driver\session::advanceClusterTime' => ['void', 'clusterTime'=>'array|object'], 'mongodb\driver\session::advanceOperationTime' => ['void', 'operationTime'=>'MongoDB\BSON\TimestampInterface'], 'mongodb\driver\session::commitTransaction' => ['void'], 'mongodb\driver\session::endSession' => ['void'], 'mongodb\driver\session::getClusterTime' => ['?object'], 'mongodb\driver\session::getLogicalSessionId' => ['object'], 'mongodb\driver\session::getOperationTime' => ['MongoDB\BSON\Timestamp|null'], 'mongodb\driver\session::getTransactionOptions' => ['array|null'], 'mongodb\driver\session::getTransactionState' => ['string'], 'mongodb\driver\session::startTransaction' => ['void', 'options'=>'array|object'], 'MongoDB\Driver\WriteConcern::__construct' => ['void', 'wstring'=>'string', 'wtimeout='=>'int', 'journal='=>'bool', 'fsync='=>'bool'], 'MongoDB\Driver\WriteConcern::bsonSerialize' => ['object'], 'MongoDB\Driver\WriteConcern::getJournal' => ['?bool'], 'MongoDB\Driver\WriteConcern::getJurnal' => ['?bool'], 'MongoDB\Driver\WriteConcern::getW' => ['int|null|string'], 'MongoDB\Driver\WriteConcern::getWtimeout' => ['int'], 'MongoDB\Driver\WriteConcern::isDefault' => ['bool'], 'MongoDB\Driver\WriteConcern::serialize' => ['string'], 'MongoDB\Driver\WriteConcern::unserialize' => ['void', 'serialized'=>'string'], 'MongoDB\Driver\WriteConcernError::getCode' => ['int'], 'MongoDB\Driver\WriteConcernError::getInfo' => ['mixed'], 'MongoDB\Driver\WriteConcernError::getMessage' => ['string'], 'MongoDB\Driver\WriteError::getCode' => ['int'], 'MongoDB\Driver\WriteError::getIndex' => ['int'], 'MongoDB\Driver\WriteError::getInfo' => ['mixed'], 'MongoDB\Driver\WriteError::getMessage' => ['string'], 'MongoDB\Driver\WriteException::getWriteResult' => [''], 'MongoDB\Driver\WriteResult::getDeletedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getInfo' => [''], 'MongoDB\Driver\WriteResult::getInsertedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getMatchedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getModifiedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getServer' => ['MongoDB\Driver\Server'], 'MongoDB\Driver\WriteResult::getUpsertedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getUpsertedIds' => ['array'], 'MongoDB\Driver\WriteResult::getWriteConcernError' => ['MongoDB\Driver\WriteConcernError|null'], 'MongoDB\Driver\WriteResult::getWriteErrors' => ['MongoDB\Driver\WriteError[]'], 'MongoDB\Driver\WriteResult::isAcknowledged' => ['bool'], 'MongoDBRef::create' => ['array', 'collection'=>'string', 'id'=>'mixed', 'database='=>'string'], 'MongoDBRef::get' => ['?array', 'db'=>'MongoDB', 'ref'=>'array'], 'MongoDBRef::isRef' => ['bool', 'ref'=>'mixed'], 'MongoDeleteBatch::__construct' => ['void', 'collection'=>'MongoCollection', 'write_options='=>'array'], 'MongoException::__clone' => ['void'], 'MongoException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'MongoException::__toString' => ['string'], 'MongoException::__wakeup' => ['void'], 'MongoException::getCode' => ['int'], 'MongoException::getFile' => ['string'], 'MongoException::getLine' => ['int'], 'MongoException::getMessage' => ['string'], 'MongoException::getPrevious' => ['Exception|Throwable'], 'MongoException::getTrace' => ['list>'], 'MongoException::getTraceAsString' => ['string'], 'MongoGridFS::__construct' => ['void', 'db'=>'MongoDB', 'prefix='=>'string', 'chunks='=>'mixed'], 'MongoGridFS::__get' => ['MongoCollection', 'name'=>'string'], 'MongoGridFS::__toString' => ['string'], 'MongoGridFS::aggregate' => ['array', 'pipeline'=>'array', 'op'=>'array', 'pipelineOperators'=>'array'], 'MongoGridFS::aggregateCursor' => ['MongoCommandCursor', 'pipeline'=>'array', 'options'=>'array'], 'MongoGridFS::batchInsert' => ['mixed', 'a'=>'array', 'options='=>'array'], 'MongoGridFS::count' => ['int', 'query='=>'stdClass|array'], 'MongoGridFS::createDBRef' => ['array', 'a'=>'array'], 'MongoGridFS::createIndex' => ['array', 'keys'=>'array', 'options='=>'array'], 'MongoGridFS::delete' => ['bool', 'id'=>'mixed'], 'MongoGridFS::deleteIndex' => ['array', 'keys'=>'array|string'], 'MongoGridFS::deleteIndexes' => ['array'], 'MongoGridFS::distinct' => ['array|bool', 'key'=>'string', 'query='=>'?array'], 'MongoGridFS::drop' => ['array'], 'MongoGridFS::ensureIndex' => ['bool', 'keys'=>'array', 'options='=>'array'], 'MongoGridFS::find' => ['MongoGridFSCursor', 'query='=>'array', 'fields='=>'array'], 'MongoGridFS::findAndModify' => ['array', 'query'=>'array', 'update='=>'?array', 'fields='=>'?array', 'options='=>'?array'], 'MongoGridFS::findOne' => ['?MongoGridFSFile', 'query='=>'mixed', 'fields='=>'mixed'], 'MongoGridFS::get' => ['?MongoGridFSFile', 'id'=>'mixed'], 'MongoGridFS::getDBRef' => ['array', 'ref'=>'array'], 'MongoGridFS::getIndexInfo' => ['array'], 'MongoGridFS::getName' => ['string'], 'MongoGridFS::getReadPreference' => ['array'], 'MongoGridFS::getSlaveOkay' => ['bool'], 'MongoGridFS::group' => ['array', 'keys'=>'mixed', 'initial'=>'array', 'reduce'=>'MongoCode', 'condition='=>'array'], 'MongoGridFS::insert' => ['array|bool', 'a'=>'array|object', 'options='=>'array'], 'MongoGridFS::put' => ['mixed', 'filename'=>'string', 'extra='=>'array'], 'MongoGridFS::remove' => ['bool', 'criteria='=>'array', 'options='=>'array'], 'MongoGridFS::save' => ['array|bool', 'a'=>'array|object', 'options='=>'array'], 'MongoGridFS::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags'=>'array'], 'MongoGridFS::setSlaveOkay' => ['bool', 'ok='=>'bool'], 'MongoGridFS::storeBytes' => ['mixed', 'bytes'=>'string', 'extra='=>'array', 'options='=>'array'], 'MongoGridFS::storeFile' => ['mixed', 'filename'=>'string', 'extra='=>'array', 'options='=>'array'], 'MongoGridFS::storeUpload' => ['mixed', 'name'=>'string', 'filename='=>'string'], 'MongoGridFS::toIndexString' => ['string', 'keys'=>'mixed'], 'MongoGridFS::update' => ['bool', 'criteria'=>'array', 'newobj'=>'array', 'options='=>'array'], 'MongoGridFS::validate' => ['array', 'scan_data='=>'bool'], 'MongoGridFSCursor::__construct' => ['void', 'gridfs'=>'MongoGridFS', 'connection'=>'resource', 'ns'=>'string', 'query'=>'array', 'fields'=>'array'], 'MongoGridFSCursor::addOption' => ['MongoCursor', 'key'=>'string', 'value'=>'mixed'], 'MongoGridFSCursor::awaitData' => ['MongoCursor', 'wait='=>'bool'], 'MongoGridFSCursor::batchSize' => ['MongoCursor', 'batchSize'=>'int'], 'MongoGridFSCursor::count' => ['int', 'all='=>'bool'], 'MongoGridFSCursor::current' => ['MongoGridFSFile'], 'MongoGridFSCursor::dead' => ['bool'], 'MongoGridFSCursor::doQuery' => ['void'], 'MongoGridFSCursor::explain' => ['array'], 'MongoGridFSCursor::fields' => ['MongoCursor', 'f'=>'array'], 'MongoGridFSCursor::getNext' => ['MongoGridFSFile'], 'MongoGridFSCursor::getReadPreference' => ['array'], 'MongoGridFSCursor::hasNext' => ['bool'], 'MongoGridFSCursor::hint' => ['MongoCursor', 'key_pattern'=>'mixed'], 'MongoGridFSCursor::immortal' => ['MongoCursor', 'liveForever='=>'bool'], 'MongoGridFSCursor::info' => ['array'], 'MongoGridFSCursor::key' => ['string'], 'MongoGridFSCursor::limit' => ['MongoCursor', 'num'=>'int'], 'MongoGridFSCursor::maxTimeMS' => ['MongoCursor', 'ms'=>'int'], 'MongoGridFSCursor::next' => ['void'], 'MongoGridFSCursor::partial' => ['MongoCursor', 'okay='=>'bool'], 'MongoGridFSCursor::reset' => ['void'], 'MongoGridFSCursor::rewind' => ['void'], 'MongoGridFSCursor::setFlag' => ['MongoCursor', 'flag'=>'int', 'set='=>'bool'], 'MongoGridFSCursor::setReadPreference' => ['MongoCursor', 'read_preference'=>'string', 'tags'=>'array'], 'MongoGridFSCursor::skip' => ['MongoCursor', 'num'=>'int'], 'MongoGridFSCursor::slaveOkay' => ['MongoCursor', 'okay='=>'bool'], 'MongoGridFSCursor::snapshot' => ['MongoCursor'], 'MongoGridFSCursor::sort' => ['MongoCursor', 'fields'=>'array'], 'MongoGridFSCursor::tailable' => ['MongoCursor', 'tail='=>'bool'], 'MongoGridFSCursor::timeout' => ['MongoCursor', 'ms'=>'int'], 'MongoGridFSCursor::valid' => ['bool'], 'MongoGridfsFile::__construct' => ['void', 'gridfs'=>'MongoGridFS', 'file'=>'array'], 'MongoGridFSFile::getBytes' => ['string'], 'MongoGridFSFile::getFilename' => ['string'], 'MongoGridFSFile::getResource' => ['resource'], 'MongoGridFSFile::getSize' => ['int'], 'MongoGridFSFile::write' => ['int', 'filename='=>'string'], 'MongoId::__construct' => ['void', 'id='=>'string|MongoId'], 'MongoId::__set_state' => ['MongoId', 'props'=>'array'], 'MongoId::__toString' => ['string'], 'MongoId::getHostname' => ['string'], 'MongoId::getInc' => ['int'], 'MongoId::getPID' => ['int'], 'MongoId::getTimestamp' => ['int'], 'MongoId::isValid' => ['bool', 'value'=>'mixed'], 'MongoInsertBatch::__construct' => ['void', 'collection'=>'MongoCollection', 'write_options='=>'array'], 'MongoInt32::__construct' => ['void', 'value'=>'string'], 'MongoInt32::__toString' => ['string'], 'MongoInt64::__construct' => ['void', 'value'=>'string'], 'MongoInt64::__toString' => ['string'], 'MongoLog::getCallback' => ['callable'], 'MongoLog::getLevel' => ['int'], 'MongoLog::getModule' => ['int'], 'MongoLog::setCallback' => ['void', 'log_function'=>'callable'], 'MongoLog::setLevel' => ['void', 'level'=>'int'], 'MongoLog::setModule' => ['void', 'module'=>'int'], 'MongoPool::getSize' => ['int'], 'MongoPool::info' => ['array'], 'MongoPool::setSize' => ['bool', 'size'=>'int'], 'MongoRegex::__construct' => ['void', 'regex'=>'string'], 'MongoRegex::__toString' => ['string'], 'MongoResultException::__clone' => ['void'], 'MongoResultException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'MongoResultException::__toString' => ['string'], 'MongoResultException::__wakeup' => ['void'], 'MongoResultException::getCode' => ['int'], 'MongoResultException::getDocument' => ['array'], 'MongoResultException::getFile' => ['string'], 'MongoResultException::getLine' => ['int'], 'MongoResultException::getMessage' => ['string'], 'MongoResultException::getPrevious' => ['Exception|Throwable'], 'MongoResultException::getTrace' => ['list>'], 'MongoResultException::getTraceAsString' => ['string'], 'MongoTimestamp::__construct' => ['void', 'second='=>'int', 'inc='=>'int'], 'MongoTimestamp::__toString' => ['string'], 'MongoUpdateBatch::__construct' => ['void', 'collection'=>'MongoCollection', 'write_options='=>'array'], 'MongoUpdateBatch::add' => ['bool', 'item'=>'array'], 'MongoUpdateBatch::execute' => ['array', 'write_options'=>'array'], 'MongoWriteBatch::__construct' => ['void', 'collection'=>'MongoCollection', 'batch_type'=>'string', 'write_options'=>'array'], 'MongoWriteBatch::add' => ['bool', 'item'=>'array'], 'MongoWriteBatch::execute' => ['array', 'write_options'=>'array'], 'MongoWriteConcernException::__clone' => ['void'], 'MongoWriteConcernException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'MongoWriteConcernException::__toString' => ['string'], 'MongoWriteConcernException::__wakeup' => ['void'], 'MongoWriteConcernException::getCode' => ['int'], 'MongoWriteConcernException::getDocument' => ['array'], 'MongoWriteConcernException::getFile' => ['string'], 'MongoWriteConcernException::getLine' => ['int'], 'MongoWriteConcernException::getMessage' => ['string'], 'MongoWriteConcernException::getPrevious' => ['Exception|Throwable'], 'MongoWriteConcernException::getTrace' => ['list>'], 'MongoWriteConcernException::getTraceAsString' => ['string'], 'monitor_custom_event' => ['void', 'class'=>'string', 'text'=>'string', 'severe='=>'int', 'user_data='=>'mixed'], 'monitor_httperror_event' => ['void', 'error_code'=>'int', 'url'=>'string', 'severe='=>'int'], 'monitor_license_info' => ['array'], 'monitor_pass_error' => ['void', 'errno'=>'int', 'errstr'=>'string', 'errfile'=>'string', 'errline'=>'int'], 'monitor_set_aggregation_hint' => ['void', 'hint'=>'string'], 'move_uploaded_file' => ['bool', 'path'=>'string', 'new_path'=>'string'], 'mqseries_back' => ['void', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_begin' => ['void', 'hconn'=>'resource', 'beginoptions'=>'array', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_close' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'options'=>'int', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_cmit' => ['void', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_conn' => ['void', 'qmanagername'=>'string', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_connx' => ['void', 'qmanagername'=>'string', 'connoptions'=>'array', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_disc' => ['void', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_get' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'md'=>'array', 'gmo'=>'array', 'bufferlength'=>'int', 'msg'=>'string', 'data_length'=>'int', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_inq' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'selectorcount'=>'int', 'selectors'=>'array', 'intattrcount'=>'int', 'intattr'=>'resource', 'charattrlength'=>'int', 'charattr'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_open' => ['void', 'hconn'=>'resource', 'objdesc'=>'array', 'option'=>'int', 'hobj'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_put' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'md'=>'array', 'pmo'=>'array', 'message'=>'string', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_put1' => ['void', 'hconn'=>'resource', 'objdesc'=>'resource', 'msgdesc'=>'resource', 'pmo'=>'resource', 'buffer'=>'string', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_set' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'selectorcount'=>'int', 'selectors'=>'array', 'intattrcount'=>'int', 'intattrs'=>'array', 'charattrlength'=>'int', 'charattrs'=>'array', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_strerror' => ['string', 'reason'=>'int'], 'ms_GetErrorObj' => ['errorObj'], 'ms_GetVersion' => ['string'], 'ms_GetVersionInt' => ['int'], 'ms_iogetStdoutBufferBytes' => ['int'], 'ms_iogetstdoutbufferstring' => ['void'], 'ms_ioinstallstdinfrombuffer' => ['void'], 'ms_ioinstallstdouttobuffer' => ['void'], 'ms_ioresethandlers' => ['void'], 'ms_iostripstdoutbuffercontentheaders' => ['void'], 'ms_iostripstdoutbuffercontenttype' => ['string'], 'ms_ResetErrorList' => ['void'], 'ms_TokenizeMap' => ['array', 'map_file_name'=>'string'], 'msession_connect' => ['bool', 'host'=>'string', 'port'=>'string'], 'msession_count' => ['int'], 'msession_create' => ['bool', 'session'=>'string', 'classname='=>'string', 'data='=>'string'], 'msession_destroy' => ['bool', 'name'=>'string'], 'msession_disconnect' => ['void'], 'msession_find' => ['array', 'name'=>'string', 'value'=>'string'], 'msession_get' => ['string', 'session'=>'string', 'name'=>'string', 'value'=>'string'], 'msession_get_array' => ['array', 'session'=>'string'], 'msession_get_data' => ['string', 'session'=>'string'], 'msession_inc' => ['string', 'session'=>'string', 'name'=>'string'], 'msession_list' => ['array'], 'msession_listvar' => ['array', 'name'=>'string'], 'msession_lock' => ['int', 'name'=>'string'], 'msession_plugin' => ['string', 'session'=>'string', 'value'=>'string', 'param='=>'string'], 'msession_randstr' => ['string', 'param'=>'int'], 'msession_set' => ['bool', 'session'=>'string', 'name'=>'string', 'value'=>'string'], 'msession_set_array' => ['void', 'session'=>'string', 'tuples'=>'array'], 'msession_set_data' => ['bool', 'session'=>'string', 'value'=>'string'], 'msession_timeout' => ['int', 'session'=>'string', 'param='=>'int'], 'msession_uniq' => ['string', 'param'=>'int', 'classname='=>'string', 'data='=>'string'], 'msession_unlock' => ['int', 'session'=>'string', 'key'=>'int'], 'msg_get_queue' => ['resource', 'key'=>'int', 'perms='=>'int'], 'msg_queue_exists' => ['bool', 'key'=>'int'], 'msg_receive' => ['bool', 'queue'=>'resource', 'desiredmsgtype'=>'int', '&w_msgtype'=>'int', 'maxsize'=>'int', '&w_message'=>'mixed', 'unserialize='=>'bool', 'flags='=>'int', '&w_errorcode='=>'int'], 'msg_remove_queue' => ['bool', 'queue'=>'resource'], 'msg_send' => ['bool', 'queue'=>'resource', 'msgtype'=>'int', 'message'=>'mixed', 'serialize='=>'bool', 'blocking='=>'bool', '&w_errorcode='=>'int'], 'msg_set_queue' => ['bool', 'queue'=>'resource', 'data'=>'array'], 'msg_stat_queue' => ['array', 'queue'=>'resource'], 'msgfmt_create' => ['MessageFormatter', 'locale'=>'string', 'pattern'=>'string'], 'msgfmt_format' => ['string|false', 'fmt'=>'MessageFormatter', 'args'=>'array'], 'msgfmt_format_message' => ['string|false', 'locale'=>'string', 'pattern'=>'string', 'args'=>'array'], 'msgfmt_get_error_code' => ['int', 'fmt'=>'MessageFormatter'], 'msgfmt_get_error_message' => ['string', 'fmt'=>'MessageFormatter'], 'msgfmt_get_locale' => ['string', 'formatter'=>'MessageFormatter'], 'msgfmt_get_pattern' => ['string', 'fmt'=>'MessageFormatter'], 'msgfmt_parse' => ['array|false', 'fmt'=>'MessageFormatter', 'value'=>'string'], 'msgfmt_parse_message' => ['array|false', 'locale'=>'string', 'pattern'=>'string', 'source'=>'string'], 'msgfmt_set_pattern' => ['bool', 'fmt'=>'MessageFormatter', 'pattern'=>'string'], 'msql_affected_rows' => ['int', 'result'=>'resource'], 'msql_close' => ['bool', 'link_identifier='=>'?resource'], 'msql_connect' => ['resource', 'hostname='=>'string'], 'msql_create_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'msql_data_seek' => ['bool', 'result'=>'resource', 'row_number'=>'int'], 'msql_db_query' => ['resource', 'database'=>'string', 'query'=>'string', 'link_identifier='=>'?resource'], 'msql_drop_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'msql_error' => ['string'], 'msql_fetch_array' => ['array', 'result'=>'resource', 'result_type='=>'int'], 'msql_fetch_field' => ['object', 'result'=>'resource', 'field_offset='=>'int'], 'msql_fetch_object' => ['object', 'result'=>'resource'], 'msql_fetch_row' => ['array', 'result'=>'resource'], 'msql_field_flags' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_len' => ['int', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_name' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_seek' => ['bool', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_table' => ['int', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_type' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'msql_free_result' => ['bool', 'result'=>'resource'], 'msql_list_dbs' => ['resource', 'link_identifier='=>'?resource'], 'msql_list_fields' => ['resource', 'database'=>'string', 'tablename'=>'string', 'link_identifier='=>'?resource'], 'msql_list_tables' => ['resource', 'database'=>'string', 'link_identifier='=>'?resource'], 'msql_num_fields' => ['int', 'result'=>'resource'], 'msql_num_rows' => ['int', 'query_identifier'=>'resource'], 'msql_pconnect' => ['resource', 'hostname='=>'string'], 'msql_query' => ['resource', 'query'=>'string', 'link_identifier='=>'?resource'], 'msql_result' => ['string', 'result'=>'resource', 'row'=>'int', 'field='=>'mixed'], 'msql_select_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'mt_getrandmax' => ['int'], 'mt_rand' => ['int', 'min'=>'int', 'max'=>'int'], 'mt_rand\'1' => ['int'], 'mt_srand' => ['void', 'seed='=>'int', 'mode='=>'int'], 'MultipleIterator::__construct' => ['void', 'flags='=>'int'], 'MultipleIterator::attachIterator' => ['void', 'iterator'=>'Iterator', 'infos='=>'string'], 'MultipleIterator::containsIterator' => ['bool', 'iterator'=>'Iterator'], 'MultipleIterator::countIterators' => ['int'], 'MultipleIterator::current' => ['array|false'], 'MultipleIterator::detachIterator' => ['void', 'iterator'=>'Iterator'], 'MultipleIterator::getFlags' => ['int'], 'MultipleIterator::key' => ['array'], 'MultipleIterator::next' => ['void'], 'MultipleIterator::rewind' => ['void'], 'MultipleIterator::setFlags' => ['int', 'flags'=>'int'], 'MultipleIterator::valid' => ['bool'], 'Mutex::create' => ['long', 'lock='=>'bool'], 'Mutex::destroy' => ['bool', 'mutex'=>'long'], 'Mutex::lock' => ['bool', 'mutex'=>'long'], 'Mutex::trylock' => ['bool', 'mutex'=>'long'], 'Mutex::unlock' => ['bool', 'mutex'=>'long', 'destroy='=>'bool'], 'mysql_xdevapi\baseresult::getWarnings' => ['array'], 'mysql_xdevapi\baseresult::getWarningsCount' => ['integer'], 'mysql_xdevapi\collection::add' => ['mysql_xdevapi\CollectionAdd', 'document'=>'mixed'], 'mysql_xdevapi\collection::addOrReplaceOne' => ['mysql_xdevapi\Result', 'id'=>'string', 'doc'=>'string'], 'mysql_xdevapi\collection::count' => ['integer'], 'mysql_xdevapi\collection::createIndex' => ['void', 'index_name'=>'string', 'index_desc_json'=>'string'], 'mysql_xdevapi\collection::dropIndex' => ['bool', 'index_name'=>'string'], 'mysql_xdevapi\collection::existsInDatabase' => ['bool'], 'mysql_xdevapi\collection::find' => ['mysql_xdevapi\CollectionFind', 'search_condition='=>'string'], 'mysql_xdevapi\collection::getName' => ['string'], 'mysql_xdevapi\collection::getOne' => ['Document', 'id'=>'string'], 'mysql_xdevapi\collection::getSchema' => ['mysql_xdevapi\schema'], 'mysql_xdevapi\collection::getSession' => ['Session'], 'mysql_xdevapi\collection::modify' => ['mysql_xdevapi\CollectionModify', 'search_condition'=>'string'], 'mysql_xdevapi\collection::remove' => ['mysql_xdevapi\CollectionRemove', 'search_condition'=>'string'], 'mysql_xdevapi\collection::removeOne' => ['mysql_xdevapi\Result', 'id'=>'string'], 'mysql_xdevapi\collection::replaceOne' => ['mysql_xdevapi\Result', 'id'=>'string', 'doc'=>'string'], 'mysql_xdevapi\collectionadd::execute' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\collectionfind::bind' => ['mysql_xdevapi\CollectionFind', 'placeholder_values'=>'array'], 'mysql_xdevapi\collectionfind::execute' => ['mysql_xdevapi\DocResult'], 'mysql_xdevapi\collectionfind::fields' => ['mysql_xdevapi\CollectionFind', 'projection'=>'string'], 'mysql_xdevapi\collectionfind::groupBy' => ['mysql_xdevapi\CollectionFind', 'sort_expr'=>'string'], 'mysql_xdevapi\collectionfind::having' => ['mysql_xdevapi\CollectionFind', 'sort_expr'=>'string'], 'mysql_xdevapi\collectionfind::limit' => ['mysql_xdevapi\CollectionFind', 'rows'=>'integer'], 'mysql_xdevapi\collectionfind::lockExclusive' => ['mysql_xdevapi\CollectionFind', 'lock_waiting_option='=>'integer'], 'mysql_xdevapi\collectionfind::lockShared' => ['mysql_xdevapi\CollectionFind', 'lock_waiting_option='=>'integer'], 'mysql_xdevapi\collectionfind::offset' => ['mysql_xdevapi\CollectionFind', 'position'=>'integer'], 'mysql_xdevapi\collectionfind::sort' => ['mysql_xdevapi\CollectionFind', 'sort_expr'=>'string'], 'mysql_xdevapi\collectionmodify::arrayAppend' => ['mysql_xdevapi\CollectionModify', 'collection_field'=>'string', 'expression_or_literal'=>'string'], 'mysql_xdevapi\collectionmodify::arrayInsert' => ['mysql_xdevapi\CollectionModify', 'collection_field'=>'string', 'expression_or_literal'=>'string'], 'mysql_xdevapi\collectionmodify::bind' => ['mysql_xdevapi\CollectionModify', 'placeholder_values'=>'array'], 'mysql_xdevapi\collectionmodify::execute' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\collectionmodify::limit' => ['mysql_xdevapi\CollectionModify', 'rows'=>'integer'], 'mysql_xdevapi\collectionmodify::patch' => ['mysql_xdevapi\CollectionModify', 'document'=>'string'], 'mysql_xdevapi\collectionmodify::replace' => ['mysql_xdevapi\CollectionModify', 'collection_field'=>'string', 'expression_or_literal'=>'string'], 'mysql_xdevapi\collectionmodify::set' => ['mysql_xdevapi\CollectionModify', 'collection_field'=>'string', 'expression_or_literal'=>'string'], 'mysql_xdevapi\collectionmodify::skip' => ['mysql_xdevapi\CollectionModify', 'position'=>'integer'], 'mysql_xdevapi\collectionmodify::sort' => ['mysql_xdevapi\CollectionModify', 'sort_expr'=>'string'], 'mysql_xdevapi\collectionmodify::unset' => ['mysql_xdevapi\CollectionModify', 'fields'=>'array'], 'mysql_xdevapi\collectionremove::bind' => ['mysql_xdevapi\CollectionRemove', 'placeholder_values'=>'array'], 'mysql_xdevapi\collectionremove::execute' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\collectionremove::limit' => ['mysql_xdevapi\CollectionRemove', 'rows'=>'integer'], 'mysql_xdevapi\collectionremove::sort' => ['mysql_xdevapi\CollectionRemove', 'sort_expr'=>'string'], 'mysql_xdevapi\columnresult::getCharacterSetName' => ['string'], 'mysql_xdevapi\columnresult::getCollationName' => ['string'], 'mysql_xdevapi\columnresult::getColumnLabel' => ['string'], 'mysql_xdevapi\columnresult::getColumnName' => ['string'], 'mysql_xdevapi\columnresult::getFractionalDigits' => ['integer'], 'mysql_xdevapi\columnresult::getLength' => ['integer'], 'mysql_xdevapi\columnresult::getSchemaName' => ['string'], 'mysql_xdevapi\columnresult::getTableLabel' => ['string'], 'mysql_xdevapi\columnresult::getTableName' => ['string'], 'mysql_xdevapi\columnresult::getType' => ['integer'], 'mysql_xdevapi\columnresult::isNumberSigned' => ['integer'], 'mysql_xdevapi\columnresult::isPadded' => ['integer'], 'mysql_xdevapi\crudoperationbindable::bind' => ['mysql_xdevapi\CrudOperationBindable', 'placeholder_values'=>'array'], 'mysql_xdevapi\crudoperationlimitable::limit' => ['mysql_xdevapi\CrudOperationLimitable', 'rows'=>'integer'], 'mysql_xdevapi\crudoperationskippable::skip' => ['mysql_xdevapi\CrudOperationSkippable', 'skip'=>'integer'], 'mysql_xdevapi\crudoperationsortable::sort' => ['mysql_xdevapi\CrudOperationSortable', 'sort_expr'=>'string'], 'mysql_xdevapi\databaseobject::existsInDatabase' => ['bool'], 'mysql_xdevapi\databaseobject::getName' => ['string'], 'mysql_xdevapi\databaseobject::getSession' => ['mysql_xdevapi\Session'], 'mysql_xdevapi\docresult::fetchAll' => ['Array'], 'mysql_xdevapi\docresult::fetchOne' => ['Object'], 'mysql_xdevapi\docresult::getWarnings' => ['Array'], 'mysql_xdevapi\docresult::getWarningsCount' => ['integer'], 'mysql_xdevapi\executable::execute' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\getsession' => ['mysql_xdevapi\Session', 'uri'=>'string'], 'mysql_xdevapi\result::getAutoIncrementValue' => ['int'], 'mysql_xdevapi\result::getGeneratedIds' => ['ArrayOfInt'], 'mysql_xdevapi\result::getWarnings' => ['array'], 'mysql_xdevapi\result::getWarningsCount' => ['integer'], 'mysql_xdevapi\rowresult::fetchAll' => ['array'], 'mysql_xdevapi\rowresult::fetchOne' => ['object'], 'mysql_xdevapi\rowresult::getColumnCount' => ['integer'], 'mysql_xdevapi\rowresult::getColumnNames' => ['array'], 'mysql_xdevapi\rowresult::getColumns' => ['array'], 'mysql_xdevapi\rowresult::getWarnings' => ['array'], 'mysql_xdevapi\rowresult::getWarningsCount' => ['integer'], 'mysql_xdevapi\schema::createCollection' => ['mysql_xdevapi\Collection', 'name'=>'string'], 'mysql_xdevapi\schema::dropCollection' => ['bool', 'collection_name'=>'string'], 'mysql_xdevapi\schema::existsInDatabase' => ['bool'], 'mysql_xdevapi\schema::getCollection' => ['mysql_xdevapi\Collection', 'name'=>'string'], 'mysql_xdevapi\schema::getCollectionAsTable' => ['mysql_xdevapi\Table', 'name'=>'string'], 'mysql_xdevapi\schema::getCollections' => ['array'], 'mysql_xdevapi\schema::getName' => ['string'], 'mysql_xdevapi\schema::getSession' => ['mysql_xdevapi\Session'], 'mysql_xdevapi\schema::getTable' => ['mysql_xdevapi\Table', 'name'=>'string'], 'mysql_xdevapi\schema::getTables' => ['array'], 'mysql_xdevapi\schemaobject::getSchema' => ['mysql_xdevapi\Schema'], 'mysql_xdevapi\session::close' => ['bool'], 'mysql_xdevapi\session::commit' => ['Object'], 'mysql_xdevapi\session::createSchema' => ['mysql_xdevapi\Schema', 'schema_name'=>'string'], 'mysql_xdevapi\session::dropSchema' => ['bool', 'schema_name'=>'string'], 'mysql_xdevapi\session::executeSql' => ['Object', 'statement'=>'string'], 'mysql_xdevapi\session::generateUUID' => ['string'], 'mysql_xdevapi\session::getClientId' => ['integer'], 'mysql_xdevapi\session::getSchema' => ['mysql_xdevapi\Schema', 'schema_name'=>'string'], 'mysql_xdevapi\session::getSchemas' => ['array'], 'mysql_xdevapi\session::getServerVersion' => ['integer'], 'mysql_xdevapi\session::killClient' => ['object', 'client_id'=>'integer'], 'mysql_xdevapi\session::listClients' => ['array'], 'mysql_xdevapi\session::quoteName' => ['string', 'name'=>'string'], 'mysql_xdevapi\session::releaseSavepoint' => ['void', 'name'=>'string'], 'mysql_xdevapi\session::rollback' => ['void'], 'mysql_xdevapi\session::rollbackTo' => ['void', 'name'=>'string'], 'mysql_xdevapi\session::setSavepoint' => ['string', 'name='=>'string'], 'mysql_xdevapi\session::sql' => ['mysql_xdevapi\SqlStatement', 'query'=>'string'], 'mysql_xdevapi\session::startTransaction' => ['void'], 'mysql_xdevapi\sqlstatement::bind' => ['mysql_xdevapi\SqlStatement', 'param'=>'string'], 'mysql_xdevapi\sqlstatement::execute' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\sqlstatement::getNextResult' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\sqlstatement::getResult' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\sqlstatement::hasMoreResults' => ['bool'], 'mysql_xdevapi\sqlstatementresult::fetchAll' => ['array'], 'mysql_xdevapi\sqlstatementresult::fetchOne' => ['object'], 'mysql_xdevapi\sqlstatementresult::getAffectedItemsCount' => ['integer'], 'mysql_xdevapi\sqlstatementresult::getColumnCount' => ['integer'], 'mysql_xdevapi\sqlstatementresult::getColumnNames' => ['array'], 'mysql_xdevapi\sqlstatementresult::getColumns' => ['Array'], 'mysql_xdevapi\sqlstatementresult::getGeneratedIds' => ['array'], 'mysql_xdevapi\sqlstatementresult::getLastInsertId' => ['String'], 'mysql_xdevapi\sqlstatementresult::getWarnings' => ['array'], 'mysql_xdevapi\sqlstatementresult::getWarningsCount' => ['integer'], 'mysql_xdevapi\sqlstatementresult::hasData' => ['bool'], 'mysql_xdevapi\sqlstatementresult::nextResult' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\statement::getNextResult' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\statement::getResult' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\statement::hasMoreResults' => ['bool'], 'mysql_xdevapi\table::count' => ['integer'], 'mysql_xdevapi\table::delete' => ['mysql_xdevapi\TableDelete'], 'mysql_xdevapi\table::existsInDatabase' => ['bool'], 'mysql_xdevapi\table::getName' => ['string'], 'mysql_xdevapi\table::getSchema' => ['mysql_xdevapi\Schema'], 'mysql_xdevapi\table::getSession' => ['mysql_xdevapi\Session'], 'mysql_xdevapi\table::insert' => ['mysql_xdevapi\TableInsert', 'columns'=>'mixed', '...args='=>'mixed'], 'mysql_xdevapi\table::isView' => ['bool'], 'mysql_xdevapi\table::select' => ['mysql_xdevapi\TableSelect', 'columns'=>'mixed', '...args='=>'mixed'], 'mysql_xdevapi\table::update' => ['mysql_xdevapi\TableUpdate'], 'mysql_xdevapi\tabledelete::bind' => ['mysql_xdevapi\TableDelete', 'placeholder_values'=>'array'], 'mysql_xdevapi\tabledelete::execute' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\tabledelete::limit' => ['mysql_xdevapi\TableDelete', 'rows'=>'integer'], 'mysql_xdevapi\tabledelete::offset' => ['mysql_xdevapi\TableDelete', 'position'=>'integer'], 'mysql_xdevapi\tabledelete::orderby' => ['mysql_xdevapi\TableDelete', 'orderby_expr'=>'string'], 'mysql_xdevapi\tabledelete::where' => ['mysql_xdevapi\TableDelete', 'where_expr'=>'string'], 'mysql_xdevapi\tableinsert::execute' => ['mysql_xdevapi\Result'], 'mysql_xdevapi\tableinsert::values' => ['mysql_xdevapi\TableInsert', 'row_values'=>'array'], 'mysql_xdevapi\tableselect::bind' => ['mysql_xdevapi\TableSelect', 'placeholder_values'=>'array'], 'mysql_xdevapi\tableselect::execute' => ['mysql_xdevapi\RowResult'], 'mysql_xdevapi\tableselect::groupBy' => ['mysql_xdevapi\TableSelect', 'sort_expr'=>'mixed'], 'mysql_xdevapi\tableselect::having' => ['mysql_xdevapi\TableSelect', 'sort_expr'=>'string'], 'mysql_xdevapi\tableselect::limit' => ['mysql_xdevapi\TableSelect', 'rows'=>'integer'], 'mysql_xdevapi\tableselect::lockExclusive' => ['mysql_xdevapi\TableSelect', 'lock_waiting_option='=>'integer'], 'mysql_xdevapi\tableselect::lockShared' => ['mysql_xdevapi\TableSelect', 'lock_waiting_option='=>'integer'], 'mysql_xdevapi\tableselect::offset' => ['mysql_xdevapi\TableSelect', 'position'=>'integer'], 'mysql_xdevapi\tableselect::orderby' => ['mysql_xdevapi\TableSelect', 'sort_expr'=>'mixed', '...args='=>'mixed'], 'mysql_xdevapi\tableselect::where' => ['mysql_xdevapi\TableSelect', 'where_expr'=>'string'], 'mysql_xdevapi\tableupdate::bind' => ['mysql_xdevapi\TableUpdate', 'placeholder_values'=>'array'], 'mysql_xdevapi\tableupdate::execute' => ['mysql_xdevapi\TableUpdate'], 'mysql_xdevapi\tableupdate::limit' => ['mysql_xdevapi\TableUpdate', 'rows'=>'integer'], 'mysql_xdevapi\tableupdate::orderby' => ['mysql_xdevapi\TableUpdate', 'orderby_expr'=>'mixed', '...args='=>'mixed'], 'mysql_xdevapi\tableupdate::set' => ['mysql_xdevapi\TableUpdate', 'table_field'=>'string', 'expression_or_literal'=>'string'], 'mysql_xdevapi\tableupdate::where' => ['mysql_xdevapi\TableUpdate', 'where_expr'=>'string'], 'mysqli::__construct' => ['void', 'host='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'mysqli::autocommit' => ['bool', 'mode'=>'bool'], 'mysqli::begin_transaction' => ['bool', 'flags='=>'int', 'name='=>'string'], 'mysqli::change_user' => ['bool', 'user'=>'string', 'password'=>'string', 'database'=>'string'], 'mysqli::character_set_name' => ['string'], 'mysqli::close' => ['bool'], 'mysqli::commit' => ['bool', 'flags='=>'int', 'name='=>'string'], 'mysqli::debug' => ['bool', 'message'=>'string'], 'mysqli::disable_reads_from_master' => ['bool'], 'mysqli::dump_debug_info' => ['bool'], 'mysqli::escape_string' => ['string', 'escapestr'=>'string'], 'mysqli::get_charset' => ['object'], 'mysqli::get_client_info' => ['string'], 'mysqli::get_connection_stats' => ['array|false'], 'mysqli::get_warnings' => ['mysqli_warning'], 'mysqli::init' => ['mysqli'], 'mysqli::kill' => ['bool', 'processid'=>'int'], 'mysqli::more_results' => ['bool'], 'mysqli::multi_query' => ['bool', 'query'=>'string'], 'mysqli::next_result' => ['bool'], 'mysqli::options' => ['bool', 'option'=>'int', 'value'=>'mixed'], 'mysqli::ping' => ['bool'], 'mysqli::poll' => ['int|false', '&w_read'=>'array', '&w_error'=>'array', '&w_reject'=>'array', 'sec'=>'int', 'usecond='=>'int'], 'mysqli::prepare' => ['mysqli_stmt|false', 'query'=>'string'], 'mysqli::query' => ['bool|mysqli_result', 'query'=>'string', 'resultmode='=>'int'], 'mysqli::real_connect' => ['bool', 'host='=>'string|null', 'username='=>'string', 'passwd='=>'string|null', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string', 'flags='=>'int'], 'mysqli::real_escape_string' => ['string', 'escapestr'=>'string'], 'mysqli::real_query' => ['bool', 'query'=>'string'], 'mysqli::reap_async_query' => ['mysqli_result|false'], 'mysqli::refresh' => ['bool', 'options'=>'int'], 'mysqli::release_savepoint' => ['bool', 'name'=>'string'], 'mysqli::rollback' => ['bool', 'flags='=>'int', 'name='=>'string'], 'mysqli::rpl_query_type' => ['int', 'query'=>'string'], 'mysqli::savepoint' => ['bool', 'name'=>'string'], 'mysqli::select_db' => ['bool', 'dbname'=>'string'], 'mysqli::send_query' => ['bool', 'query'=>'string'], 'mysqli::set_charset' => ['bool', 'charset'=>'string'], 'mysqli::set_local_infile_default' => ['void'], 'mysqli::set_local_infile_handler' => ['bool', 'read_func='=>'callable'], 'mysqli::ssl_set' => ['bool', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'mysqli::stat' => ['string|false'], 'mysqli::stmt_init' => ['mysqli_stmt'], 'mysqli::store_result' => ['mysqli_result|false', 'option='=>'int'], 'mysqli::thread_safe' => ['bool'], 'mysqli::use_result' => ['mysqli_result|false'], 'mysqli_affected_rows' => ['int', 'link'=>'mysqli'], 'mysqli_autocommit' => ['bool', 'link'=>'mysqli', 'mode'=>'bool'], 'mysqli_begin_transaction' => ['bool', 'link'=>'mysqli', 'flags='=>'int', 'name='=>'string'], 'mysqli_change_user' => ['bool', 'link'=>'mysqli', 'user'=>'string', 'password'=>'string', 'database'=>'?string'], 'mysqli_character_set_name' => ['string', 'link'=>'mysqli'], 'mysqli_close' => ['bool', 'link'=>'mysqli'], 'mysqli_commit' => ['bool', 'link'=>'mysqli', 'flags='=>'int', 'name='=>'string'], 'mysqli_connect' => ['mysqli|false', 'host='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'mysqli_connect_errno' => ['int'], 'mysqli_connect_error' => ['string'], 'mysqli_data_seek' => ['bool', 'result'=>'mysqli_result', 'offset'=>'int'], 'mysqli_debug' => ['bool', 'message'=>'string'], 'mysqli_disable_reads_from_master' => ['bool', 'link'=>'mysqli'], 'mysqli_disable_rpl_parse' => ['bool', 'link'=>'mysqli'], 'mysqli_driver::embedded_server_end' => ['void'], 'mysqli_driver::embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'], 'mysqli_dump_debug_info' => ['bool', 'link'=>'mysqli'], 'mysqli_embedded_server_end' => ['void'], 'mysqli_embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'], 'mysqli_enable_reads_from_master' => ['bool', 'link'=>'mysqli'], 'mysqli_enable_rpl_parse' => ['bool', 'link'=>'mysqli'], 'mysqli_errno' => ['int', 'link'=>'mysqli'], 'mysqli_error' => ['string', 'link'=>'mysqli'], 'mysqli_error_list' => ['array', 'connection'=>'mysqli'], 'mysqli_escape_string' => ['string', 'link'=>'mysqli', 'escapestr'=>'string'], 'mysqli_execute' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_fetch_all' => ['array', 'result'=>'mysqli_result', 'resulttype='=>'int'], 'mysqli_fetch_array' => ['?array', 'result'=>'mysqli_result', 'resulttype='=>'int'], 'mysqli_fetch_assoc' => ['array|null', 'result'=>'mysqli_result'], 'mysqli_fetch_field' => ['object|false', 'result'=>'mysqli_result'], 'mysqli_fetch_field_direct' => ['object|false', 'result'=>'mysqli_result', 'fieldnr'=>'int'], 'mysqli_fetch_fields' => ['array|false', 'result'=>'mysqli_result'], 'mysqli_fetch_lengths' => ['array|false', 'result'=>'mysqli_result'], 'mysqli_fetch_object' => ['?object', 'result'=>'mysqli_result', 'class_name='=>'string', 'params='=>'?array'], 'mysqli_fetch_row' => ['?array', 'result'=>'mysqli_result'], 'mysqli_field_count' => ['int', 'link'=>'mysqli'], 'mysqli_field_seek' => ['bool', 'result'=>'mysqli_result', 'fieldnr'=>'int'], 'mysqli_field_tell' => ['int', 'result'=>'mysqli_result'], 'mysqli_free_result' => ['void', 'link'=>'mysqli_result'], 'mysqli_get_cache_stats' => ['array|false'], 'mysqli_get_charset' => ['object', 'link'=>'mysqli'], 'mysqli_get_client_info' => ['string', 'link'=>'mysqli'], 'mysqli_get_client_stats' => ['array|false'], 'mysqli_get_client_version' => ['int', 'link'=>'mysqli'], 'mysqli_get_connection_stats' => ['array|false', 'link'=>'mysqli'], 'mysqli_get_host_info' => ['string', 'link'=>'mysqli'], 'mysqli_get_links_stats' => ['array'], 'mysqli_get_proto_info' => ['int', 'link'=>'mysqli'], 'mysqli_get_server_info' => ['string', 'link'=>'mysqli'], 'mysqli_get_server_version' => ['int', 'link'=>'mysqli'], 'mysqli_get_warnings' => ['mysqli_warning', 'link'=>'mysqli'], 'mysqli_info' => ['?string', 'link'=>'mysqli'], 'mysqli_init' => ['mysqli'], 'mysqli_insert_id' => ['int|string', 'link'=>'mysqli'], 'mysqli_kill' => ['bool', 'link'=>'mysqli', 'processid'=>'int'], 'mysqli_link_construct' => ['object'], 'mysqli_master_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_more_results' => ['bool', 'link'=>'mysqli'], 'mysqli_multi_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_next_result' => ['bool', 'link'=>'mysqli'], 'mysqli_num_fields' => ['int', 'link'=>'mysqli_result'], 'mysqli_num_rows' => ['int', 'link'=>'mysqli_result'], 'mysqli_options' => ['bool', 'link'=>'mysqli', 'option'=>'int', 'value'=>'mixed'], 'mysqli_ping' => ['bool', 'link'=>'mysqli'], 'mysqli_poll' => ['int|false', 'read'=>'array', 'error'=>'array', 'reject'=>'array', 'second'=>'int', 'usecond='=>'int'], 'mysqli_prepare' => ['mysqli_stmt|false', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_query' => ['mysqli_result|bool', 'link'=>'mysqli', 'query'=>'string', 'resultmode='=>'int'], 'mysqli_real_connect' => ['bool', 'link='=>'mysqli', 'host='=>'string|null', 'username='=>'string', 'passwd='=>'string|null', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string', 'flags='=>'int'], 'mysqli_real_escape_string' => ['string', 'link'=>'mysqli', 'escapestr'=>'string'], 'mysqli_real_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_reap_async_query' => ['mysqli_result|false', 'link'=>'mysqli'], 'mysqli_refresh' => ['bool', 'link'=>'mysqli', 'options'=>'int'], 'mysqli_release_savepoint' => ['bool', 'link'=>'mysqli', 'name'=>'string'], 'mysqli_report' => ['bool', 'flags'=>'int'], 'mysqli_result::__construct' => ['void', 'link'=>'mysqli', 'resultmode='=>'int'], 'mysqli_result::close' => ['void'], 'mysqli_result::data_seek' => ['bool', 'offset'=>'int'], 'mysqli_result::fetch_all' => ['array', 'resulttype='=>'int'], 'mysqli_result::fetch_array' => ['?array', 'resulttype='=>'int'], 'mysqli_result::fetch_assoc' => ['array|null'], 'mysqli_result::fetch_field' => ['object|false'], 'mysqli_result::fetch_field_direct' => ['object|false', 'fieldnr'=>'int'], 'mysqli_result::fetch_fields' => ['array|false'], 'mysqli_result::fetch_object' => ['object|stdClass|null', 'class_name='=>'string', 'params='=>'array'], 'mysqli_result::fetch_row' => ['?array'], 'mysqli_result::field_seek' => ['bool', 'fieldnr'=>'int'], 'mysqli_result::free' => ['void'], 'mysqli_result::free_result' => ['void'], 'mysqli_rollback' => ['bool', 'link'=>'mysqli', 'flags='=>'int', 'name='=>'string'], 'mysqli_rpl_parse_enabled' => ['int', 'link'=>'mysqli'], 'mysqli_rpl_probe' => ['bool', 'link'=>'mysqli'], 'mysqli_rpl_query_type' => ['int', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_savepoint' => ['bool', 'link'=>'mysqli', 'name'=>'string'], 'mysqli_savepoint_libmysql' => ['bool'], 'mysqli_select_db' => ['bool', 'link'=>'mysqli', 'dbname'=>'string'], 'mysqli_send_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_set_charset' => ['bool', 'link'=>'mysqli', 'charset'=>'string'], 'mysqli_set_local_infile_default' => ['void', 'link'=>'mysqli'], 'mysqli_set_local_infile_handler' => ['bool', 'link'=>'mysqli', 'read_func'=>'callable'], 'mysqli_set_opt' => ['bool', 'link'=>'mysqli', 'option'=>'int', 'value'=>'mixed'], 'mysqli_slave_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_sqlstate' => ['string', 'link'=>'mysqli'], 'mysqli_ssl_set' => ['bool', 'link'=>'mysqli', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'mysqli_stat' => ['string|false', 'link'=>'mysqli'], 'mysqli_stmt::__construct' => ['void', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_stmt::attr_get' => ['false|int', 'attr'=>'int'], 'mysqli_stmt::attr_set' => ['bool', 'attr'=>'int', 'mode'=>'int'], 'mysqli_stmt::bind_param' => ['bool', 'types'=>'string', '&var1'=>'mixed', '&...args='=>'mixed'], 'mysqli_stmt::bind_result' => ['bool', '&w_var1'=>'', '&...w_vars='=>''], 'mysqli_stmt::close' => ['bool'], 'mysqli_stmt::data_seek' => ['void', 'offset'=>'int'], 'mysqli_stmt::execute' => ['bool'], 'mysqli_stmt::fetch' => ['bool|null'], 'mysqli_stmt::free_result' => ['void'], 'mysqli_stmt::get_result' => ['mysqli_result|false'], 'mysqli_stmt::get_warnings' => ['object'], 'mysqli_stmt::more_results' => ['bool'], 'mysqli_stmt::next_result' => ['bool'], 'mysqli_stmt::num_rows' => ['int'], 'mysqli_stmt::prepare' => ['bool', 'query'=>'string'], 'mysqli_stmt::reset' => ['bool'], 'mysqli_stmt::result_metadata' => ['mysqli_result|false'], 'mysqli_stmt::send_long_data' => ['bool', 'param_nr'=>'int', 'data'=>'string'], 'mysqli_stmt::store_result' => ['bool'], 'mysqli_stmt_affected_rows' => ['int|string', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_attr_get' => ['int|false', 'stmt'=>'mysqli_stmt', 'attr'=>'int'], 'mysqli_stmt_attr_set' => ['bool', 'stmt'=>'mysqli_stmt', 'attr'=>'int', 'mode'=>'int'], 'mysqli_stmt_bind_param' => ['bool', 'stmt'=>'mysqli_stmt', 'types'=>'string', '&var1'=>'mixed', '&...args='=>'mixed'], 'mysqli_stmt_bind_result' => ['bool', 'stmt'=>'mysqli_stmt', '&w_var1'=>'', '&...w_vars='=>''], 'mysqli_stmt_close' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_data_seek' => ['void', 'stmt'=>'mysqli_stmt', 'offset'=>'int'], 'mysqli_stmt_errno' => ['int', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_error' => ['string', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_error_list' => ['array', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_execute' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_fetch' => ['bool|null', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_field_count' => ['int', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_free_result' => ['void', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_get_result' => ['mysqli_result|false', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_get_warnings' => ['object', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_init' => ['mysqli_stmt', 'link'=>'mysqli'], 'mysqli_stmt_insert_id' => ['mixed', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_more_results' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_next_result' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_num_rows' => ['int', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_param_count' => ['int', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_prepare' => ['bool', 'stmt'=>'mysqli_stmt', 'query'=>'string'], 'mysqli_stmt_reset' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_result_metadata' => ['mysqli_result|false', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_send_long_data' => ['bool', 'stmt'=>'mysqli_stmt', 'param_nr'=>'int', 'data'=>'string'], 'mysqli_stmt_sqlstate' => ['string', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_store_result' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_store_result' => ['mysqli_result|false', 'link'=>'mysqli', 'option='=>'int'], 'mysqli_thread_id' => ['int', 'link'=>'mysqli'], 'mysqli_thread_safe' => ['bool'], 'mysqli_use_result' => ['mysqli_result|false', 'link'=>'mysqli'], 'mysqli_warning::__construct' => ['void'], 'mysqli_warning::next' => ['bool'], 'mysqli_warning_count' => ['int', 'link'=>'mysqli'], 'mysqlnd_memcache_get_config' => ['array', 'connection'=>'mixed'], 'mysqlnd_memcache_set' => ['bool', 'mysql_connection'=>'mixed', 'memcache_connection='=>'Memcached', 'pattern='=>'string', 'callback='=>'callable'], 'mysqlnd_ms_dump_servers' => ['array', 'connection'=>'mixed'], 'mysqlnd_ms_fabric_select_global' => ['array', 'connection'=>'mixed', 'table_name'=>'mixed'], 'mysqlnd_ms_fabric_select_shard' => ['array', 'connection'=>'mixed', 'table_name'=>'mixed', 'shard_key'=>'mixed'], 'mysqlnd_ms_get_last_gtid' => ['string', 'connection'=>'mixed'], 'mysqlnd_ms_get_last_used_connection' => ['array', 'connection'=>'mixed'], 'mysqlnd_ms_get_stats' => ['array'], 'mysqlnd_ms_match_wild' => ['bool', 'table_name'=>'string', 'wildcard'=>'string'], 'mysqlnd_ms_query_is_select' => ['int', 'query'=>'string'], 'mysqlnd_ms_set_qos' => ['bool', 'connection'=>'mixed', 'service_level'=>'int', 'service_level_option='=>'int', 'option_value='=>'mixed'], 'mysqlnd_ms_set_user_pick_server' => ['bool', 'function'=>'string'], 'mysqlnd_ms_xa_begin' => ['int', 'connection'=>'mixed', 'gtrid'=>'string', 'timeout='=>'int'], 'mysqlnd_ms_xa_commit' => ['int', 'connection'=>'mixed', 'gtrid'=>'string'], 'mysqlnd_ms_xa_gc' => ['int', 'connection'=>'mixed', 'gtrid='=>'string', 'ignore_max_retries='=>'bool'], 'mysqlnd_ms_xa_rollback' => ['int', 'connection'=>'mixed', 'gtrid'=>'string'], 'mysqlnd_qc_change_handler' => ['bool', 'handler'=>''], 'mysqlnd_qc_clear_cache' => ['bool'], 'mysqlnd_qc_get_available_handlers' => ['array'], 'mysqlnd_qc_get_cache_info' => ['array'], 'mysqlnd_qc_get_core_stats' => ['array'], 'mysqlnd_qc_get_handler' => ['array'], 'mysqlnd_qc_get_normalized_query_trace_log' => ['array'], 'mysqlnd_qc_get_query_trace_log' => ['array'], 'mysqlnd_qc_set_cache_condition' => ['bool', 'condition_type'=>'int', 'condition'=>'mixed', 'condition_option'=>'mixed'], 'mysqlnd_qc_set_is_select' => ['mixed', 'callback'=>'string'], 'mysqlnd_qc_set_storage_handler' => ['bool', 'handler'=>'string'], 'mysqlnd_qc_set_user_handlers' => ['bool', 'get_hash'=>'string', 'find_query_in_cache'=>'string', 'return_to_cache'=>'string', 'add_query_to_cache_if_not_exists'=>'string', 'query_is_select'=>'string', 'update_query_run_time_stats'=>'string', 'get_stats'=>'string', 'clear_cache'=>'string'], 'mysqlnd_uh_convert_to_mysqlnd' => ['resource', '&rw_mysql_connection'=>'mysqli'], 'mysqlnd_uh_set_connection_proxy' => ['bool', '&rw_connection_proxy'=>'MysqlndUhConnection', '&rw_mysqli_connection='=>'mysqli'], 'mysqlnd_uh_set_statement_proxy' => ['bool', '&rw_statement_proxy'=>'MysqlndUhStatement'], 'MysqlndUhConnection::__construct' => ['void'], 'MysqlndUhConnection::changeUser' => ['bool', 'connection'=>'mysqlnd_connection', 'user'=>'string', 'password'=>'string', 'database'=>'string', 'silent'=>'bool', 'passwd_len'=>'int'], 'MysqlndUhConnection::charsetName' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::close' => ['bool', 'connection'=>'mysqlnd_connection', 'close_type'=>'int'], 'MysqlndUhConnection::connect' => ['bool', 'connection'=>'mysqlnd_connection', 'host'=>'string', 'use'=>'string', 'password'=>'string', 'database'=>'string', 'port'=>'int', 'socket'=>'string', 'mysql_flags'=>'int'], 'MysqlndUhConnection::endPSession' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::escapeString' => ['string', 'connection'=>'mysqlnd_connection', 'escape_string'=>'string'], 'MysqlndUhConnection::getAffectedRows' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getErrorNumber' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getErrorString' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getFieldCount' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getHostInformation' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getLastInsertId' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getLastMessage' => ['void', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getProtocolInformation' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getServerInformation' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getServerStatistics' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getServerVersion' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getSqlstate' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getStatistics' => ['array', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getThreadId' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getWarningCount' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::init' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::killConnection' => ['bool', 'connection'=>'mysqlnd_connection', 'pid'=>'int'], 'MysqlndUhConnection::listFields' => ['array', 'connection'=>'mysqlnd_connection', 'table'=>'string', 'achtung_wild'=>'string'], 'MysqlndUhConnection::listMethod' => ['void', 'connection'=>'mysqlnd_connection', 'query'=>'string', 'achtung_wild'=>'string', 'par1'=>'string'], 'MysqlndUhConnection::moreResults' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::nextResult' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::ping' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::query' => ['bool', 'connection'=>'mysqlnd_connection', 'query'=>'string'], 'MysqlndUhConnection::queryReadResultsetHeader' => ['bool', 'connection'=>'mysqlnd_connection', 'mysqlnd_stmt'=>'mysqlnd_statement'], 'MysqlndUhConnection::reapQuery' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::refreshServer' => ['bool', 'connection'=>'mysqlnd_connection', 'options'=>'int'], 'MysqlndUhConnection::restartPSession' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::selectDb' => ['bool', 'connection'=>'mysqlnd_connection', 'database'=>'string'], 'MysqlndUhConnection::sendClose' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::sendQuery' => ['bool', 'connection'=>'mysqlnd_connection', 'query'=>'string'], 'MysqlndUhConnection::serverDumpDebugInformation' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::setAutocommit' => ['bool', 'connection'=>'mysqlnd_connection', 'mode'=>'int'], 'MysqlndUhConnection::setCharset' => ['bool', 'connection'=>'mysqlnd_connection', 'charset'=>'string'], 'MysqlndUhConnection::setClientOption' => ['bool', 'connection'=>'mysqlnd_connection', 'option'=>'int', 'value'=>'int'], 'MysqlndUhConnection::setServerOption' => ['void', 'connection'=>'mysqlnd_connection', 'option'=>'int'], 'MysqlndUhConnection::shutdownServer' => ['void', 'MYSQLND_UH_RES_MYSQLND_NAME'=>'string', 'level'=>'string'], 'MysqlndUhConnection::simpleCommand' => ['bool', 'connection'=>'mysqlnd_connection', 'command'=>'int', 'arg'=>'string', 'ok_packet'=>'int', 'silent'=>'bool', 'ignore_upsert_status'=>'bool'], 'MysqlndUhConnection::simpleCommandHandleResponse' => ['bool', 'connection'=>'mysqlnd_connection', 'ok_packet'=>'int', 'silent'=>'bool', 'command'=>'int', 'ignore_upsert_status'=>'bool'], 'MysqlndUhConnection::sslSet' => ['bool', 'connection'=>'mysqlnd_connection', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'MysqlndUhConnection::stmtInit' => ['resource', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::storeResult' => ['resource', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::txCommit' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::txRollback' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::useResult' => ['resource', 'connection'=>'mysqlnd_connection'], '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'], 'ncurses_addch' => ['int', 'ch'=>'int'], 'ncurses_addchnstr' => ['int', 's'=>'string', 'n'=>'int'], 'ncurses_addchstr' => ['int', 's'=>'string'], 'ncurses_addnstr' => ['int', 's'=>'string', 'n'=>'int'], 'ncurses_addstr' => ['int', 'text'=>'string'], 'ncurses_assume_default_colors' => ['int', 'fg'=>'int', 'bg'=>'int'], 'ncurses_attroff' => ['int', 'attributes'=>'int'], 'ncurses_attron' => ['int', 'attributes'=>'int'], 'ncurses_attrset' => ['int', 'attributes'=>'int'], 'ncurses_baudrate' => ['int'], 'ncurses_beep' => ['int'], 'ncurses_bkgd' => ['int', 'attrchar'=>'int'], 'ncurses_bkgdset' => ['void', 'attrchar'=>'int'], 'ncurses_border' => ['int', 'left'=>'int', 'right'=>'int', 'top'=>'int', 'bottom'=>'int', 'tl_corner'=>'int', 'tr_corner'=>'int', 'bl_corner'=>'int', 'br_corner'=>'int'], 'ncurses_bottom_panel' => ['int', 'panel'=>'resource'], 'ncurses_can_change_color' => ['bool'], 'ncurses_cbreak' => ['bool'], 'ncurses_clear' => ['bool'], 'ncurses_clrtobot' => ['bool'], 'ncurses_clrtoeol' => ['bool'], 'ncurses_color_content' => ['int', 'color'=>'int', 'r'=>'int', 'g'=>'int', 'b'=>'int'], 'ncurses_color_set' => ['int', 'pair'=>'int'], 'ncurses_curs_set' => ['int', 'visibility'=>'int'], 'ncurses_def_prog_mode' => ['bool'], 'ncurses_def_shell_mode' => ['bool'], 'ncurses_define_key' => ['int', 'definition'=>'string', 'keycode'=>'int'], 'ncurses_del_panel' => ['bool', 'panel'=>'resource'], 'ncurses_delay_output' => ['int', 'milliseconds'=>'int'], 'ncurses_delch' => ['bool'], 'ncurses_deleteln' => ['bool'], 'ncurses_delwin' => ['bool', 'window'=>'resource'], 'ncurses_doupdate' => ['bool'], 'ncurses_echo' => ['bool'], 'ncurses_echochar' => ['int', 'character'=>'int'], 'ncurses_end' => ['int'], 'ncurses_erase' => ['bool'], 'ncurses_erasechar' => ['string'], 'ncurses_filter' => ['void'], 'ncurses_flash' => ['bool'], 'ncurses_flushinp' => ['bool'], 'ncurses_getch' => ['int'], 'ncurses_getmaxyx' => ['void', 'window'=>'resource', 'y'=>'int', 'x'=>'int'], 'ncurses_getmouse' => ['bool', 'mevent'=>'array'], 'ncurses_getyx' => ['void', 'window'=>'resource', 'y'=>'int', 'x'=>'int'], 'ncurses_halfdelay' => ['int', 'tenth'=>'int'], 'ncurses_has_colors' => ['bool'], 'ncurses_has_ic' => ['bool'], 'ncurses_has_il' => ['bool'], 'ncurses_has_key' => ['int', 'keycode'=>'int'], 'ncurses_hide_panel' => ['int', 'panel'=>'resource'], 'ncurses_hline' => ['int', 'charattr'=>'int', 'n'=>'int'], 'ncurses_inch' => ['string'], 'ncurses_init' => ['void'], 'ncurses_init_color' => ['int', 'color'=>'int', 'r'=>'int', 'g'=>'int', 'b'=>'int'], 'ncurses_init_pair' => ['int', 'pair'=>'int', 'fg'=>'int', 'bg'=>'int'], 'ncurses_insch' => ['int', 'character'=>'int'], 'ncurses_insdelln' => ['int', 'count'=>'int'], 'ncurses_insertln' => ['int'], 'ncurses_insstr' => ['int', 'text'=>'string'], 'ncurses_instr' => ['int', 'buffer'=>'string'], 'ncurses_isendwin' => ['bool'], 'ncurses_keyok' => ['int', 'keycode'=>'int', 'enable'=>'bool'], 'ncurses_keypad' => ['int', 'window'=>'resource', 'bf'=>'bool'], 'ncurses_killchar' => ['string'], 'ncurses_longname' => ['string'], 'ncurses_meta' => ['int', 'window'=>'resource', '_8bit'=>'bool'], 'ncurses_mouse_trafo' => ['bool', 'y'=>'int', 'x'=>'int', 'toscreen'=>'bool'], 'ncurses_mouseinterval' => ['int', 'milliseconds'=>'int'], 'ncurses_mousemask' => ['int', 'newmask'=>'int', 'oldmask'=>'int'], 'ncurses_move' => ['int', 'y'=>'int', 'x'=>'int'], 'ncurses_move_panel' => ['int', 'panel'=>'resource', 'startx'=>'int', 'starty'=>'int'], 'ncurses_mvaddch' => ['int', 'y'=>'int', 'x'=>'int', 'c'=>'int'], 'ncurses_mvaddchnstr' => ['int', 'y'=>'int', 'x'=>'int', 's'=>'string', 'n'=>'int'], 'ncurses_mvaddchstr' => ['int', 'y'=>'int', 'x'=>'int', 's'=>'string'], 'ncurses_mvaddnstr' => ['int', 'y'=>'int', 'x'=>'int', 's'=>'string', 'n'=>'int'], 'ncurses_mvaddstr' => ['int', 'y'=>'int', 'x'=>'int', 's'=>'string'], 'ncurses_mvcur' => ['int', 'old_y'=>'int', 'old_x'=>'int', 'new_y'=>'int', 'new_x'=>'int'], 'ncurses_mvdelch' => ['int', 'y'=>'int', 'x'=>'int'], 'ncurses_mvgetch' => ['int', 'y'=>'int', 'x'=>'int'], 'ncurses_mvhline' => ['int', 'y'=>'int', 'x'=>'int', 'attrchar'=>'int', 'n'=>'int'], 'ncurses_mvinch' => ['int', 'y'=>'int', 'x'=>'int'], 'ncurses_mvvline' => ['int', 'y'=>'int', 'x'=>'int', 'attrchar'=>'int', 'n'=>'int'], 'ncurses_mvwaddstr' => ['int', 'window'=>'resource', 'y'=>'int', 'x'=>'int', 'text'=>'string'], 'ncurses_napms' => ['int', 'milliseconds'=>'int'], 'ncurses_new_panel' => ['resource', 'window'=>'resource'], 'ncurses_newpad' => ['resource', 'rows'=>'int', 'cols'=>'int'], 'ncurses_newwin' => ['resource', 'rows'=>'int', 'cols'=>'int', 'y'=>'int', 'x'=>'int'], 'ncurses_nl' => ['bool'], 'ncurses_nocbreak' => ['bool'], 'ncurses_noecho' => ['bool'], 'ncurses_nonl' => ['bool'], 'ncurses_noqiflush' => ['void'], 'ncurses_noraw' => ['bool'], 'ncurses_pair_content' => ['int', 'pair'=>'int', 'f'=>'int', 'b'=>'int'], 'ncurses_panel_above' => ['resource', 'panel'=>'resource'], 'ncurses_panel_below' => ['resource', 'panel'=>'resource'], 'ncurses_panel_window' => ['resource', 'panel'=>'resource'], 'ncurses_pnoutrefresh' => ['int', 'pad'=>'resource', 'pminrow'=>'int', 'pmincol'=>'int', 'sminrow'=>'int', 'smincol'=>'int', 'smaxrow'=>'int', 'smaxcol'=>'int'], 'ncurses_prefresh' => ['int', 'pad'=>'resource', 'pminrow'=>'int', 'pmincol'=>'int', 'sminrow'=>'int', 'smincol'=>'int', 'smaxrow'=>'int', 'smaxcol'=>'int'], 'ncurses_putp' => ['int', 'text'=>'string'], 'ncurses_qiflush' => ['void'], 'ncurses_raw' => ['bool'], 'ncurses_refresh' => ['int', 'ch'=>'int'], 'ncurses_replace_panel' => ['int', 'panel'=>'resource', 'window'=>'resource'], 'ncurses_reset_prog_mode' => ['int'], 'ncurses_reset_shell_mode' => ['int'], 'ncurses_resetty' => ['bool'], 'ncurses_savetty' => ['bool'], 'ncurses_scr_dump' => ['int', 'filename'=>'string'], 'ncurses_scr_init' => ['int', 'filename'=>'string'], 'ncurses_scr_restore' => ['int', 'filename'=>'string'], 'ncurses_scr_set' => ['int', 'filename'=>'string'], 'ncurses_scrl' => ['int', 'count'=>'int'], 'ncurses_show_panel' => ['int', 'panel'=>'resource'], 'ncurses_slk_attr' => ['int'], 'ncurses_slk_attroff' => ['int', 'intarg'=>'int'], 'ncurses_slk_attron' => ['int', 'intarg'=>'int'], 'ncurses_slk_attrset' => ['int', 'intarg'=>'int'], 'ncurses_slk_clear' => ['bool'], 'ncurses_slk_color' => ['int', 'intarg'=>'int'], 'ncurses_slk_init' => ['bool', 'format'=>'int'], 'ncurses_slk_noutrefresh' => ['bool'], 'ncurses_slk_refresh' => ['int'], 'ncurses_slk_restore' => ['int'], 'ncurses_slk_set' => ['bool', 'labelnr'=>'int', 'label'=>'string', 'format'=>'int'], 'ncurses_slk_touch' => ['int'], 'ncurses_standend' => ['int'], 'ncurses_standout' => ['int'], 'ncurses_start_color' => ['int'], 'ncurses_termattrs' => ['bool'], 'ncurses_termname' => ['string'], 'ncurses_timeout' => ['void', 'millisec'=>'int'], 'ncurses_top_panel' => ['int', 'panel'=>'resource'], 'ncurses_typeahead' => ['int', 'fd'=>'int'], 'ncurses_ungetch' => ['int', 'keycode'=>'int'], 'ncurses_ungetmouse' => ['bool', 'mevent'=>'array'], 'ncurses_update_panels' => ['void'], 'ncurses_use_default_colors' => ['bool'], 'ncurses_use_env' => ['void', 'flag'=>'bool'], 'ncurses_use_extended_names' => ['int', 'flag'=>'bool'], 'ncurses_vidattr' => ['int', 'intarg'=>'int'], 'ncurses_vline' => ['int', 'charattr'=>'int', 'n'=>'int'], 'ncurses_waddch' => ['int', 'window'=>'resource', 'ch'=>'int'], 'ncurses_waddstr' => ['int', 'window'=>'resource', 'string'=>'string', 'n='=>'int'], 'ncurses_wattroff' => ['int', 'window'=>'resource', 'attrs'=>'int'], 'ncurses_wattron' => ['int', 'window'=>'resource', 'attrs'=>'int'], 'ncurses_wattrset' => ['int', 'window'=>'resource', 'attrs'=>'int'], 'ncurses_wborder' => ['int', 'window'=>'resource', 'left'=>'int', 'right'=>'int', 'top'=>'int', 'bottom'=>'int', 'tl_corner'=>'int', 'tr_corner'=>'int', 'bl_corner'=>'int', 'br_corner'=>'int'], 'ncurses_wclear' => ['int', 'window'=>'resource'], 'ncurses_wcolor_set' => ['int', 'window'=>'resource', 'color_pair'=>'int'], 'ncurses_werase' => ['int', 'window'=>'resource'], 'ncurses_wgetch' => ['int', 'window'=>'resource'], 'ncurses_whline' => ['int', 'window'=>'resource', 'charattr'=>'int', 'n'=>'int'], 'ncurses_wmouse_trafo' => ['bool', 'window'=>'resource', 'y'=>'int', 'x'=>'int', 'toscreen'=>'bool'], 'ncurses_wmove' => ['int', 'window'=>'resource', 'y'=>'int', 'x'=>'int'], 'ncurses_wnoutrefresh' => ['int', 'window'=>'resource'], 'ncurses_wrefresh' => ['int', 'window'=>'resource'], 'ncurses_wstandend' => ['int', 'window'=>'resource'], 'ncurses_wstandout' => ['int', 'window'=>'resource'], 'ncurses_wvline' => ['int', 'window'=>'resource', 'charattr'=>'int', 'n'=>'int'], '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'], 'newrelic_background_job' => ['void', 'flag='=>'bool'], 'newrelic_capture_params' => ['void', 'enable='=>'bool'], 'newrelic_custom_metric' => ['bool', 'metric_name'=>'string', 'value'=>'float'], 'newrelic_disable_autorum' => ['true'], 'newrelic_end_of_transaction' => ['void'], 'newrelic_end_transaction' => ['bool', 'ignore='=>'bool'], 'newrelic_get_browser_timing_footer' => ['string', 'include_tags='=>'bool'], 'newrelic_get_browser_timing_header' => ['string', 'include_tags='=>'bool'], 'newrelic_ignore_apdex' => ['void'], 'newrelic_ignore_transaction' => ['void'], 'newrelic_name_transaction' => ['bool', 'name'=>'string'], 'newrelic_notice_error' => ['void', 'message'=>'string', 'exception='=>'Exception|Throwable'], 'newrelic_notice_error\'1' => ['void', 'unused_1'=>'string', 'message'=>'string', 'unused_2'=>'string', 'unused_3'=>'int', 'unused_4='=>''], 'newrelic_record_custom_event' => ['void', 'name'=>'string', 'attributes'=>'array'], 'newrelic_record_datastore_segment' => ['mixed', 'func'=>'callable', 'parameters'=>'array'], 'newrelic_set_appname' => ['bool', 'name'=>'string', 'license='=>'string', 'xmit='=>'bool'], 'newrelic_set_user_attributes' => ['bool', 'user'=>'string', 'account'=>'string', 'product'=>'string'], 'newrelic_start_transaction' => ['bool', 'appname'=>'string', 'license='=>'string'], 'newt_bell' => ['void'], 'newt_button' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string'], 'newt_button_bar' => ['resource', 'buttons'=>'array'], 'newt_centered_window' => ['int', 'width'=>'int', 'height'=>'int', 'title='=>'string'], 'newt_checkbox' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string', 'def_value'=>'string', 'seq='=>'string'], 'newt_checkbox_get_value' => ['string', 'checkbox'=>'resource'], 'newt_checkbox_set_flags' => ['void', 'checkbox'=>'resource', 'flags'=>'int', 'sense'=>'int'], 'newt_checkbox_set_value' => ['void', 'checkbox'=>'resource', 'value'=>'string'], 'newt_checkbox_tree' => ['resource', 'left'=>'int', 'top'=>'int', 'height'=>'int', 'flags='=>'int'], 'newt_checkbox_tree_add_item' => ['void', 'checkboxtree'=>'resource', 'text'=>'string', 'data'=>'mixed', 'flags'=>'int', 'index'=>'int', '...args='=>'int'], 'newt_checkbox_tree_find_item' => ['array', 'checkboxtree'=>'resource', 'data'=>'mixed'], 'newt_checkbox_tree_get_current' => ['mixed', 'checkboxtree'=>'resource'], 'newt_checkbox_tree_get_entry_value' => ['string', 'checkboxtree'=>'resource', 'data'=>'mixed'], 'newt_checkbox_tree_get_multi_selection' => ['array', 'checkboxtree'=>'resource', 'seqnum'=>'string'], 'newt_checkbox_tree_get_selection' => ['array', 'checkboxtree'=>'resource'], 'newt_checkbox_tree_multi' => ['resource', 'left'=>'int', 'top'=>'int', 'height'=>'int', 'seq'=>'string', 'flags='=>'int'], 'newt_checkbox_tree_set_current' => ['void', 'checkboxtree'=>'resource', 'data'=>'mixed'], 'newt_checkbox_tree_set_entry' => ['void', 'checkboxtree'=>'resource', 'data'=>'mixed', 'text'=>'string'], 'newt_checkbox_tree_set_entry_value' => ['void', 'checkboxtree'=>'resource', 'data'=>'mixed', 'value'=>'string'], 'newt_checkbox_tree_set_width' => ['void', 'checkbox_tree'=>'resource', 'width'=>'int'], 'newt_clear_key_buffer' => ['void'], 'newt_cls' => ['void'], 'newt_compact_button' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string'], 'newt_component_add_callback' => ['void', 'component'=>'resource', 'func_name'=>'mixed', 'data'=>'mixed'], 'newt_component_takes_focus' => ['void', 'component'=>'resource', 'takes_focus'=>'bool'], 'newt_create_grid' => ['resource', 'cols'=>'int', 'rows'=>'int'], 'newt_cursor_off' => ['void'], 'newt_cursor_on' => ['void'], 'newt_delay' => ['void', 'microseconds'=>'int'], 'newt_draw_form' => ['void', 'form'=>'resource'], 'newt_draw_root_text' => ['void', 'left'=>'int', 'top'=>'int', 'text'=>'string'], 'newt_entry' => ['resource', 'left'=>'int', 'top'=>'int', 'width'=>'int', 'init_value='=>'string', 'flags='=>'int'], 'newt_entry_get_value' => ['string', 'entry'=>'resource'], 'newt_entry_set' => ['void', 'entry'=>'resource', 'value'=>'string', 'cursor_at_end='=>'bool'], 'newt_entry_set_filter' => ['void', 'entry'=>'resource', 'filter'=>'callable', 'data'=>'mixed'], 'newt_entry_set_flags' => ['void', 'entry'=>'resource', 'flags'=>'int', 'sense'=>'int'], 'newt_finished' => ['int'], 'newt_form' => ['resource', 'vert_bar='=>'resource', 'help='=>'string', 'flags='=>'int'], 'newt_form_add_component' => ['void', 'form'=>'resource', 'component'=>'resource'], 'newt_form_add_components' => ['void', 'form'=>'resource', 'components'=>'array'], 'newt_form_add_hot_key' => ['void', 'form'=>'resource', 'key'=>'int'], 'newt_form_destroy' => ['void', 'form'=>'resource'], 'newt_form_get_current' => ['resource', 'form'=>'resource'], 'newt_form_run' => ['void', 'form'=>'resource', 'exit_struct'=>'array'], 'newt_form_set_background' => ['void', 'from'=>'resource', 'background'=>'int'], 'newt_form_set_height' => ['void', 'form'=>'resource', 'height'=>'int'], 'newt_form_set_size' => ['void', 'form'=>'resource'], 'newt_form_set_timer' => ['void', 'form'=>'resource', 'milliseconds'=>'int'], 'newt_form_set_width' => ['void', 'form'=>'resource', 'width'=>'int'], 'newt_form_watch_fd' => ['void', 'form'=>'resource', 'stream'=>'resource', 'flags='=>'int'], 'newt_get_screen_size' => ['void', 'cols'=>'int', 'rows'=>'int'], 'newt_grid_add_components_to_form' => ['void', 'grid'=>'resource', 'form'=>'resource', 'recurse'=>'bool'], 'newt_grid_basic_window' => ['resource', 'text'=>'resource', 'middle'=>'resource', 'buttons'=>'resource'], 'newt_grid_free' => ['void', 'grid'=>'resource', 'recurse'=>'bool'], 'newt_grid_get_size' => ['void', 'grid'=>'resource', 'width'=>'int', 'height'=>'int'], 'newt_grid_h_close_stacked' => ['resource', 'element1_type'=>'int', 'element1'=>'resource', '...args='=>'resource'], 'newt_grid_h_stacked' => ['resource', 'element1_type'=>'int', 'element1'=>'resource', '...args='=>'resource'], 'newt_grid_place' => ['void', 'grid'=>'resource', 'left'=>'int', 'top'=>'int'], 'newt_grid_set_field' => ['void', 'grid'=>'resource', 'col'=>'int', 'row'=>'int', 'type'=>'int', 'value'=>'resource', 'pad_left'=>'int', 'pad_top'=>'int', 'pad_right'=>'int', 'pad_bottom'=>'int', 'anchor'=>'int', 'flags='=>'int'], 'newt_grid_simple_window' => ['resource', 'text'=>'resource', 'middle'=>'resource', 'buttons'=>'resource'], 'newt_grid_v_close_stacked' => ['resource', 'element1_type'=>'int', 'element1'=>'resource', '...args='=>'resource'], 'newt_grid_v_stacked' => ['resource', 'element1_type'=>'int', 'element1'=>'resource', '...args='=>'resource'], 'newt_grid_wrapped_window' => ['void', 'grid'=>'resource', 'title'=>'string'], 'newt_grid_wrapped_window_at' => ['void', 'grid'=>'resource', 'title'=>'string', 'left'=>'int', 'top'=>'int'], 'newt_init' => ['int'], 'newt_label' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string'], 'newt_label_set_text' => ['void', 'label'=>'resource', 'text'=>'string'], 'newt_listbox' => ['resource', 'left'=>'int', 'top'=>'int', 'height'=>'int', 'flags='=>'int'], 'newt_listbox_append_entry' => ['void', 'listbox'=>'resource', 'text'=>'string', 'data'=>'mixed'], 'newt_listbox_clear' => ['void', 'listobx'=>'resource'], 'newt_listbox_clear_selection' => ['void', 'listbox'=>'resource'], 'newt_listbox_delete_entry' => ['void', 'listbox'=>'resource', 'key'=>'mixed'], 'newt_listbox_get_current' => ['string', 'listbox'=>'resource'], 'newt_listbox_get_selection' => ['array', 'listbox'=>'resource'], 'newt_listbox_insert_entry' => ['void', 'listbox'=>'resource', 'text'=>'string', 'data'=>'mixed', 'key'=>'mixed'], 'newt_listbox_item_count' => ['int', 'listbox'=>'resource'], 'newt_listbox_select_item' => ['void', 'listbox'=>'resource', 'key'=>'mixed', 'sense'=>'int'], 'newt_listbox_set_current' => ['void', 'listbox'=>'resource', 'num'=>'int'], 'newt_listbox_set_current_by_key' => ['void', 'listbox'=>'resource', 'key'=>'mixed'], 'newt_listbox_set_data' => ['void', 'listbox'=>'resource', 'num'=>'int', 'data'=>'mixed'], 'newt_listbox_set_entry' => ['void', 'listbox'=>'resource', 'num'=>'int', 'text'=>'string'], 'newt_listbox_set_width' => ['void', 'listbox'=>'resource', 'width'=>'int'], 'newt_listitem' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string', 'is_default'=>'bool', 'prev_item'=>'resource', 'data'=>'mixed', 'flags='=>'int'], 'newt_listitem_get_data' => ['mixed', 'item'=>'resource'], 'newt_listitem_set' => ['void', 'item'=>'resource', 'text'=>'string'], 'newt_open_window' => ['int', 'left'=>'int', 'top'=>'int', 'width'=>'int', 'height'=>'int', 'title='=>'string'], 'newt_pop_help_line' => ['void'], 'newt_pop_window' => ['void'], 'newt_push_help_line' => ['void', 'text='=>'string'], 'newt_radio_get_current' => ['resource', 'set_member'=>'resource'], 'newt_radiobutton' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string', 'is_default'=>'bool', 'prev_button='=>'resource'], 'newt_redraw_help_line' => ['void'], 'newt_reflow_text' => ['string', 'text'=>'string', 'width'=>'int', 'flex_down'=>'int', 'flex_up'=>'int', 'actual_width'=>'int', 'actual_height'=>'int'], 'newt_refresh' => ['void'], 'newt_resize_screen' => ['void', 'redraw='=>'bool'], 'newt_resume' => ['void'], 'newt_run_form' => ['resource', 'form'=>'resource'], 'newt_scale' => ['resource', 'left'=>'int', 'top'=>'int', 'width'=>'int', 'full_value'=>'int'], 'newt_scale_set' => ['void', 'scale'=>'resource', 'amount'=>'int'], 'newt_scrollbar_set' => ['void', 'scrollbar'=>'resource', 'where'=>'int', 'total'=>'int'], 'newt_set_help_callback' => ['void', 'function'=>'mixed'], 'newt_set_suspend_callback' => ['void', 'function'=>'callable', 'data'=>'mixed'], 'newt_suspend' => ['void'], 'newt_textbox' => ['resource', 'left'=>'int', 'top'=>'int', 'width'=>'int', 'height'=>'int', 'flags='=>'int'], 'newt_textbox_get_num_lines' => ['int', 'textbox'=>'resource'], 'newt_textbox_reflowed' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'char', 'width'=>'int', 'flex_down'=>'int', 'flex_up'=>'int', 'flags='=>'int'], 'newt_textbox_set_height' => ['void', 'textbox'=>'resource', 'height'=>'int'], 'newt_textbox_set_text' => ['void', 'textbox'=>'resource', 'text'=>'string'], 'newt_vertical_scrollbar' => ['resource', 'left'=>'int', 'top'=>'int', 'height'=>'int', 'normal_colorset='=>'int', 'thumb_colorset='=>'int'], 'newt_wait_for_key' => ['void'], 'newt_win_choice' => ['int', 'title'=>'string', 'button1_text'=>'string', 'button2_text'=>'string', 'format'=>'string', 'args='=>'mixed', '...args='=>'mixed'], 'newt_win_entries' => ['int', 'title'=>'string', 'text'=>'string', 'suggested_width'=>'int', 'flex_down'=>'int', 'flex_up'=>'int', 'data_width'=>'int', 'items'=>'array', 'button1'=>'string', '...args='=>'string'], 'newt_win_menu' => ['int', 'title'=>'string', 'text'=>'string', 'suggestedwidth'=>'int', 'flexdown'=>'int', 'flexup'=>'int', 'maxlistheight'=>'int', 'items'=>'array', 'listitem'=>'int', 'button1='=>'string', '...args='=>'string'], 'newt_win_message' => ['void', 'title'=>'string', 'button_text'=>'string', 'format'=>'string', 'args='=>'mixed', '...args='=>'mixed'], 'newt_win_messagev' => ['void', 'title'=>'string', 'button_text'=>'string', 'format'=>'string', 'args'=>'array'], 'newt_win_ternary' => ['int', 'title'=>'string', 'button1_text'=>'string', 'button2_text'=>'string', 'button3_text'=>'string', 'format'=>'string', 'args='=>'mixed', '...args='=>'mixed'], 'next' => ['mixed', '&r_array'=>'array|object'], 'ngettext' => ['string', 'msgid1'=>'string', 'msgid2'=>'string', 'n'=>'int'], 'nl2br' => ['string', 'string'=>'string', 'is_xhtml='=>'bool'], 'nl_langinfo' => ['string|false', 'item'=>'int'], 'NoRewindIterator::__construct' => ['void', 'iterator'=>'Iterator'], 'NoRewindIterator::current' => ['mixed'], 'NoRewindIterator::getInnerIterator' => ['Iterator'], 'NoRewindIterator::key' => ['mixed'], 'NoRewindIterator::next' => ['void'], 'NoRewindIterator::rewind' => ['void'], 'NoRewindIterator::valid' => ['bool'], 'Normalizer::getRawDecomposition' => ['string|null', 'input'=>'string'], 'Normalizer::isNormalized' => ['bool', 'input'=>'string', 'form='=>'int'], 'Normalizer::normalize' => ['string', 'input'=>'string', 'form='=>'int'], 'normalizer_get_raw_decomposition' => ['string|null', 'input'=>'string'], 'normalizer_is_normalized' => ['bool', 'input'=>'string', 'form='=>'int'], 'normalizer_normalize' => ['string', 'input'=>'string', 'form='=>'int'], 'notes_body' => ['array', 'server'=>'string', 'mailbox'=>'string', 'msg_number'=>'int'], 'notes_copy_db' => ['bool', 'from_database_name'=>'string', 'to_database_name'=>'string'], 'notes_create_db' => ['bool', 'database_name'=>'string'], 'notes_create_note' => ['bool', 'database_name'=>'string', 'form_name'=>'string'], 'notes_drop_db' => ['bool', 'database_name'=>'string'], 'notes_find_note' => ['int', 'database_name'=>'string', 'name'=>'string', 'type='=>'string'], 'notes_header_info' => ['object', 'server'=>'string', 'mailbox'=>'string', 'msg_number'=>'int'], 'notes_list_msgs' => ['bool', 'db'=>'string'], 'notes_mark_read' => ['bool', 'database_name'=>'string', 'user_name'=>'string', 'note_id'=>'string'], 'notes_mark_unread' => ['bool', 'database_name'=>'string', 'user_name'=>'string', 'note_id'=>'string'], 'notes_nav_create' => ['bool', 'database_name'=>'string', 'name'=>'string'], 'notes_search' => ['array', 'database_name'=>'string', 'keywords'=>'string'], 'notes_unread' => ['array', 'database_name'=>'string', 'user_name'=>'string'], 'notes_version' => ['float', 'database_name'=>'string'], 'nsapi_request_headers' => ['array'], 'nsapi_response_headers' => ['array'], 'nsapi_virtual' => ['bool', 'uri'=>'string'], 'nthmac' => ['string', 'clent'=>'string', 'data'=>'string'], 'number_format' => ['string', 'number'=>'float|int', 'num_decimal_places='=>'int'], 'number_format\'1' => ['string', 'number'=>'float|int', 'num_decimal_places'=>'int', 'dec_separator'=>'string', 'thousands_separator'=>'string'], 'NumberFormatter::__construct' => ['void', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'], 'NumberFormatter::create' => ['NumberFormatter|false', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'], 'NumberFormatter::format' => ['string|false', 'num'=>'', 'type='=>'int'], 'NumberFormatter::formatCurrency' => ['string', 'num'=>'float', 'currency'=>'string'], 'NumberFormatter::getAttribute' => ['int|false', 'attr'=>'int'], 'NumberFormatter::getErrorCode' => ['int'], 'NumberFormatter::getErrorMessage' => ['string'], 'NumberFormatter::getLocale' => ['string', 'type='=>'int'], 'NumberFormatter::getPattern' => ['string|false'], 'NumberFormatter::getSymbol' => ['string|false', 'attr'=>'int'], 'NumberFormatter::getTextAttribute' => ['string|false', 'attr'=>'int'], 'NumberFormatter::parse' => ['float|false', 'string'=>'string', 'type='=>'int', '&rw_position='=>'int'], 'NumberFormatter::parseCurrency' => ['float|false', 'string'=>'string', '&w_currency'=>'string', '&rw_position='=>'int'], 'NumberFormatter::setAttribute' => ['bool', 'attr'=>'int', 'value'=>''], 'NumberFormatter::setPattern' => ['bool', 'pattern'=>'string'], 'NumberFormatter::setSymbol' => ['bool', 'attr'=>'int', 'symbol'=>'string'], 'NumberFormatter::setTextAttribute' => ['bool', 'attr'=>'int', 'value'=>'string'], 'numfmt_create' => ['NumberFormatter|false', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'], 'numfmt_format' => ['string|false', 'fmt'=>'NumberFormatter', 'value'=>'int|float', 'type='=>'int'], 'numfmt_format_currency' => ['string|false', 'fmt'=>'NumberFormatter', 'value'=>'float', 'currency'=>'string'], 'numfmt_get_attribute' => ['int|false', 'fmt'=>'NumberFormatter', 'attr'=>'int'], 'numfmt_get_error_code' => ['int', 'fmt'=>'NumberFormatter'], 'numfmt_get_error_message' => ['string', 'fmt'=>'NumberFormatter'], 'numfmt_get_locale' => ['string', 'fmt'=>'NumberFormatter', 'type='=>'int'], 'numfmt_get_pattern' => ['string|false', 'fmt'=>'NumberFormatter'], 'numfmt_get_symbol' => ['string|false', 'fmt'=>'NumberFormatter', 'attr'=>'int'], 'numfmt_get_text_attribute' => ['string|false', 'fmt'=>'NumberFormatter', 'attr'=>'int'], 'numfmt_parse' => ['float|int|false', 'fmt'=>'NumberFormatter', 'value'=>'string', 'type='=>'int', '&rw_position='=>'int'], 'numfmt_parse_currency' => ['float|false', 'fmt'=>'NumberFormatter', 'value'=>'string', '&w_currency'=>'string', '&rw_position='=>'int'], 'numfmt_set_attribute' => ['bool', 'fmt'=>'NumberFormatter', 'attr'=>'int', 'value'=>'int'], 'numfmt_set_pattern' => ['bool', 'fmt'=>'NumberFormatter', 'pattern'=>'string'], 'numfmt_set_symbol' => ['bool', 'fmt'=>'NumberFormatter', 'attr'=>'int', 'value'=>'string'], 'numfmt_set_text_attribute' => ['bool', 'fmt'=>'NumberFormatter', 'attr'=>'int', 'value'=>'string'], 'OAuth::__construct' => ['void', 'consumer_key'=>'string', 'consumer_secret'=>'string', 'signature_method='=>'string', 'auth_type='=>'int'], 'OAuth::__destruct' => ['void'], 'OAuth::disableDebug' => ['bool'], 'OAuth::disableRedirects' => ['bool'], 'OAuth::disableSSLChecks' => ['bool'], 'OAuth::enableDebug' => ['bool'], 'OAuth::enableRedirects' => ['bool'], 'OAuth::enableSSLChecks' => ['bool'], 'OAuth::fetch' => ['mixed', 'protected_resource_url'=>'string', 'extra_parameters='=>'array', 'http_method='=>'string', 'http_headers='=>'array'], 'OAuth::generateSignature' => ['string', 'http_method'=>'string', 'url'=>'string', 'extra_parameters='=>'mixed'], 'OAuth::getAccessToken' => ['array|false', 'access_token_url'=>'string', 'auth_session_handle='=>'string', 'verifier_token='=>'string', 'http_method='=>'string'], 'OAuth::getCAPath' => ['array'], 'OAuth::getLastResponse' => ['string'], 'OAuth::getLastResponseHeaders' => ['string|false'], 'OAuth::getLastResponseInfo' => ['array'], 'OAuth::getRequestHeader' => ['string|false', 'http_method'=>'string', 'url'=>'string', 'extra_parameters='=>'mixed'], 'OAuth::getRequestToken' => ['array|false', 'request_token_url'=>'string', 'callback_url='=>'string', 'http_method='=>'string'], 'OAuth::setAuthType' => ['bool', 'auth_type'=>'int'], 'OAuth::setCAPath' => ['mixed', 'ca_path='=>'string', 'ca_info='=>'string'], 'OAuth::setNonce' => ['mixed', 'nonce'=>'string'], 'OAuth::setRequestEngine' => ['void', 'reqengine'=>'int'], 'OAuth::setRSACertificate' => ['mixed', 'cert'=>'string'], 'OAuth::setSSLChecks' => ['bool', 'sslcheck'=>'int'], 'OAuth::setTimeout' => ['void', 'timeout'=>'int'], 'OAuth::setTimestamp' => ['mixed', 'timestamp'=>'string'], 'OAuth::setToken' => ['bool', 'token'=>'string', 'token_secret'=>'string'], 'OAuth::setVersion' => ['bool', 'version'=>'string'], 'oauth_get_sbs' => ['string', 'http_method'=>'string', 'uri'=>'string', 'request_parameters='=>'array'], 'oauth_urlencode' => ['string', 'uri'=>'string'], 'OAuthProvider::__construct' => ['void', 'params_array='=>'array'], 'OAuthProvider::addRequiredParameter' => ['bool', 'req_params'=>'string'], 'OAuthProvider::callconsumerHandler' => ['void'], 'OAuthProvider::callTimestampNonceHandler' => ['void'], 'OAuthProvider::calltokenHandler' => ['void'], 'OAuthProvider::checkOAuthRequest' => ['void', 'uri='=>'string', 'method='=>'string'], 'OAuthProvider::consumerHandler' => ['void', 'callback_function'=>'callable'], 'OAuthProvider::generateToken' => ['string', 'size'=>'int', 'strong='=>'bool'], 'OAuthProvider::is2LeggedEndpoint' => ['void', 'params_array'=>'mixed'], 'OAuthProvider::isRequestTokenEndpoint' => ['void', 'will_issue_request_token'=>'bool'], 'OAuthProvider::removeRequiredParameter' => ['bool', 'req_params'=>'string'], 'OAuthProvider::reportProblem' => ['string', 'oauthexception'=>'string', 'send_headers='=>'bool'], 'OAuthProvider::setParam' => ['bool', 'param_key'=>'string', 'param_val='=>'mixed'], 'OAuthProvider::setRequestTokenPath' => ['bool', 'path'=>'string'], 'OAuthProvider::timestampNonceHandler' => ['void', 'callback_function'=>'callable'], 'OAuthProvider::tokenHandler' => ['void', 'callback_function'=>'callable'], 'ob_clean' => ['bool'], 'ob_deflatehandler' => ['string', 'data'=>'string', 'mode'=>'int'], 'ob_end_clean' => ['bool'], 'ob_end_flush' => ['bool'], 'ob_etaghandler' => ['string', 'data'=>'string', 'mode'=>'int'], 'ob_flush' => ['bool'], 'ob_get_clean' => ['string|false'], 'ob_get_contents' => ['string|false'], 'ob_get_flush' => ['string|false'], 'ob_get_length' => ['int|false'], 'ob_get_level' => ['int'], 'ob_get_status' => ['array', 'full_status='=>'bool'], 'ob_gzhandler' => ['string|false', 'data'=>'string', 'flags'=>'int'], 'ob_iconv_handler' => ['string', 'contents'=>'string', 'status'=>'int'], 'ob_implicit_flush' => ['void', 'flag='=>'int'], 'ob_inflatehandler' => ['string', 'data'=>'string', 'mode'=>'int'], 'ob_list_handlers' => ['false|list'], 'ob_start' => ['bool', 'user_function='=>'string|array|?callable', 'chunk_size='=>'int', 'flags='=>'int'], 'ob_tidyhandler' => ['string', 'input'=>'string', 'mode='=>'int'], 'oci_bind_array_by_name' => ['bool', 'stmt'=>'resource', 'name'=>'string', '&rw_var'=>'array', 'max_table_length'=>'int', 'max_item_length='=>'int', 'type='=>'int'], 'oci_bind_by_name' => ['bool', 'stmt'=>'resource', 'name'=>'string', '&rw_var'=>'mixed', 'maxlength='=>'int', 'type='=>'int'], 'oci_cancel' => ['bool', 'stmt'=>'resource'], 'oci_client_version' => ['string'], 'oci_close' => ['bool', 'connection'=>'resource'], 'OCI_Collection::append' => ['bool', 'value'=>'mixed'], 'OCI_Collection::assign' => ['bool', 'from'=>'OCI_Collection'], 'OCI_Collection::assignElem' => ['bool', 'index'=>'int', 'value'=>'mixed'], 'OCI_Collection::free' => ['bool'], 'OCI_Collection::getElem' => ['mixed', 'index'=>'int'], 'OCI_Collection::max' => ['int|false'], 'OCI_Collection::size' => ['int|false'], 'OCI_Collection::trim' => ['bool', 'num'=>'int'], 'oci_collection_append' => ['bool', 'value'=>'string'], 'oci_collection_assign' => ['bool', 'from'=>'object'], 'oci_collection_element_assign' => ['bool', 'index'=>'int', 'value'=>'string'], 'oci_collection_element_get' => ['string', 'ndx'=>'int'], 'oci_collection_max' => ['int'], 'oci_collection_size' => ['int'], 'oci_collection_trim' => ['bool', 'num'=>'int'], 'oci_commit' => ['bool', 'connection'=>'resource'], 'oci_connect' => ['resource|false', 'user'=>'string', 'pass'=>'string', 'db='=>'string', 'charset='=>'string', 'session_mode='=>'int'], 'oci_define_by_name' => ['bool', 'stmt'=>'resource', 'name'=>'string', '&w_var'=>'mixed', 'type='=>'int'], 'oci_error' => ['array|false', 'resource='=>'resource'], 'oci_execute' => ['bool', 'stmt'=>'resource', 'mode='=>'int'], 'oci_fetch' => ['bool', 'stmt'=>'resource'], 'oci_fetch_all' => ['int|false', 'stmt'=>'resource', '&w_output'=>'array', 'skip='=>'int', 'maxrows='=>'int', 'flags='=>'int'], 'oci_fetch_array' => ['array|false', 'stmt'=>'resource', 'mode='=>'int'], 'oci_fetch_assoc' => ['array|false', 'stmt'=>'resource'], 'oci_fetch_object' => ['object|false', 'stmt'=>'resource'], 'oci_fetch_row' => ['array|false', 'stmt'=>'resource'], 'oci_field_is_null' => ['bool', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_name' => ['string|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_precision' => ['int|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_scale' => ['int|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_size' => ['int|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_type' => ['mixed|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_type_raw' => ['int|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_free_collection' => ['bool'], 'oci_free_cursor' => ['bool', 'stmt'=>'resource'], 'oci_free_descriptor' => ['bool'], 'oci_free_statement' => ['bool', 'stmt'=>'resource'], 'oci_get_implicit' => ['bool', 'stmt'=>''], 'oci_get_implicit_resultset' => ['resource|false', 'statement'=>'resource'], 'oci_internal_debug' => ['void', 'onoff'=>'bool'], 'OCI_Lob::append' => ['bool', 'lob_from'=>'OCI_Lob'], 'OCI_Lob::close' => ['bool'], 'OCI_Lob::eof' => ['bool'], 'OCI_Lob::erase' => ['int|false', 'offset='=>'int', 'length='=>'int'], 'OCI_Lob::export' => ['bool', 'filename'=>'string', 'start='=>'int', 'length='=>'int'], 'OCI_Lob::flush' => ['bool', 'flag='=>'int'], 'OCI_Lob::free' => ['bool'], 'OCI_Lob::getbuffering' => ['bool'], 'OCI_Lob::import' => ['bool', 'filename'=>'string'], 'OCI_Lob::load' => ['string|false'], 'OCI_Lob::read' => ['string|false', 'length'=>'int'], 'OCI_Lob::rewind' => ['bool'], 'OCI_Lob::save' => ['bool', 'data'=>'string', 'offset='=>'int'], 'OCI_Lob::savefile' => ['bool', 'filename'=>''], 'OCI_Lob::seek' => ['bool', 'offset'=>'int', 'whence='=>'int'], 'OCI_Lob::setbuffering' => ['bool', 'on_off'=>'bool'], 'OCI_Lob::size' => ['int|false'], 'OCI_Lob::tell' => ['int|false'], 'OCI_Lob::truncate' => ['bool', 'length='=>'int'], 'OCI_Lob::write' => ['int|false', 'data'=>'string', 'length='=>'int'], 'OCI_Lob::writeTemporary' => ['bool', 'data'=>'string', 'lob_type='=>'int'], 'OCI_Lob::writetofile' => ['bool', 'filename'=>'', 'start'=>'', 'length'=>''], 'oci_lob_append' => ['bool', 'lob'=>'object'], 'oci_lob_close' => ['bool'], 'oci_lob_copy' => ['bool', 'lob_to'=>'OCI_Lob', 'lob_from'=>'OCI_Lob', 'length='=>'int'], 'oci_lob_eof' => ['bool'], 'oci_lob_erase' => ['int', 'offset'=>'int', 'length'=>'int'], 'oci_lob_export' => ['bool', 'filename'=>'string', 'start'=>'int', 'length'=>'int'], 'oci_lob_flush' => ['bool', 'flag'=>'int'], 'oci_lob_import' => ['bool', 'filename'=>'string'], 'oci_lob_is_equal' => ['bool', 'lob1'=>'OCI_Lob', 'lob2'=>'OCI_Lob'], 'oci_lob_load' => ['string'], 'oci_lob_read' => ['string', 'length'=>'int'], 'oci_lob_rewind' => ['bool'], 'oci_lob_save' => ['bool', 'data'=>'string', 'offset'=>'int'], 'oci_lob_seek' => ['bool', 'offset'=>'int', 'whence'=>'int'], 'oci_lob_size' => ['int'], 'oci_lob_tell' => ['int'], 'oci_lob_truncate' => ['bool', 'length'=>'int'], 'oci_lob_write' => ['int', 'string'=>'string', 'length'=>'int'], 'oci_lob_write_temporary' => ['bool', 'value'=>'string', 'lob_type'=>'int'], 'oci_new_collection' => ['OCI_Collection|false', 'connection'=>'resource', 'tdo'=>'string', 'schema='=>'string'], 'oci_new_connect' => ['resource|false', 'user'=>'string', 'pass'=>'string', 'db='=>'string', 'charset='=>'string', 'session_mode='=>'int'], 'oci_new_cursor' => ['resource|false', 'connection'=>'resource'], 'oci_new_descriptor' => ['OCI_Lob|false', 'connection'=>'resource', 'type='=>'int'], 'oci_num_fields' => ['int|false', 'stmt'=>'resource'], 'oci_num_rows' => ['int|false', 'stmt'=>'resource'], 'oci_parse' => ['resource|false', 'connection'=>'resource', 'statement'=>'string'], 'oci_password_change' => ['bool', 'connection'=>'resource', 'username'=>'string', 'old_password'=>'string', 'new_password'=>'string'], 'oci_pconnect' => ['resource|false', 'user'=>'string', 'pass'=>'string', 'db='=>'string', 'charset='=>'string', 'session_mode='=>'int'], 'oci_register_taf_callback' => ['bool', 'connection'=>'resource', 'callback='=>'callable'], 'oci_result' => ['mixed|false', 'stmt'=>'resource', 'column'=>'mixed'], 'oci_rollback' => ['bool', 'connection'=>'resource'], 'oci_server_version' => ['string|false', 'connection'=>'resource'], 'oci_set_action' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_call_timeout' => ['bool', 'connection'=>'resource', 'time_out'=>'int'], 'oci_set_client_identifier' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_client_info' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_db_operation' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_edition' => ['bool', 'value'=>'string'], 'oci_set_module_name' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_prefetch' => ['bool', 'stmt'=>'resource', 'prefetch_rows'=>'int'], 'oci_statement_type' => ['string|false', 'stmt'=>'resource'], 'oci_unregister_taf_callback' => ['bool', 'connection'=>'resource'], 'ocifetchinto' => ['int|bool', 'stmt'=>'resource', '&w_output'=>'array', 'mode='=>'int'], 'ocigetbufferinglob' => ['bool'], 'ocisetbufferinglob' => ['bool', 'flag'=>'bool'], 'octdec' => ['int|float', 'octal_number'=>'string'], 'odbc_autocommit' => ['mixed', 'connection_id'=>'resource', 'onoff='=>'bool'], 'odbc_binmode' => ['bool', 'result_id'=>'resource', 'mode'=>'int'], 'odbc_close' => ['void', 'connection_id'=>'resource'], 'odbc_close_all' => ['void'], 'odbc_columnprivileges' => ['resource|false', 'connection_id'=>'resource', 'catalog'=>'string', 'schema'=>'string', 'table'=>'string', 'column'=>'string'], 'odbc_columns' => ['resource|false', 'connection_id'=>'resource', 'qualifier='=>'string', 'owner='=>'string', 'table_name='=>'string', 'column_name='=>'string'], 'odbc_commit' => ['bool', 'connection_id'=>'resource'], 'odbc_connect' => ['resource|false', 'dsn'=>'string', 'user'=>'string', 'password'=>'string', 'cursor_option='=>'int'], 'odbc_cursor' => ['string', 'result_id'=>'resource'], 'odbc_data_source' => ['array|false', 'connection_id'=>'resource', 'fetch_type'=>'int'], 'odbc_do' => ['resource', 'connection_id'=>'resource', 'query'=>'string', 'flags='=>'int'], 'odbc_error' => ['string', 'connection_id='=>'resource'], 'odbc_errormsg' => ['string', 'connection_id='=>'resource'], 'odbc_exec' => ['resource', 'connection_id'=>'resource', 'query'=>'string', 'flags='=>'int'], 'odbc_execute' => ['bool', 'result_id'=>'resource', 'parameters_array='=>'array'], 'odbc_fetch_array' => ['array|false', 'result'=>'resource', 'rownumber='=>'int'], 'odbc_fetch_into' => ['int', 'result_id'=>'resource', '&w_result_array'=>'array', 'rownumber='=>'int'], 'odbc_fetch_object' => ['object|false', 'result'=>'resource', 'rownumber='=>'int'], 'odbc_fetch_row' => ['bool', 'result_id'=>'resource', 'row_number='=>'int'], 'odbc_field_len' => ['int|false', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_field_name' => ['string|false', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_field_num' => ['int|false', 'result_id'=>'resource', 'field_name'=>'string'], 'odbc_field_precision' => ['int', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_field_scale' => ['int|false', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_field_type' => ['string|false', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_foreignkeys' => ['resource|false', 'connection_id'=>'resource', 'pk_qualifier'=>'string', 'pk_owner'=>'string', 'pk_table'=>'string', 'fk_qualifier'=>'string', 'fk_owner'=>'string', 'fk_table'=>'string'], 'odbc_free_result' => ['bool', 'result_id'=>'resource'], 'odbc_gettypeinfo' => ['resource', 'connection_id'=>'resource', 'data_type='=>'int'], 'odbc_longreadlen' => ['bool', 'result_id'=>'resource', 'length'=>'int'], 'odbc_next_result' => ['bool', 'result_id'=>'resource'], 'odbc_num_fields' => ['int', 'result_id'=>'resource'], 'odbc_num_rows' => ['int', 'result_id'=>'resource'], 'odbc_pconnect' => ['resource|false', 'dsn'=>'string', 'user'=>'string', 'password'=>'string', 'cursor_option='=>'int'], 'odbc_prepare' => ['resource|false', 'connection_id'=>'resource', 'query'=>'string'], 'odbc_primarykeys' => ['resource|false', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'table'=>'string'], 'odbc_procedurecolumns' => ['resource|false', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'proc'=>'string', 'column'=>'string'], 'odbc_procedures' => ['resource|false', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'name'=>'string'], 'odbc_result' => ['mixed|false', 'result_id'=>'resource', 'field'=>'mixed'], 'odbc_result_all' => ['int|false', 'result_id'=>'resource', 'format='=>'string'], 'odbc_rollback' => ['bool', 'connection_id'=>'resource'], 'odbc_setoption' => ['bool', 'result_id'=>'resource', 'which'=>'int', 'option'=>'int', 'value'=>'int'], 'odbc_specialcolumns' => ['resource|false', 'connection_id'=>'resource', 'type'=>'int', 'qualifier'=>'string', 'owner'=>'string', 'table'=>'string', 'scope'=>'int', 'nullable'=>'int'], 'odbc_statistics' => ['resource|false', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'name'=>'string', 'unique'=>'int', 'accuracy'=>'int'], 'odbc_tableprivileges' => ['resource|false', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'name'=>'string'], 'odbc_tables' => ['resource|false', 'connection_id'=>'resource', 'qualifier='=>'string', 'owner='=>'string', 'name='=>'string', 'table_types='=>'string'], 'opcache_compile_file' => ['bool', 'file'=>'string'], 'opcache_get_configuration' => ['array'], 'opcache_get_status' => ['array|false', 'get_scripts='=>'bool'], 'opcache_invalidate' => ['bool', 'script'=>'string', 'force='=>'bool'], 'opcache_is_script_cached' => ['bool', 'script'=>'string'], 'opcache_reset' => ['bool'], 'openal_buffer_create' => ['resource'], 'openal_buffer_data' => ['bool', 'buffer'=>'resource', 'format'=>'int', 'data'=>'string', 'freq'=>'int'], 'openal_buffer_destroy' => ['bool', 'buffer'=>'resource'], 'openal_buffer_get' => ['int', 'buffer'=>'resource', 'property'=>'int'], 'openal_buffer_loadwav' => ['bool', 'buffer'=>'resource', 'wavfile'=>'string'], 'openal_context_create' => ['resource', 'device'=>'resource'], 'openal_context_current' => ['bool', 'context'=>'resource'], 'openal_context_destroy' => ['bool', 'context'=>'resource'], 'openal_context_process' => ['bool', 'context'=>'resource'], 'openal_context_suspend' => ['bool', 'context'=>'resource'], 'openal_device_close' => ['bool', 'device'=>'resource'], 'openal_device_open' => ['resource|false', 'device_desc='=>'string'], 'openal_listener_get' => ['mixed', 'property'=>'int'], 'openal_listener_set' => ['bool', 'property'=>'int', 'setting'=>'mixed'], 'openal_source_create' => ['resource'], 'openal_source_destroy' => ['bool', 'source'=>'resource'], 'openal_source_get' => ['mixed', 'source'=>'resource', 'property'=>'int'], 'openal_source_pause' => ['bool', 'source'=>'resource'], 'openal_source_play' => ['bool', 'source'=>'resource'], 'openal_source_rewind' => ['bool', 'source'=>'resource'], 'openal_source_set' => ['bool', 'source'=>'resource', 'property'=>'int', 'setting'=>'mixed'], 'openal_source_stop' => ['bool', 'source'=>'resource'], 'openal_stream' => ['resource', 'source'=>'resource', 'format'=>'int', 'rate'=>'int'], 'opendir' => ['resource|false', 'path'=>'string', 'context='=>'resource'], 'openlog' => ['bool', 'ident'=>'string', 'option'=>'int', 'facility'=>'int'], 'openssl_cipher_iv_length' => ['int|false', 'method'=>'string'], 'openssl_csr_export' => ['bool', 'csr'=>'string|resource', '&w_out'=>'string', 'notext='=>'bool'], 'openssl_csr_export_to_file' => ['bool', 'csr'=>'string|resource', 'outfilename'=>'string', 'notext='=>'bool'], 'openssl_csr_get_public_key' => ['resource|false', 'csr'=>'string|resource', 'use_shortnames='=>'bool'], 'openssl_csr_get_subject' => ['array|false', 'csr'=>'string|resource', 'use_shortnames='=>'bool'], 'openssl_csr_new' => ['resource|false', 'dn'=>'array', '&w_privkey'=>'resource', 'configargs='=>'array', 'extraattribs='=>'array'], 'openssl_csr_sign' => ['resource|false', 'csr'=>'string|resource', 'x509'=>'string|resource|null', 'priv_key'=>'string|resource|array', 'days'=>'int', 'config_args='=>'array', 'serial='=>'int'], 'openssl_decrypt' => ['string|false', 'data'=>'string', 'method'=>'string', 'key'=>'string', 'options='=>'int', 'iv='=>'string', 'tag='=>'string', 'aad='=>'string'], 'openssl_dh_compute_key' => ['string|false', 'pub_key'=>'string', 'dh_key'=>'resource'], 'openssl_digest' => ['string|false', 'data'=>'string', 'method'=>'string', 'raw_output='=>'bool'], 'openssl_encrypt' => ['string|false', 'data'=>'string', 'method'=>'string', 'key'=>'string', 'options='=>'int', 'iv='=>'string', '&w_tag='=>'string', 'aad='=>'string', 'tag_length='=>'int'], 'openssl_error_string' => ['string|false'], 'openssl_free_key' => ['void', 'key_identifier'=>'resource'], 'openssl_get_cert_locations' => ['array'], 'openssl_get_cipher_methods' => ['array', 'aliases='=>'bool'], 'openssl_get_curve_names' => ['list'], 'openssl_get_md_methods' => ['array', 'aliases='=>'bool'], 'openssl_get_privatekey' => ['resource|false', 'key'=>'string', 'passphrase='=>'string'], 'openssl_get_publickey' => ['resource|false', 'cert'=>'resource|string'], 'openssl_open' => ['bool', 'sealed_data'=>'string', '&w_open_data'=>'string', 'env_key'=>'string', 'priv_key_id'=>'string|array|resource', 'method='=>'string', 'iv='=>'string'], 'openssl_pbkdf2' => ['string|false', 'password'=>'string', 'salt'=>'string', 'key_length'=>'int', 'iterations'=>'int', 'digest_algorithm='=>'string'], 'openssl_pkcs12_export' => ['bool', 'x509'=>'string|resource', '&w_out'=>'string', 'priv_key'=>'string|array|resource', 'pass'=>'string', 'args='=>'array'], 'openssl_pkcs12_export_to_file' => ['bool', 'x509'=>'string|resource', 'filename'=>'string', 'priv_key'=>'string|array|resource', 'pass'=>'string', 'args='=>'array'], 'openssl_pkcs12_read' => ['bool', 'pkcs12'=>'string', '&w_certs'=>'array', 'pass'=>'string'], 'openssl_pkcs7_decrypt' => ['bool', 'infilename'=>'string', 'outfilename'=>'string', 'recipcert'=>'string|resource', 'recipkey='=>'string|resource|array'], 'openssl_pkcs7_encrypt' => ['bool', 'infile'=>'string', 'outfile'=>'string', 'recipcerts'=>'string|resource|array', 'headers'=>'array', 'flags='=>'int', 'cipherid='=>'int'], 'openssl_pkcs7_read' => ['bool', 'infilename'=>'string', '&w_certs'=>'array'], 'openssl_pkcs7_sign' => ['bool', 'infile'=>'string', 'outfile'=>'string', 'signcert'=>'string|resource', 'privkey'=>'string|resource|array', 'headers'=>'array', 'flags='=>'int', 'extracerts='=>'string'], 'openssl_pkcs7_verify' => ['bool|int', 'filename'=>'string', 'flags'=>'int', 'outfilename='=>'string', 'cainfo='=>'array', 'extracerts='=>'string', 'content='=>'string', 'p7bfilename='=>'string'], 'openssl_pkey_derive' => ['string|false', 'peer_pub_key'=>'mixed', 'priv_key'=>'mixed', 'keylen='=>'?int'], 'openssl_pkey_export' => ['bool', 'key'=>'resource', '&w_out'=>'string', 'passphrase='=>'string|null', 'configargs='=>'array'], 'openssl_pkey_export_to_file' => ['bool', 'key'=>'resource|string|array', 'outfilename'=>'string', 'passphrase='=>'string|null', 'configargs='=>'array'], 'openssl_pkey_free' => ['void', 'key'=>'resource'], 'openssl_pkey_get_details' => ['array|false', 'key'=>'resource'], 'openssl_pkey_get_private' => ['resource|false', 'key'=>'string', 'passphrase='=>'string'], 'openssl_pkey_get_public' => ['resource|false', 'certificate'=>'resource|string'], 'openssl_pkey_new' => ['resource|false', 'configargs='=>'array'], 'openssl_private_decrypt' => ['bool', 'data'=>'string', '&w_decrypted'=>'string', 'key'=>'string|resource|array', 'padding='=>'int'], 'openssl_private_encrypt' => ['bool', 'data'=>'string', '&w_crypted'=>'string', 'key'=>'string|resource|array', 'padding='=>'int'], 'openssl_public_decrypt' => ['bool', 'data'=>'string', '&w_decrypted'=>'string', 'key'=>'string|resource', 'padding='=>'int'], 'openssl_public_encrypt' => ['bool', 'data'=>'string', '&w_crypted'=>'string', 'key'=>'string|resource', 'padding='=>'int'], 'openssl_random_pseudo_bytes' => ['string|false', 'length'=>'int', '&w_crypto_strong='=>'bool'], 'openssl_seal' => ['int|false', 'data'=>'string', '&w_sealed_data'=>'string', '&w_env_keys'=>'array', 'pub_key_ids'=>'array', 'method='=>'string', '&rw_iv='=>'string'], 'openssl_sign' => ['bool', 'data'=>'string', '&w_signature'=>'string', 'priv_key_id'=>'resource|string', 'signature_alg='=>'int|string'], 'openssl_spki_export' => ['?string', 'spkac'=>'string'], 'openssl_spki_export_challenge' => ['?string', 'spkac'=>'string'], 'openssl_spki_new' => ['?string', 'privkey'=>'resource', 'challenge'=>'string', 'algorithm='=>'int'], 'openssl_spki_verify' => ['bool', 'spkac'=>'string'], 'openssl_verify' => ['-1|0|1', 'data'=>'string', 'signature'=>'string', 'pub_key_id'=>'resource|string', 'signature_alg='=>'int|string'], 'openssl_x509_check_private_key' => ['bool', 'cert'=>'string|resource', 'key'=>'string|resource|array'], 'openssl_x509_checkpurpose' => ['bool|int', 'x509cert'=>'string|resource', 'purpose'=>'int', 'cainfo='=>'array', 'untrustedfile='=>'string'], 'openssl_x509_export' => ['bool', 'x509'=>'string|resource', '&w_output'=>'string', 'notext='=>'bool'], 'openssl_x509_export_to_file' => ['bool', 'x509'=>'string|resource', 'outfilename'=>'string', 'notext='=>'bool'], 'openssl_x509_fingerprint' => ['string|false', 'x509'=>'string|resource', 'hash_algorithm='=>'string', 'raw_output='=>'bool'], 'openssl_x509_free' => ['void', 'x509'=>'resource'], 'openssl_x509_parse' => ['array|false', 'x509cert'=>'string|resource', 'shortnames='=>'bool'], 'openssl_x509_read' => ['resource|false', 'x509certdata'=>'string|resource'], 'ord' => ['int', 'character'=>'string'], 'OuterIterator::current' => ['mixed'], 'OuterIterator::getInnerIterator' => ['Iterator'], 'OuterIterator::key' => ['int|string'], 'OuterIterator::next' => ['void'], 'OuterIterator::rewind' => ['void'], 'OuterIterator::valid' => ['bool'], 'OutOfBoundsException::__clone' => ['void'], 'OutOfBoundsException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?OutOfBoundsException'], 'OutOfBoundsException::__toString' => ['string'], 'OutOfBoundsException::getCode' => ['int'], 'OutOfBoundsException::getFile' => ['string'], 'OutOfBoundsException::getLine' => ['int'], 'OutOfBoundsException::getMessage' => ['string'], 'OutOfBoundsException::getPrevious' => ['Throwable|OutOfBoundsException|null'], 'OutOfBoundsException::getTrace' => ['list>'], 'OutOfBoundsException::getTraceAsString' => ['string'], 'OutOfRangeException::__clone' => ['void'], 'OutOfRangeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?OutOfRangeException'], 'OutOfRangeException::__toString' => ['string'], 'OutOfRangeException::getCode' => ['int'], 'OutOfRangeException::getFile' => ['string'], 'OutOfRangeException::getLine' => ['int'], 'OutOfRangeException::getMessage' => ['string'], 'OutOfRangeException::getPrevious' => ['Throwable|OutOfRangeException|null'], 'OutOfRangeException::getTrace' => ['list>'], 'OutOfRangeException::getTraceAsString' => ['string'], 'output_add_rewrite_var' => ['bool', 'name'=>'string', 'value'=>'string'], 'output_cache_disable' => ['void'], 'output_cache_disable_compression' => ['void'], 'output_cache_exists' => ['bool', 'key'=>'string', 'lifetime'=>'int'], 'output_cache_fetch' => ['string', 'key'=>'string', 'function'=>'', 'lifetime'=>'int'], 'output_cache_get' => ['mixed|false', 'key'=>'string', 'lifetime'=>'int'], 'output_cache_output' => ['string', 'key'=>'string', 'function'=>'', 'lifetime'=>'int'], 'output_cache_put' => ['bool', 'key'=>'string', 'data'=>'mixed'], 'output_cache_remove' => ['bool', 'filename'=>''], 'output_cache_remove_key' => ['bool', 'key'=>'string'], 'output_cache_remove_url' => ['bool', 'url'=>'string'], 'output_cache_stop' => ['void'], 'output_reset_rewrite_vars' => ['bool'], 'outputformatObj::getOption' => ['string', 'property_name'=>'string'], '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'], 'OverflowException::__toString' => ['string'], 'OverflowException::getCode' => ['int'], 'OverflowException::getFile' => ['string'], 'OverflowException::getLine' => ['int'], 'OverflowException::getMessage' => ['string'], 'OverflowException::getPrevious' => ['Throwable|OverflowException|null'], 'OverflowException::getTrace' => ['list>'], 'OverflowException::getTraceAsString' => ['string'], 'overload' => ['', 'class_name'=>'string'], 'override_function' => ['bool', 'function_name'=>'string', 'function_args'=>'string', 'function_code'=>'string'], 'OwsrequestObj::__construct' => ['void'], 'OwsrequestObj::addParameter' => ['int', 'name'=>'string', 'value'=>'string'], 'OwsrequestObj::getName' => ['string', 'index'=>'int'], 'OwsrequestObj::getValue' => ['string', 'index'=>'int'], 'OwsrequestObj::getValueByName' => ['string', 'name'=>'string'], 'OwsrequestObj::loadParams' => ['int'], 'OwsrequestObj::setParameter' => ['int', 'name'=>'string', 'value'=>'string'], 'pack' => ['string|false', 'format'=>'string', '...args='=>'mixed'], 'parallel\Future::done' => ['bool'], 'parallel\Future::select' => ['mixed', '&resolving'=>'parallel\Future[]', '&w_resolved'=>'parallel\Future[]', '&w_errored'=>'parallel\Future[]', '&w_timedout='=>'parallel\Future[]', 'timeout='=>'int'], 'parallel\Future::value' => ['mixed', 'timeout='=>'int'], 'parallel\Runtime::__construct' => ['void', 'arg'=>'string|array'], 'parallel\Runtime::__construct\'1' => ['void', 'bootstrap'=>'string', 'configuration'=>'array'], 'parallel\Runtime::close' => ['void'], 'parallel\Runtime::kill' => ['void'], 'parallel\Runtime::run' => ['?parallel\Future', 'closure'=>'Closure', 'args='=>'array'], 'ParentIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator'], 'ParentIterator::accept' => ['bool'], 'ParentIterator::getChildren' => ['ParentIterator'], 'ParentIterator::hasChildren' => ['bool'], 'ParentIterator::next' => ['void'], 'ParentIterator::rewind' => ['void'], 'ParentIterator::valid' => [''], 'Parle\Lexer::advance' => ['void'], 'Parle\Lexer::build' => ['void'], 'Parle\Lexer::callout' => ['void', 'id'=>'int', 'callback'=>'callable'], 'Parle\Lexer::consume' => ['void', 'data'=>'string'], 'Parle\Lexer::dump' => ['void'], 'Parle\Lexer::getToken' => ['Parle\Token'], 'Parle\Lexer::insertMacro' => ['void', 'name'=>'string', 'regex'=>'string'], 'Parle\Lexer::push' => ['void', 'regex'=>'string', 'id'=>'int'], 'Parle\Lexer::reset' => ['void', 'pos'=>'int'], 'Parle\Parser::advance' => ['void'], 'Parle\Parser::build' => ['void'], 'Parle\Parser::consume' => ['void', 'data'=>'string', 'lexer'=>'Parle\Lexer'], 'Parle\Parser::dump' => ['void'], 'Parle\Parser::errorInfo' => ['Parle\ErrorInfo'], 'Parle\Parser::left' => ['void', 'token'=>'string'], 'Parle\Parser::nonassoc' => ['void', 'token'=>'string'], 'Parle\Parser::precedence' => ['void', 'token'=>'string'], 'Parle\Parser::push' => ['int', 'name'=>'string', 'rule'=>'string'], 'Parle\Parser::reset' => ['void', 'tokenId'=>'int'], 'Parle\Parser::right' => ['void', 'token'=>'string'], 'Parle\Parser::sigil' => ['string', 'idx'=>'array'], 'Parle\Parser::token' => ['void', 'token'=>'string'], 'Parle\Parser::tokenId' => ['int', 'token'=>'string'], 'Parle\Parser::trace' => ['string'], 'Parle\Parser::validate' => ['bool', 'data'=>'string', 'lexer'=>'Parle\Lexer'], 'Parle\RLexer::advance' => ['void'], 'Parle\RLexer::build' => ['void'], 'Parle\RLexer::callout' => ['void', 'id'=>'int', 'callback'=>'callable'], 'Parle\RLexer::consume' => ['void', 'data'=>'string'], 'Parle\RLexer::dump' => ['void'], 'Parle\RLexer::getToken' => ['Parle\Token'], 'parle\rlexer::insertMacro' => ['void', 'name'=>'string', 'regex'=>'string'], 'Parle\RLexer::push' => ['void', 'state'=>'string', 'regex'=>'string', 'newState'=>'string'], 'Parle\RLexer::pushState' => ['int', 'state'=>'string'], 'Parle\RLexer::reset' => ['void', 'pos'=>'int'], 'Parle\RParser::advance' => ['void'], 'Parle\RParser::build' => ['void'], 'Parle\RParser::consume' => ['void', 'data'=>'string', 'lexer'=>'Parle\Lexer'], 'Parle\RParser::dump' => ['void'], 'Parle\RParser::errorInfo' => ['Parle\ErrorInfo'], 'Parle\RParser::left' => ['void', 'token'=>'string'], 'Parle\RParser::nonassoc' => ['void', 'token'=>'string'], 'Parle\RParser::precedence' => ['void', 'token'=>'string'], 'Parle\RParser::push' => ['int', 'name'=>'string', 'rule'=>'string'], 'Parle\RParser::reset' => ['void', 'tokenId'=>'int'], 'Parle\RParser::right' => ['void', 'token'=>'string'], 'Parle\RParser::sigil' => ['string', 'idx'=>'array'], 'Parle\RParser::token' => ['void', 'token'=>'string'], 'Parle\RParser::tokenId' => ['int', 'token'=>'string'], 'Parle\RParser::trace' => ['string'], 'Parle\RParser::validate' => ['bool', 'data'=>'string', 'lexer'=>'Parle\Lexer'], 'Parle\Stack::pop' => ['void'], 'Parle\Stack::push' => ['void', 'item'=>'mixed'], 'parse_ini_file' => ['array|false', 'filename'=>'string', 'process_sections='=>'bool', 'scanner_mode='=>'int'], 'parse_ini_string' => ['array|false', 'ini_string'=>'string', 'process_sections='=>'bool', 'scanner_mode='=>'int'], 'parse_str' => ['void', 'encoded_string'=>'string', '&w_result='=>'array'], 'parse_url' => ['mixed|false', 'url'=>'string', 'url_component='=>'int'], 'ParseError::__clone' => ['void'], 'ParseError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?ParseError'], 'ParseError::__toString' => ['string'], 'ParseError::getCode' => ['int'], 'ParseError::getFile' => ['string'], 'ParseError::getLine' => ['int'], 'ParseError::getMessage' => ['string'], 'ParseError::getPrevious' => ['Throwable|ParseError|null'], 'ParseError::getTrace' => ['list>'], 'ParseError::getTraceAsString' => ['string'], 'parsekit_compile_file' => ['array', 'filename'=>'string', 'errors='=>'array', 'options='=>'int'], 'parsekit_compile_string' => ['array', 'phpcode'=>'string', 'errors='=>'array', 'options='=>'int'], 'parsekit_func_arginfo' => ['array', 'function'=>'mixed'], 'passthru' => ['void', 'command'=>'string', '&w_return_value='=>'int'], 'password_get_info' => ['array', 'hash'=>'string'], 'password_hash' => ['string|null', 'password'=>'string', 'algo'=>'int|string|null', 'options='=>'array'], 'password_make_salt' => ['bool', 'password'=>'string', 'hash'=>'string'], 'password_needs_rehash' => ['bool', 'hash'=>'string', 'algo'=>'int|string|null', 'options='=>'array'], 'password_verify' => ['bool', 'password'=>'string', 'hash'=>'string'], 'pathinfo' => ['array|string', 'path'=>'string', 'options='=>'int'], 'pclose' => ['int', 'fp'=>'resource'], 'pcnlt_sigwaitinfo' => ['int', 'set'=>'array', '&w_siginfo'=>'array'], 'pcntl_alarm' => ['int', 'seconds'=>'int'], 'pcntl_async_signals' => ['bool', 'on='=>'bool'], 'pcntl_errno' => ['int'], 'pcntl_exec' => ['null|false', 'path'=>'string', 'args='=>'array', 'envs='=>'array'], 'pcntl_fork' => ['int'], 'pcntl_get_last_error' => ['int'], 'pcntl_getpriority' => ['int', 'pid='=>'int', 'process_identifier='=>'int'], 'pcntl_setpriority' => ['bool', 'priority'=>'int', 'pid='=>'int', 'process_identifier='=>'int'], 'pcntl_signal' => ['bool', 'signo'=>'int', 'handle'=>'callable():void|callable(int):void|callable(int,array):void|int', 'restart_syscalls='=>'bool'], 'pcntl_signal_dispatch' => ['bool'], 'pcntl_signal_get_handler' => ['int|string', 'signo'=>'int'], 'pcntl_sigprocmask' => ['bool', 'how'=>'int', 'set'=>'array', '&w_oldset='=>'array'], 'pcntl_sigtimedwait' => ['int', 'set'=>'array', '&w_siginfo='=>'array', 'seconds='=>'int', 'nanoseconds='=>'int'], 'pcntl_sigwaitinfo' => ['int', 'set'=>'array', '&w_siginfo='=>'array'], 'pcntl_strerror' => ['string|false', 'errno'=>'int'], 'pcntl_wait' => ['int', '&w_status'=>'int', 'options='=>'int', '&w_rusage='=>'array'], 'pcntl_waitpid' => ['int', 'pid'=>'int', '&w_status'=>'int', 'options='=>'int', '&w_rusage='=>'array'], 'pcntl_wexitstatus' => ['int', 'status'=>'int'], 'pcntl_wifcontinued' => ['bool', 'status'=>'int'], 'pcntl_wifexited' => ['bool', 'status'=>'int'], 'pcntl_wifsignaled' => ['bool', 'status'=>'int'], 'pcntl_wifstopped' => ['bool', 'status'=>'int'], 'pcntl_wstopsig' => ['int', 'status'=>'int'], 'pcntl_wtermsig' => ['int', 'status'=>'int'], 'PDF_activate_item' => ['bool', 'pdfdoc'=>'resource', 'id'=>'int'], 'PDF_add_launchlink' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string'], 'PDF_add_locallink' => ['bool', 'pdfdoc'=>'resource', 'lowerleftx'=>'float', 'lowerlefty'=>'float', 'upperrightx'=>'float', 'upperrighty'=>'float', 'page'=>'int', 'dest'=>'string'], 'PDF_add_nameddest' => ['bool', 'pdfdoc'=>'resource', 'name'=>'string', 'optlist'=>'string'], 'PDF_add_note' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'contents'=>'string', 'title'=>'string', 'icon'=>'string', 'open'=>'int'], 'PDF_add_pdflink' => ['bool', 'pdfdoc'=>'resource', 'bottom_left_x'=>'float', 'bottom_left_y'=>'float', 'up_right_x'=>'float', 'up_right_y'=>'float', 'filename'=>'string', 'page'=>'int', 'dest'=>'string'], 'PDF_add_table_cell' => ['int', 'pdfdoc'=>'resource', 'table'=>'int', 'column'=>'int', 'row'=>'int', 'text'=>'string', 'optlist'=>'string'], 'PDF_add_textflow' => ['int', 'pdfdoc'=>'resource', 'textflow'=>'int', 'text'=>'string', 'optlist'=>'string'], 'PDF_add_thumbnail' => ['bool', 'pdfdoc'=>'resource', 'image'=>'int'], 'PDF_add_weblink' => ['bool', 'pdfdoc'=>'resource', 'lowerleftx'=>'float', 'lowerlefty'=>'float', 'upperrightx'=>'float', 'upperrighty'=>'float', 'url'=>'string'], 'PDF_arc' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float', 'r'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'PDF_arcn' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float', 'r'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'PDF_attach_file' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string', 'description'=>'string', 'author'=>'string', 'mimetype'=>'string', 'icon'=>'string'], 'PDF_begin_document' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string', 'optlist'=>'string'], 'PDF_begin_font' => ['bool', 'pdfdoc'=>'resource', 'filename'=>'string', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'e'=>'float', 'f'=>'float', 'optlist'=>'string'], 'PDF_begin_glyph' => ['bool', 'pdfdoc'=>'resource', 'glyphname'=>'string', 'wx'=>'float', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float'], 'PDF_begin_item' => ['int', 'pdfdoc'=>'resource', 'tag'=>'string', 'optlist'=>'string'], 'PDF_begin_layer' => ['bool', 'pdfdoc'=>'resource', 'layer'=>'int'], 'PDF_begin_page' => ['bool', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float'], 'PDF_begin_page_ext' => ['bool', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float', 'optlist'=>'string'], 'PDF_begin_pattern' => ['int', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float', 'xstep'=>'float', 'ystep'=>'float', 'painttype'=>'int'], 'PDF_begin_template' => ['int', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float'], 'PDF_begin_template_ext' => ['int', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float', 'optlist'=>'string'], 'PDF_circle' => ['bool', 'pdfdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'r'=>'float'], 'PDF_clip' => ['bool', 'p'=>'resource'], 'PDF_close' => ['bool', 'p'=>'resource'], 'PDF_close_image' => ['bool', 'p'=>'resource', 'image'=>'int'], 'PDF_close_pdi' => ['bool', 'p'=>'resource', 'doc'=>'int'], 'PDF_close_pdi_page' => ['bool', 'p'=>'resource', 'page'=>'int'], 'PDF_closepath' => ['bool', 'p'=>'resource'], 'PDF_closepath_fill_stroke' => ['bool', 'p'=>'resource'], 'PDF_closepath_stroke' => ['bool', 'p'=>'resource'], 'PDF_concat' => ['bool', 'p'=>'resource', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'e'=>'float', 'f'=>'float'], 'PDF_continue_text' => ['bool', 'p'=>'resource', 'text'=>'string'], 'PDF_create_3dview' => ['int', 'pdfdoc'=>'resource', 'username'=>'string', 'optlist'=>'string'], 'PDF_create_action' => ['int', 'pdfdoc'=>'resource', 'type'=>'string', 'optlist'=>'string'], 'PDF_create_annotation' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'type'=>'string', 'optlist'=>'string'], 'PDF_create_bookmark' => ['int', 'pdfdoc'=>'resource', 'text'=>'string', 'optlist'=>'string'], 'PDF_create_field' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'name'=>'string', 'type'=>'string', 'optlist'=>'string'], 'PDF_create_fieldgroup' => ['bool', 'pdfdoc'=>'resource', 'name'=>'string', 'optlist'=>'string'], 'PDF_create_gstate' => ['int', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_create_pvf' => ['bool', 'pdfdoc'=>'resource', 'filename'=>'string', 'data'=>'string', 'optlist'=>'string'], 'PDF_create_textflow' => ['int', 'pdfdoc'=>'resource', 'text'=>'string', 'optlist'=>'string'], 'PDF_curveto' => ['bool', 'p'=>'resource', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'PDF_define_layer' => ['int', 'pdfdoc'=>'resource', 'name'=>'string', 'optlist'=>'string'], 'PDF_delete' => ['bool', 'pdfdoc'=>'resource'], 'PDF_delete_pvf' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string'], 'PDF_delete_table' => ['bool', 'pdfdoc'=>'resource', 'table'=>'int', 'optlist'=>'string'], 'PDF_delete_textflow' => ['bool', 'pdfdoc'=>'resource', 'textflow'=>'int'], 'PDF_encoding_set_char' => ['bool', 'pdfdoc'=>'resource', 'encoding'=>'string', 'slot'=>'int', 'glyphname'=>'string', 'uv'=>'int'], 'PDF_end_document' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_end_font' => ['bool', 'pdfdoc'=>'resource'], 'PDF_end_glyph' => ['bool', 'pdfdoc'=>'resource'], 'PDF_end_item' => ['bool', 'pdfdoc'=>'resource', 'id'=>'int'], 'PDF_end_layer' => ['bool', 'pdfdoc'=>'resource'], 'PDF_end_page' => ['bool', 'p'=>'resource'], 'PDF_end_page_ext' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_end_pattern' => ['bool', 'p'=>'resource'], 'PDF_end_template' => ['bool', 'p'=>'resource'], 'PDF_endpath' => ['bool', 'p'=>'resource'], 'PDF_fill' => ['bool', 'p'=>'resource'], 'PDF_fill_imageblock' => ['int', 'pdfdoc'=>'resource', 'page'=>'int', 'blockname'=>'string', 'image'=>'int', 'optlist'=>'string'], 'PDF_fill_pdfblock' => ['int', 'pdfdoc'=>'resource', 'page'=>'int', 'blockname'=>'string', 'contents'=>'int', 'optlist'=>'string'], 'PDF_fill_stroke' => ['bool', 'p'=>'resource'], 'PDF_fill_textblock' => ['int', 'pdfdoc'=>'resource', 'page'=>'int', 'blockname'=>'string', 'text'=>'string', 'optlist'=>'string'], 'PDF_findfont' => ['int', 'p'=>'resource', 'fontname'=>'string', 'encoding'=>'string', 'embed'=>'int'], 'PDF_fit_image' => ['bool', 'pdfdoc'=>'resource', 'image'=>'int', 'x'=>'float', 'y'=>'float', 'optlist'=>'string'], 'PDF_fit_pdi_page' => ['bool', 'pdfdoc'=>'resource', 'page'=>'int', 'x'=>'float', 'y'=>'float', 'optlist'=>'string'], 'PDF_fit_table' => ['string', 'pdfdoc'=>'resource', 'table'=>'int', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'optlist'=>'string'], 'PDF_fit_textflow' => ['string', 'pdfdoc'=>'resource', 'textflow'=>'int', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'optlist'=>'string'], 'PDF_fit_textline' => ['bool', 'pdfdoc'=>'resource', 'text'=>'string', 'x'=>'float', 'y'=>'float', 'optlist'=>'string'], 'PDF_get_apiname' => ['string', 'pdfdoc'=>'resource'], 'PDF_get_buffer' => ['string', 'p'=>'resource'], 'PDF_get_errmsg' => ['string', 'pdfdoc'=>'resource'], 'PDF_get_errnum' => ['int', 'pdfdoc'=>'resource'], 'PDF_get_majorversion' => ['int'], 'PDF_get_minorversion' => ['int'], 'PDF_get_parameter' => ['string', 'p'=>'resource', 'key'=>'string', 'modifier'=>'float'], 'PDF_get_pdi_parameter' => ['string', 'p'=>'resource', 'key'=>'string', 'doc'=>'int', 'page'=>'int', 'reserved'=>'int'], 'PDF_get_pdi_value' => ['float', 'p'=>'resource', 'key'=>'string', 'doc'=>'int', 'page'=>'int', 'reserved'=>'int'], 'PDF_get_value' => ['float', 'p'=>'resource', 'key'=>'string', 'modifier'=>'float'], 'PDF_info_font' => ['float', 'pdfdoc'=>'resource', 'font'=>'int', 'keyword'=>'string', 'optlist'=>'string'], 'PDF_info_matchbox' => ['float', 'pdfdoc'=>'resource', 'boxname'=>'string', 'num'=>'int', 'keyword'=>'string'], 'PDF_info_table' => ['float', 'pdfdoc'=>'resource', 'table'=>'int', 'keyword'=>'string'], 'PDF_info_textflow' => ['float', 'pdfdoc'=>'resource', 'textflow'=>'int', 'keyword'=>'string'], 'PDF_info_textline' => ['float', 'pdfdoc'=>'resource', 'text'=>'string', 'keyword'=>'string', 'optlist'=>'string'], 'PDF_initgraphics' => ['bool', 'p'=>'resource'], 'PDF_lineto' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float'], 'PDF_load_3ddata' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string', 'optlist'=>'string'], 'PDF_load_font' => ['int', 'pdfdoc'=>'resource', 'fontname'=>'string', 'encoding'=>'string', 'optlist'=>'string'], 'PDF_load_iccprofile' => ['int', 'pdfdoc'=>'resource', 'profilename'=>'string', 'optlist'=>'string'], 'PDF_load_image' => ['int', 'pdfdoc'=>'resource', 'imagetype'=>'string', 'filename'=>'string', 'optlist'=>'string'], 'PDF_makespotcolor' => ['int', 'p'=>'resource', 'spotname'=>'string'], 'PDF_moveto' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float'], 'PDF_new' => ['resource'], 'PDF_open_ccitt' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string', 'width'=>'int', 'height'=>'int', 'bitreverse'=>'int', 'k'=>'int', 'blackls1'=>'int'], 'PDF_open_file' => ['bool', 'p'=>'resource', 'filename'=>'string'], 'PDF_open_image' => ['int', 'p'=>'resource', 'imagetype'=>'string', 'source'=>'string', 'data'=>'string', 'length'=>'int', 'width'=>'int', 'height'=>'int', 'components'=>'int', 'bpc'=>'int', 'params'=>'string'], 'PDF_open_image_file' => ['int', 'p'=>'resource', 'imagetype'=>'string', 'filename'=>'string', 'stringparam'=>'string', 'intparam'=>'int'], 'PDF_open_memory_image' => ['int', 'p'=>'resource', 'image'=>'resource'], 'PDF_open_pdi' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string', 'optlist'=>'string', 'length'=>'int'], 'PDF_open_pdi_document' => ['int', 'p'=>'resource', 'filename'=>'string', 'optlist'=>'string'], 'PDF_open_pdi_page' => ['int', 'p'=>'resource', 'doc'=>'int', 'pagenumber'=>'int', 'optlist'=>'string'], 'PDF_pcos_get_number' => ['float', 'p'=>'resource', 'doc'=>'int', 'path'=>'string'], 'PDF_pcos_get_stream' => ['string', 'p'=>'resource', 'doc'=>'int', 'optlist'=>'string', 'path'=>'string'], 'PDF_pcos_get_string' => ['string', 'p'=>'resource', 'doc'=>'int', 'path'=>'string'], 'PDF_place_image' => ['bool', 'pdfdoc'=>'resource', 'image'=>'int', 'x'=>'float', 'y'=>'float', 'scale'=>'float'], 'PDF_place_pdi_page' => ['bool', 'pdfdoc'=>'resource', 'page'=>'int', 'x'=>'float', 'y'=>'float', 'sx'=>'float', 'sy'=>'float'], 'PDF_process_pdi' => ['int', 'pdfdoc'=>'resource', 'doc'=>'int', 'page'=>'int', 'optlist'=>'string'], 'PDF_rect' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'PDF_restore' => ['bool', 'p'=>'resource'], 'PDF_resume_page' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_rotate' => ['bool', 'p'=>'resource', 'phi'=>'float'], 'PDF_save' => ['bool', 'p'=>'resource'], 'PDF_scale' => ['bool', 'p'=>'resource', 'sx'=>'float', 'sy'=>'float'], 'PDF_set_border_color' => ['bool', 'p'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDF_set_border_dash' => ['bool', 'pdfdoc'=>'resource', 'black'=>'float', 'white'=>'float'], 'PDF_set_border_style' => ['bool', 'pdfdoc'=>'resource', 'style'=>'string', 'width'=>'float'], 'PDF_set_gstate' => ['bool', 'pdfdoc'=>'resource', 'gstate'=>'int'], 'PDF_set_info' => ['bool', 'p'=>'resource', 'key'=>'string', 'value'=>'string'], 'PDF_set_layer_dependency' => ['bool', 'pdfdoc'=>'resource', 'type'=>'string', 'optlist'=>'string'], 'PDF_set_parameter' => ['bool', 'p'=>'resource', 'key'=>'string', 'value'=>'string'], 'PDF_set_text_pos' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float'], 'PDF_set_value' => ['bool', 'p'=>'resource', 'key'=>'string', 'value'=>'float'], 'PDF_setcolor' => ['bool', 'p'=>'resource', 'fstype'=>'string', 'colorspace'=>'string', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float'], 'PDF_setdash' => ['bool', 'pdfdoc'=>'resource', 'b'=>'float', 'w'=>'float'], 'PDF_setdashpattern' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_setflat' => ['bool', 'pdfdoc'=>'resource', 'flatness'=>'float'], 'PDF_setfont' => ['bool', 'pdfdoc'=>'resource', 'font'=>'int', 'fontsize'=>'float'], 'PDF_setgray' => ['bool', 'p'=>'resource', 'g'=>'float'], 'PDF_setgray_fill' => ['bool', 'p'=>'resource', 'g'=>'float'], 'PDF_setgray_stroke' => ['bool', 'p'=>'resource', 'g'=>'float'], 'PDF_setlinecap' => ['bool', 'p'=>'resource', 'linecap'=>'int'], 'PDF_setlinejoin' => ['bool', 'p'=>'resource', 'value'=>'int'], 'PDF_setlinewidth' => ['bool', 'p'=>'resource', 'width'=>'float'], 'PDF_setmatrix' => ['bool', 'p'=>'resource', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'e'=>'float', 'f'=>'float'], 'PDF_setmiterlimit' => ['bool', 'pdfdoc'=>'resource', 'miter'=>'float'], 'PDF_setrgbcolor' => ['bool', 'p'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDF_setrgbcolor_fill' => ['bool', 'p'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDF_setrgbcolor_stroke' => ['bool', 'p'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDF_shading' => ['int', 'pdfdoc'=>'resource', 'shtype'=>'string', 'x0'=>'float', 'y0'=>'float', 'x1'=>'float', 'y1'=>'float', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float', 'optlist'=>'string'], 'PDF_shading_pattern' => ['int', 'pdfdoc'=>'resource', 'shading'=>'int', 'optlist'=>'string'], 'PDF_shfill' => ['bool', 'pdfdoc'=>'resource', 'shading'=>'int'], 'PDF_show' => ['bool', 'pdfdoc'=>'resource', 'text'=>'string'], 'PDF_show_boxed' => ['int', 'p'=>'resource', 'text'=>'string', 'left'=>'float', 'top'=>'float', 'width'=>'float', 'height'=>'float', 'mode'=>'string', 'feature'=>'string'], 'PDF_show_xy' => ['bool', 'p'=>'resource', 'text'=>'string', 'x'=>'float', 'y'=>'float'], 'PDF_skew' => ['bool', 'p'=>'resource', 'alpha'=>'float', 'beta'=>'float'], 'PDF_stringwidth' => ['float', 'p'=>'resource', 'text'=>'string', 'font'=>'int', 'fontsize'=>'float'], 'PDF_stroke' => ['bool', 'p'=>'resource'], 'PDF_suspend_page' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_translate' => ['bool', 'p'=>'resource', 'tx'=>'float', 'ty'=>'float'], 'PDF_utf16_to_utf8' => ['string', 'pdfdoc'=>'resource', 'utf16string'=>'string'], 'PDF_utf32_to_utf16' => ['string', 'pdfdoc'=>'resource', 'utf32string'=>'string', 'ordering'=>'string'], 'PDF_utf8_to_utf16' => ['string', 'pdfdoc'=>'resource', 'utf8string'=>'string', 'ordering'=>'string'], 'PDFlib::activate_item' => ['bool', 'id'=>''], 'PDFlib::add_launchlink' => ['bool', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string'], 'PDFlib::add_locallink' => ['bool', 'lowerleftx'=>'float', 'lowerlefty'=>'float', 'upperrightx'=>'float', 'upperrighty'=>'float', 'page'=>'int', 'dest'=>'string'], 'PDFlib::add_nameddest' => ['bool', 'name'=>'string', 'optlist'=>'string'], 'PDFlib::add_note' => ['bool', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'contents'=>'string', 'title'=>'string', 'icon'=>'string', 'open'=>'int'], 'PDFlib::add_pdflink' => ['bool', 'bottom_left_x'=>'float', 'bottom_left_y'=>'float', 'up_right_x'=>'float', 'up_right_y'=>'float', 'filename'=>'string', 'page'=>'int', 'dest'=>'string'], 'PDFlib::add_table_cell' => ['int', 'table'=>'int', 'column'=>'int', 'row'=>'int', 'text'=>'string', 'optlist'=>'string'], 'PDFlib::add_textflow' => ['int', 'textflow'=>'int', 'text'=>'string', 'optlist'=>'string'], 'PDFlib::add_thumbnail' => ['bool', 'image'=>'int'], 'PDFlib::add_weblink' => ['bool', 'lowerleftx'=>'float', 'lowerlefty'=>'float', 'upperrightx'=>'float', 'upperrighty'=>'float', 'url'=>'string'], 'PDFlib::arc' => ['bool', 'x'=>'float', 'y'=>'float', 'r'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'PDFlib::arcn' => ['bool', 'x'=>'float', 'y'=>'float', 'r'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'PDFlib::attach_file' => ['bool', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string', 'description'=>'string', 'author'=>'string', 'mimetype'=>'string', 'icon'=>'string'], 'PDFlib::begin_document' => ['int', 'filename'=>'string', 'optlist'=>'string'], 'PDFlib::begin_font' => ['bool', 'filename'=>'string', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'e'=>'float', 'f'=>'float', 'optlist'=>'string'], 'PDFlib::begin_glyph' => ['bool', 'glyphname'=>'string', 'wx'=>'float', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float'], 'PDFlib::begin_item' => ['int', 'tag'=>'string', 'optlist'=>'string'], 'PDFlib::begin_layer' => ['bool', 'layer'=>'int'], 'PDFlib::begin_page' => ['bool', 'width'=>'float', 'height'=>'float'], 'PDFlib::begin_page_ext' => ['bool', 'width'=>'float', 'height'=>'float', 'optlist'=>'string'], 'PDFlib::begin_pattern' => ['int', 'width'=>'float', 'height'=>'float', 'xstep'=>'float', 'ystep'=>'float', 'painttype'=>'int'], 'PDFlib::begin_template' => ['int', 'width'=>'float', 'height'=>'float'], 'PDFlib::begin_template_ext' => ['int', 'width'=>'float', 'height'=>'float', 'optlist'=>'string'], 'PDFlib::circle' => ['bool', 'x'=>'float', 'y'=>'float', 'r'=>'float'], 'PDFlib::clip' => ['bool'], 'PDFlib::close' => ['bool'], 'PDFlib::close_image' => ['bool', 'image'=>'int'], 'PDFlib::close_pdi' => ['bool', 'doc'=>'int'], 'PDFlib::close_pdi_page' => ['bool', 'page'=>'int'], 'PDFlib::closepath' => ['bool'], 'PDFlib::closepath_fill_stroke' => ['bool'], 'PDFlib::closepath_stroke' => ['bool'], 'PDFlib::concat' => ['bool', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'e'=>'float', 'f'=>'float'], 'PDFlib::continue_text' => ['bool', 'text'=>'string'], 'PDFlib::create_3dview' => ['int', 'username'=>'string', 'optlist'=>'string'], 'PDFlib::create_action' => ['int', 'type'=>'string', 'optlist'=>'string'], 'PDFlib::create_annotation' => ['bool', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'type'=>'string', 'optlist'=>'string'], 'PDFlib::create_bookmark' => ['int', 'text'=>'string', 'optlist'=>'string'], 'PDFlib::create_field' => ['bool', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'name'=>'string', 'type'=>'string', 'optlist'=>'string'], 'PDFlib::create_fieldgroup' => ['bool', 'name'=>'string', 'optlist'=>'string'], 'PDFlib::create_gstate' => ['int', 'optlist'=>'string'], 'PDFlib::create_pvf' => ['bool', 'filename'=>'string', 'data'=>'string', 'optlist'=>'string'], 'PDFlib::create_textflow' => ['int', 'text'=>'string', 'optlist'=>'string'], 'PDFlib::curveto' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'PDFlib::define_layer' => ['int', 'name'=>'string', 'optlist'=>'string'], 'PDFlib::delete' => ['bool'], 'PDFlib::delete_pvf' => ['int', 'filename'=>'string'], 'PDFlib::delete_table' => ['bool', 'table'=>'int', 'optlist'=>'string'], 'PDFlib::delete_textflow' => ['bool', 'textflow'=>'int'], 'PDFlib::encoding_set_char' => ['bool', 'encoding'=>'string', 'slot'=>'int', 'glyphname'=>'string', 'uv'=>'int'], 'PDFlib::end_document' => ['bool', 'optlist'=>'string'], 'PDFlib::end_font' => ['bool'], 'PDFlib::end_glyph' => ['bool'], 'PDFlib::end_item' => ['bool', 'id'=>'int'], 'PDFlib::end_layer' => ['bool'], 'PDFlib::end_page' => ['bool', 'p'=>''], 'PDFlib::end_page_ext' => ['bool', 'optlist'=>'string'], 'PDFlib::end_pattern' => ['bool', 'p'=>''], 'PDFlib::end_template' => ['bool', 'p'=>''], 'PDFlib::endpath' => ['bool', 'p'=>''], 'PDFlib::fill' => ['bool'], 'PDFlib::fill_imageblock' => ['int', 'page'=>'int', 'blockname'=>'string', 'image'=>'int', 'optlist'=>'string'], 'PDFlib::fill_pdfblock' => ['int', 'page'=>'int', 'blockname'=>'string', 'contents'=>'int', 'optlist'=>'string'], 'PDFlib::fill_stroke' => ['bool'], 'PDFlib::fill_textblock' => ['int', 'page'=>'int', 'blockname'=>'string', 'text'=>'string', 'optlist'=>'string'], 'PDFlib::findfont' => ['int', 'fontname'=>'string', 'encoding'=>'string', 'embed'=>'int'], 'PDFlib::fit_image' => ['bool', 'image'=>'int', 'x'=>'float', 'y'=>'float', 'optlist'=>'string'], 'PDFlib::fit_pdi_page' => ['bool', 'page'=>'int', 'x'=>'float', 'y'=>'float', 'optlist'=>'string'], 'PDFlib::fit_table' => ['string', 'table'=>'int', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'optlist'=>'string'], 'PDFlib::fit_textflow' => ['string', 'textflow'=>'int', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'optlist'=>'string'], 'PDFlib::fit_textline' => ['bool', 'text'=>'string', 'x'=>'float', 'y'=>'float', 'optlist'=>'string'], 'PDFlib::get_apiname' => ['string'], 'PDFlib::get_buffer' => ['string'], 'PDFlib::get_errmsg' => ['string'], 'PDFlib::get_errnum' => ['int'], 'PDFlib::get_majorversion' => ['int'], 'PDFlib::get_minorversion' => ['int'], 'PDFlib::get_parameter' => ['string', 'key'=>'string', 'modifier'=>'float'], 'PDFlib::get_pdi_parameter' => ['string', 'key'=>'string', 'doc'=>'int', 'page'=>'int', 'reserved'=>'int'], 'PDFlib::get_pdi_value' => ['float', 'key'=>'string', 'doc'=>'int', 'page'=>'int', 'reserved'=>'int'], 'PDFlib::get_value' => ['float', 'key'=>'string', 'modifier'=>'float'], 'PDFlib::info_font' => ['float', 'font'=>'int', 'keyword'=>'string', 'optlist'=>'string'], 'PDFlib::info_matchbox' => ['float', 'boxname'=>'string', 'num'=>'int', 'keyword'=>'string'], 'PDFlib::info_table' => ['float', 'table'=>'int', 'keyword'=>'string'], 'PDFlib::info_textflow' => ['float', 'textflow'=>'int', 'keyword'=>'string'], 'PDFlib::info_textline' => ['float', 'text'=>'string', 'keyword'=>'string', 'optlist'=>'string'], 'PDFlib::initgraphics' => ['bool'], 'PDFlib::lineto' => ['bool', 'x'=>'float', 'y'=>'float'], 'PDFlib::load_3ddata' => ['int', 'filename'=>'string', 'optlist'=>'string'], 'PDFlib::load_font' => ['int', 'fontname'=>'string', 'encoding'=>'string', 'optlist'=>'string'], 'PDFlib::load_iccprofile' => ['int', 'profilename'=>'string', 'optlist'=>'string'], 'PDFlib::load_image' => ['int', 'imagetype'=>'string', 'filename'=>'string', 'optlist'=>'string'], 'PDFlib::makespotcolor' => ['int', 'spotname'=>'string'], 'PDFlib::moveto' => ['bool', 'x'=>'float', 'y'=>'float'], 'PDFlib::open_ccitt' => ['int', 'filename'=>'string', 'width'=>'int', 'height'=>'int', 'BitReverse'=>'int', 'k'=>'int', 'Blackls1'=>'int'], 'PDFlib::open_file' => ['bool', 'filename'=>'string'], 'PDFlib::open_image' => ['int', 'imagetype'=>'string', 'source'=>'string', 'data'=>'string', 'length'=>'int', 'width'=>'int', 'height'=>'int', 'components'=>'int', 'bpc'=>'int', 'params'=>'string'], 'PDFlib::open_image_file' => ['int', 'imagetype'=>'string', 'filename'=>'string', 'stringparam'=>'string', 'intparam'=>'int'], 'PDFlib::open_memory_image' => ['int', 'image'=>'resource'], 'PDFlib::open_pdi' => ['int', 'filename'=>'string', 'optlist'=>'string', 'length'=>'int'], 'PDFlib::open_pdi_document' => ['int', 'filename'=>'string', 'optlist'=>'string'], 'PDFlib::open_pdi_page' => ['int', 'doc'=>'int', 'pagenumber'=>'int', 'optlist'=>'string'], 'PDFlib::pcos_get_number' => ['float', 'doc'=>'int', 'path'=>'string'], 'PDFlib::pcos_get_stream' => ['string', 'doc'=>'int', 'optlist'=>'string', 'path'=>'string'], 'PDFlib::pcos_get_string' => ['string', 'doc'=>'int', 'path'=>'string'], 'PDFlib::place_image' => ['bool', 'image'=>'int', 'x'=>'float', 'y'=>'float', 'scale'=>'float'], 'PDFlib::place_pdi_page' => ['bool', 'page'=>'int', 'x'=>'float', 'y'=>'float', 'sx'=>'float', 'sy'=>'float'], 'PDFlib::process_pdi' => ['int', 'doc'=>'int', 'page'=>'int', 'optlist'=>'string'], 'PDFlib::rect' => ['bool', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'PDFlib::restore' => ['bool', 'p'=>''], 'PDFlib::resume_page' => ['bool', 'optlist'=>'string'], 'PDFlib::rotate' => ['bool', 'phi'=>'float'], 'PDFlib::save' => ['bool', 'p'=>''], 'PDFlib::scale' => ['bool', 'sx'=>'float', 'sy'=>'float'], 'PDFlib::set_border_color' => ['bool', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDFlib::set_border_dash' => ['bool', 'black'=>'float', 'white'=>'float'], 'PDFlib::set_border_style' => ['bool', 'style'=>'string', 'width'=>'float'], 'PDFlib::set_gstate' => ['bool', 'gstate'=>'int'], 'PDFlib::set_info' => ['bool', 'key'=>'string', 'value'=>'string'], 'PDFlib::set_layer_dependency' => ['bool', 'type'=>'string', 'optlist'=>'string'], 'PDFlib::set_parameter' => ['bool', 'key'=>'string', 'value'=>'string'], 'PDFlib::set_text_pos' => ['bool', 'x'=>'float', 'y'=>'float'], 'PDFlib::set_value' => ['bool', 'key'=>'string', 'value'=>'float'], 'PDFlib::setcolor' => ['bool', 'fstype'=>'string', 'colorspace'=>'string', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float'], 'PDFlib::setdash' => ['bool', 'b'=>'float', 'w'=>'float'], 'PDFlib::setdashpattern' => ['bool', 'optlist'=>'string'], 'PDFlib::setflat' => ['bool', 'flatness'=>'float'], 'PDFlib::setfont' => ['bool', 'font'=>'int', 'fontsize'=>'float'], 'PDFlib::setgray' => ['bool', 'g'=>'float'], 'PDFlib::setgray_fill' => ['bool', 'g'=>'float'], 'PDFlib::setgray_stroke' => ['bool', 'g'=>'float'], 'PDFlib::setlinecap' => ['bool', 'linecap'=>'int'], 'PDFlib::setlinejoin' => ['bool', 'value'=>'int'], 'PDFlib::setlinewidth' => ['bool', 'width'=>'float'], 'PDFlib::setmatrix' => ['bool', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'e'=>'float', 'f'=>'float'], 'PDFlib::setmiterlimit' => ['bool', 'miter'=>'float'], 'PDFlib::setrgbcolor' => ['bool', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDFlib::setrgbcolor_fill' => ['bool', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDFlib::setrgbcolor_stroke' => ['bool', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDFlib::shading' => ['int', 'shtype'=>'string', 'x0'=>'float', 'y0'=>'float', 'x1'=>'float', 'y1'=>'float', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float', 'optlist'=>'string'], 'PDFlib::shading_pattern' => ['int', 'shading'=>'int', 'optlist'=>'string'], 'PDFlib::shfill' => ['bool', 'shading'=>'int'], 'PDFlib::show' => ['bool', 'text'=>'string'], 'PDFlib::show_boxed' => ['int', 'text'=>'string', 'left'=>'float', 'top'=>'float', 'width'=>'float', 'height'=>'float', 'mode'=>'string', 'feature'=>'string'], 'PDFlib::show_xy' => ['bool', 'text'=>'string', 'x'=>'float', 'y'=>'float'], 'PDFlib::skew' => ['bool', 'alpha'=>'float', 'beta'=>'float'], 'PDFlib::stringwidth' => ['float', 'text'=>'string', 'font'=>'int', 'fontsize'=>'float'], 'PDFlib::stroke' => ['bool', 'p'=>''], 'PDFlib::suspend_page' => ['bool', 'optlist'=>'string'], 'PDFlib::translate' => ['bool', 'tx'=>'float', 'ty'=>'float'], 'PDFlib::utf16_to_utf8' => ['string', 'utf16string'=>'string'], 'PDFlib::utf32_to_utf16' => ['string', 'utf32string'=>'string', 'ordering'=>'string'], 'PDFlib::utf8_to_utf16' => ['string', 'utf8string'=>'string', 'ordering'=>'string'], 'PDO::__construct' => ['void', 'dsn'=>'string', 'username='=>'?string', 'passwd='=>'?string', 'options='=>'?array'], 'PDO::__sleep' => ['list'], 'PDO::__wakeup' => ['void'], 'PDO::beginTransaction' => ['bool'], 'PDO::commit' => ['bool'], 'PDO::cubrid_schema' => ['array', 'schema_type'=>'int', 'table_name='=>'string', 'col_name='=>'string'], 'PDO::errorCode' => ['?string'], 'PDO::errorInfo' => ['array'], 'PDO::exec' => ['int|false', 'query'=>'string'], 'PDO::getAttribute' => ['', 'attribute'=>'int'], 'PDO::getAvailableDrivers' => ['array'], 'PDO::inTransaction' => ['bool'], 'PDO::lastInsertId' => ['string', 'name='=>'string|null'], 'PDO::pgsqlCopyFromArray' => ['bool', 'table_name'=>'string', 'rows'=>'array', 'delimiter'=>'string', 'null_as'=>'string', 'fields'=>'string'], 'PDO::pgsqlCopyFromFile' => ['bool', 'table_name'=>'string', 'filename'=>'string', 'delimiter'=>'string', 'null_as'=>'string', 'fields'=>'string'], 'PDO::pgsqlCopyToArray' => ['array', 'table_name'=>'string', 'delimiter'=>'string', 'null_as'=>'string', 'fields'=>'string'], 'PDO::pgsqlCopyToFile' => ['bool', 'table_name'=>'string', 'filename'=>'string', 'delimiter'=>'string', 'null_as'=>'string', 'fields'=>'string'], 'PDO::pgsqlGetNotify' => ['array', 'result_type'=>'int', 'ms_timeout'=>'int'], 'PDO::pgsqlGetPid' => ['int'], 'PDO::pgsqlLOBCreate' => ['string'], 'PDO::pgsqlLOBOpen' => ['resource', 'oid'=>'string', 'mode='=>'string'], 'PDO::pgsqlLOBUnlink' => ['bool', 'oid'=>'string'], 'PDO::prepare' => ['PDOStatement|false', 'statement'=>'string', 'options='=>'array'], 'PDO::query' => ['PDOStatement|false', 'sql'=>'string'], 'PDO::query\'1' => ['PDOStatement|false', 'sql'=>'string', 'fetch_column'=>'int', 'colno='=>'int'], 'PDO::query\'2' => ['PDOStatement|false', 'sql'=>'string', 'fetch_class'=>'int', 'classname'=>'string', 'ctorargs'=>'array'], 'PDO::query\'3' => ['PDOStatement|false', 'sql'=>'string', 'fetch_into'=>'int', 'object'=>'object'], 'PDO::quote' => ['string|false', 'string'=>'string', 'paramtype='=>'int'], 'PDO::rollBack' => ['bool'], 'PDO::setAttribute' => ['bool', 'attribute'=>'int', 'value'=>''], 'PDO::sqliteCreateAggregate' => ['bool', 'function_name'=>'string', 'step_func'=>'callable', 'finalize_func'=>'callable', 'num_args='=>'int'], 'PDO::sqliteCreateCollation' => ['bool', 'name'=>'string', 'callback'=>'callable'], 'PDO::sqliteCreateFunction' => ['bool', 'function_name'=>'string', 'callback'=>'callable', 'num_args='=>'int'], 'pdo_drivers' => ['array'], 'PDOException::getCode' => ['string'], 'PDOException::getFile' => ['string'], 'PDOException::getLine' => ['int'], 'PDOException::getMessage' => ['string'], 'PDOException::getPrevious' => ['?Throwable'], 'PDOException::getTrace' => ['list>'], 'PDOException::getTraceAsString' => ['string'], 'PDOStatement::__sleep' => ['list'], 'PDOStatement::__wakeup' => ['void'], 'PDOStatement::bindColumn' => ['bool', 'column'=>'mixed', '&rw_param'=>'mixed', 'type='=>'int', 'maxlen='=>'int', 'driverdata='=>'mixed'], 'PDOStatement::bindParam' => ['bool', 'paramno'=>'mixed', '&rw_param'=>'mixed', 'type='=>'int', 'maxlen='=>'int', 'driverdata='=>'mixed'], 'PDOStatement::bindValue' => ['bool', 'paramno'=>'mixed', 'param'=>'mixed', 'type='=>'int'], 'PDOStatement::closeCursor' => ['bool'], 'PDOStatement::columnCount' => ['int'], 'PDOStatement::debugDumpParams' => ['void'], 'PDOStatement::errorCode' => ['string'], 'PDOStatement::errorInfo' => ['array'], 'PDOStatement::execute' => ['bool', 'bound_input_params='=>'?array'], 'PDOStatement::fetch' => ['mixed', 'how='=>'int', 'orientation='=>'int', 'offset='=>'int'], 'PDOStatement::fetchAll' => ['array|false', 'how='=>'int', 'fetch_argument='=>'int|string|callable', 'ctor_args='=>'?array'], 'PDOStatement::fetchColumn' => ['string|int|float|bool|null', 'column_number='=>'int'], 'PDOStatement::fetchObject' => ['mixed|false', 'class_name='=>'string', 'ctor_args='=>'?array'], 'PDOStatement::getAttribute' => ['mixed', 'attribute'=>'int'], 'PDOStatement::getColumnMeta' => ['array|false', 'column'=>'int'], 'PDOStatement::nextRowset' => ['bool'], 'PDOStatement::rowCount' => ['int'], 'PDOStatement::setAttribute' => ['bool', 'attribute'=>'int', 'value'=>'mixed'], 'PDOStatement::setFetchMode' => ['bool', 'mode'=>'int'], 'PDOStatement::setFetchMode\'1' => ['bool', 'fetch_column'=>'int', 'colno'=>'int'], 'PDOStatement::setFetchMode\'2' => ['bool', 'fetch_class'=>'int', 'classname'=>'string', 'ctorargs'=>'array'], 'PDOStatement::setFetchMode\'3' => ['bool', 'fetch_into'=>'int', 'object'=>'object'], 'pfsockopen' => ['resource|false', 'hostname'=>'string', 'port='=>'int', '&w_errno='=>'int', '&w_errstr='=>'string', 'timeout='=>'float'], 'pg_affected_rows' => ['int', 'result'=>'resource'], 'pg_cancel_query' => ['bool', 'connection'=>'resource'], 'pg_client_encoding' => ['string|false', 'connection='=>'resource'], 'pg_close' => ['bool', 'connection='=>'resource'], 'pg_connect' => ['resource|false', 'connection_string'=>'string', 'connect_type='=>'int'], 'pg_connect_poll' => ['int', 'connection'=>'resource'], 'pg_connection_busy' => ['bool', 'connection'=>'resource'], 'pg_connection_reset' => ['bool', 'connection'=>'resource'], 'pg_connection_status' => ['int', 'connection'=>'resource'], 'pg_consume_input' => ['bool', 'connection'=>'resource'], 'pg_convert' => ['array', 'db'=>'resource', 'table'=>'string', 'values'=>'array', 'options='=>'int'], 'pg_copy_from' => ['bool', 'connection'=>'resource', 'table_name'=>'string', 'rows'=>'array', 'delimiter='=>'string', 'null_as='=>'string'], 'pg_copy_to' => ['array|false', 'connection'=>'resource', 'table_name'=>'string', 'delimiter='=>'string', 'null_as='=>'string'], 'pg_dbname' => ['string|false', 'connection='=>'resource'], 'pg_delete' => ['string|bool', 'db'=>'resource', 'table'=>'string', 'ids'=>'array', 'options='=>'int'], 'pg_end_copy' => ['bool', 'connection='=>'resource'], 'pg_escape_bytea' => ['string', 'connection'=>'resource', 'data'=>'string'], 'pg_escape_bytea\'1' => ['string', 'data'=>'string'], 'pg_escape_identifier' => ['string', 'connection'=>'resource', 'data'=>'string'], 'pg_escape_identifier\'1' => ['string', 'data'=>'string'], 'pg_escape_literal' => ['string', 'connection'=>'resource', 'data'=>'string'], 'pg_escape_literal\'1' => ['string', 'data'=>'string'], 'pg_escape_string' => ['string', 'connection'=>'resource', 'data'=>'string'], 'pg_escape_string\'1' => ['string', 'data'=>'string'], 'pg_exec' => ['resource|false', 'connection'=>'resource', 'query'=>'string'], 'pg_execute' => ['resource|false', 'connection'=>'resource', 'stmtname'=>'string', 'params'=>'array'], 'pg_execute\'1' => ['resource|false', 'stmtname'=>'string', 'params'=>'array'], 'pg_fetch_all' => ['array|false', 'result'=>'resource', 'result_type='=>'int'], 'pg_fetch_all_columns' => ['array|false', 'result'=>'resource', 'column_number='=>'int'], 'pg_fetch_array' => ['array|false', 'result'=>'resource', 'row='=>'?int', 'result_type='=>'int'], 'pg_fetch_assoc' => ['array|false', 'result'=>'resource', 'row='=>'?int'], 'pg_fetch_object' => ['object', 'result'=>'resource', 'row='=>'?int', 'result_type='=>'int'], 'pg_fetch_object\'1' => ['object', 'result'=>'resource', 'row='=>'?int', 'class_name='=>'string', 'ctor_params='=>'array'], 'pg_fetch_result' => ['string', 'result'=>'resource', 'field_name'=>'string|int'], 'pg_fetch_result\'1' => ['string', 'result'=>'resource', 'row'=>'?int', 'field_name'=>'string|int'], 'pg_fetch_row' => ['array', 'result'=>'resource', 'row='=>'?int', 'result_type='=>'int'], 'pg_field_is_null' => ['int', 'result'=>'resource', 'field_name_or_number'=>'string|int'], 'pg_field_is_null\'1' => ['int', 'result'=>'resource', 'row'=>'int', 'field_name_or_number'=>'string|int'], 'pg_field_name' => ['string|false', 'result'=>'resource', 'field_number'=>'int'], 'pg_field_num' => ['int', 'result'=>'resource', 'field_name'=>'string'], 'pg_field_prtlen' => ['int|false', 'result'=>'resource', 'field_name_or_number'=>''], 'pg_field_prtlen\'1' => ['int', 'result'=>'resource', 'row'=>'int', 'field_name_or_number'=>'string|int'], 'pg_field_size' => ['int', 'result'=>'resource', 'field_number'=>'int'], 'pg_field_table' => ['mixed|false', 'result'=>'resource', 'field_number'=>'int', 'oid_only='=>'bool'], 'pg_field_type' => ['string|false', 'result'=>'resource', 'field_number'=>'int'], 'pg_field_type_oid' => ['int|false', 'result'=>'resource', 'field_number'=>'int'], 'pg_flush' => ['mixed', 'connection'=>'resource'], 'pg_free_result' => ['bool', 'result'=>'resource'], 'pg_get_notify' => ['array|false', 'connection'=>'resource', 'result_type='=>'int'], 'pg_get_pid' => ['int|false', 'connection'=>'resource'], 'pg_get_result' => ['resource|false', 'connection='=>'resource'], 'pg_host' => ['string|false', 'connection='=>'resource'], 'pg_insert' => ['resource|string|false', 'db'=>'resource', 'table'=>'string', 'values'=>'array', 'options='=>'int'], 'pg_last_error' => ['string', 'connection='=>'resource', 'operation='=>'int'], 'pg_last_notice' => ['string|array|bool', 'connection'=>'resource', 'option='=>'int'], 'pg_last_oid' => ['string', 'result'=>'resource'], 'pg_lo_close' => ['bool', 'large_object'=>'resource'], 'pg_lo_create' => ['int|false', 'connection='=>'resource', 'large_object_oid='=>''], 'pg_lo_export' => ['bool', 'connection'=>'resource', 'oid'=>'int', 'filename'=>'string'], 'pg_lo_export\'1' => ['bool', 'oid'=>'int', 'pathname'=>'string'], 'pg_lo_import' => ['int', 'connection'=>'resource', 'pathname'=>'string', 'oid'=>''], 'pg_lo_import\'1' => ['int', 'pathname'=>'string', 'oid'=>''], 'pg_lo_open' => ['resource|false', 'connection'=>'resource', 'oid'=>'int', 'mode'=>'string'], 'pg_lo_read' => ['string', 'large_object'=>'resource', 'length='=>'int'], 'pg_lo_read_all' => ['int|false', 'large_object'=>'resource'], 'pg_lo_seek' => ['bool', 'large_object'=>'resource', 'offset'=>'int', 'whence='=>'int'], 'pg_lo_tell' => ['int', 'large_object'=>'resource'], 'pg_lo_truncate' => ['bool', 'large_object'=>'resource', 'size'=>'int'], 'pg_lo_unlink' => ['bool', 'connection'=>'resource', 'oid'=>'int'], 'pg_lo_write' => ['int|false', 'large_object'=>'resource', 'data'=>'string', 'length='=>'int'], 'pg_meta_data' => ['array', 'db'=>'resource', 'table'=>'string', 'extended='=>'bool'], 'pg_num_fields' => ['int', 'result'=>'resource'], 'pg_num_rows' => ['int', 'result'=>'resource'], 'pg_options' => ['string', 'connection='=>'resource'], 'pg_parameter_status' => ['string|false', 'connection'=>'resource', 'param_name'=>'string'], 'pg_parameter_status\'1' => ['string|false', 'param_name'=>'string'], 'pg_pconnect' => ['resource|false', 'connection_string'=>'string', 'host='=>'string', 'port='=>'string|int', 'options='=>'string', 'tty='=>'string', 'database='=>'string'], 'pg_ping' => ['bool', 'connection='=>'resource'], 'pg_port' => ['int', 'connection='=>'resource'], 'pg_prepare' => ['resource|false', 'connection'=>'resource', 'stmtname'=>'string', 'query'=>'string'], 'pg_prepare\'1' => ['resource|false', 'stmtname'=>'string', 'query'=>'string'], 'pg_put_line' => ['bool', 'connection'=>'resource', 'data'=>'string'], 'pg_put_line\'1' => ['bool', 'data'=>'string'], 'pg_query' => ['resource|false', 'connection'=>'resource', 'query'=>'string'], 'pg_query\'1' => ['resource|false', 'query'=>'string'], 'pg_query_params' => ['resource|false', 'connection'=>'resource', 'query'=>'string', 'params'=>'array'], 'pg_query_params\'1' => ['resource|false', 'query'=>'string', 'params'=>'array'], 'pg_result_error' => ['string|false', 'result'=>'resource'], 'pg_result_error_field' => ['string|?false', 'result'=>'resource', 'fieldcode'=>'int'], 'pg_result_seek' => ['bool', 'result'=>'resource', 'offset'=>'int'], 'pg_result_status' => ['mixed', 'result'=>'resource', 'result_type='=>'int'], 'pg_select' => ['string|bool', 'db'=>'resource', 'table'=>'string', 'ids'=>'array', 'options='=>'int', 'result_type='=>'int'], 'pg_send_execute' => ['bool', 'connection'=>'resource', 'stmtname'=>'string', 'params'=>'array'], 'pg_send_prepare' => ['bool', 'connection'=>'resource', 'stmtname'=>'string', 'query'=>'string'], 'pg_send_query' => ['bool', 'connection'=>'resource', 'query'=>'string'], 'pg_send_query_params' => ['bool', 'connection'=>'resource', 'query'=>'string', 'params'=>'array'], 'pg_set_client_encoding' => ['int', 'connection'=>'resource', 'encoding'=>'string'], 'pg_set_client_encoding\'1' => ['int', 'encoding'=>'string'], 'pg_set_error_verbosity' => ['int', 'connection'=>'resource', 'verbosity'=>'int'], 'pg_set_error_verbosity\'1' => ['int', 'verbosity'=>'int'], 'pg_socket' => ['resource|false', 'connection'=>'resource'], 'pg_trace' => ['bool', 'filename'=>'string', 'mode='=>'string', 'connection='=>'resource'], 'pg_transaction_status' => ['int', 'connection'=>'resource'], 'pg_tty' => ['string', 'connection='=>'resource'], 'pg_tty\'1' => ['string'], 'pg_unescape_bytea' => ['string', 'data'=>'string'], 'pg_untrace' => ['bool', 'connection='=>'resource'], 'pg_untrace\'1' => ['bool'], 'pg_update' => ['mixed', 'db'=>'resource', 'table'=>'string', 'fields'=>'array', 'ids'=>'array', 'options='=>'int'], 'pg_version' => ['array', 'connection='=>'resource'], 'Phar::__construct' => ['void', 'fname'=>'string', 'flags='=>'int', 'alias='=>'string'], 'Phar::addEmptyDir' => ['void', 'dirname'=>'string'], 'Phar::addFile' => ['void', 'file'=>'string', 'localname='=>'string'], 'Phar::addFromString' => ['void', 'localname'=>'string', 'contents'=>'string'], 'Phar::apiVersion' => ['string'], 'Phar::buildFromDirectory' => ['array', 'base_dir'=>'string', 'regex='=>'string'], 'Phar::buildFromIterator' => ['array', 'iter'=>'Iterator', 'base_directory='=>'string'], 'Phar::canCompress' => ['bool', 'method='=>'int'], 'Phar::canWrite' => ['bool'], 'Phar::compress' => ['Phar', 'compression'=>'int', 'extension='=>'string'], 'Phar::compressAllFilesBZIP2' => ['bool'], 'Phar::compressAllFilesGZ' => ['bool'], 'Phar::compressFiles' => ['void', 'compression'=>'int'], 'Phar::convertToData' => ['PharData', 'format='=>'int', 'compression='=>'int', 'extension='=>'string'], 'Phar::convertToExecutable' => ['Phar', 'format='=>'int', 'compression='=>'int', 'extension='=>'string'], 'Phar::copy' => ['bool', 'oldfile'=>'string', 'newfile'=>'string'], 'Phar::count' => ['int'], 'Phar::createDefaultStub' => ['string', 'indexfile='=>'string', 'webindexfile='=>'string'], 'Phar::decompress' => ['Phar', 'extension='=>'string'], 'Phar::decompressFiles' => ['bool'], 'Phar::delete' => ['bool', 'entry'=>'string'], 'Phar::delMetadata' => ['bool'], 'Phar::extractTo' => ['bool', 'pathto'=>'string', 'files='=>'string|array|null', 'overwrite='=>'bool'], 'Phar::getAlias' => ['string'], 'Phar::getMetadata' => ['mixed'], 'Phar::getModified' => ['bool'], 'Phar::getPath' => ['string'], 'Phar::getSignature' => ['array{hash:string, hash_type:string}'], 'Phar::getStub' => ['string'], 'Phar::getSupportedCompression' => ['array'], 'Phar::getSupportedSignatures' => ['array'], 'Phar::getVersion' => ['string'], 'Phar::hasMetadata' => ['bool'], 'Phar::interceptFileFuncs' => ['void'], 'Phar::isBuffering' => ['bool'], 'Phar::isCompressed' => ['mixed|false'], 'Phar::isFileFormat' => ['bool', 'format'=>'int'], 'Phar::isValidPharFilename' => ['bool', 'filename'=>'string', 'executable='=>'bool'], 'Phar::isWritable' => ['bool'], 'Phar::loadPhar' => ['bool', 'filename'=>'string', 'alias='=>'string'], 'Phar::mapPhar' => ['bool', 'alias='=>'string', 'dataoffset='=>'int'], 'Phar::mount' => ['void', 'pharpath'=>'string', 'externalpath'=>'string'], 'Phar::mungServer' => ['void', 'munglist'=>'array'], 'Phar::offsetExists' => ['bool', 'offset'=>'string'], 'Phar::offsetGet' => ['PharFileInfo', 'offset'=>'string'], 'Phar::offsetSet' => ['void', 'offset'=>'string', 'value'=>'string'], 'Phar::offsetUnset' => ['bool', 'offset'=>'string'], 'Phar::running' => ['string', 'retphar='=>'bool'], 'Phar::setAlias' => ['bool', 'alias'=>'string'], 'Phar::setDefaultStub' => ['bool', 'index='=>'string', 'webindex='=>'string'], 'Phar::setMetadata' => ['void', 'metadata'=>''], 'Phar::setSignatureAlgorithm' => ['void', 'sigtype'=>'int', 'privatekey='=>'string'], 'Phar::setStub' => ['bool', 'stub'=>'string', 'length='=>'int'], 'Phar::startBuffering' => ['void'], 'Phar::stopBuffering' => ['void'], 'Phar::uncompressAllFiles' => ['bool'], 'Phar::unlinkArchive' => ['bool', 'archive'=>'string'], 'Phar::webPhar' => ['', 'alias='=>'string', 'index='=>'string', 'f404='=>'string', 'mimetypes='=>'array', 'rewrites='=>'array'], 'PharData::__construct' => ['void', 'fname'=>'string', 'flags='=>'?int', 'alias='=>'?string', 'format='=>'int'], 'PharData::addEmptyDir' => ['bool', 'dirname'=>'string'], 'PharData::addFile' => ['void', 'file'=>'string', 'localname='=>'string'], 'PharData::addFromString' => ['bool', 'localname'=>'string', 'contents'=>'string'], 'PharData::buildFromDirectory' => ['array', 'base_dir'=>'string', 'regex='=>'string'], 'PharData::buildFromIterator' => ['array', 'iter'=>'Iterator', 'base_directory='=>'string'], 'PharData::compress' => ['PharData', 'compression'=>'int', 'extension='=>'string'], 'PharData::compressFiles' => ['bool', 'compression'=>'int'], 'PharData::convertToData' => ['PharData', 'format='=>'int', 'compression='=>'int', 'extension='=>'string'], 'PharData::convertToExecutable' => ['Phar', 'format='=>'int', 'compression='=>'int', 'extension='=>'string'], 'PharData::copy' => ['bool', 'oldfile'=>'string', 'newfile'=>'string'], 'PharData::decompress' => ['PharData', 'extension='=>'string'], 'PharData::decompressFiles' => ['bool'], 'PharData::delete' => ['bool', 'entry'=>'string'], 'PharData::delMetadata' => ['bool'], 'PharData::extractTo' => ['bool', 'pathto'=>'string', 'files='=>'string|array|null', 'overwrite='=>'bool'], 'PharData::isWritable' => ['bool'], 'PharData::offsetExists' => ['bool', 'offset'=>'string'], 'PharData::offsetGet' => ['PharFileInfo', 'offset'=>'string'], 'PharData::offsetSet' => ['void', 'offset'=>'string', 'value'=>'string'], 'PharData::offsetUnset' => ['bool', 'offset'=>'string'], 'PharData::setAlias' => ['bool', 'alias'=>'string'], 'PharData::setDefaultStub' => ['bool', 'index='=>'string', 'webindex='=>'string'], 'phardata::setMetadata' => ['void', 'metadata'=>'mixed'], 'phardata::setSignatureAlgorithm' => ['void', 'sigtype'=>'int'], 'PharData::setStub' => ['bool', 'stub'=>'string', 'length='=>'int'], 'PharFileInfo::__construct' => ['void', 'entry'=>'string'], 'PharFileInfo::chmod' => ['void', 'permissions'=>'int'], 'PharFileInfo::compress' => ['bool', 'compression'=>'int'], 'PharFileInfo::decompress' => ['bool'], 'PharFileInfo::delMetadata' => ['bool'], 'PharFileInfo::getCompressedSize' => ['int'], 'PharFileInfo::getContent' => ['string'], 'PharFileInfo::getCRC32' => ['int'], 'PharFileInfo::getMetadata' => ['mixed'], 'PharFileInfo::getPharFlags' => ['int'], 'PharFileInfo::hasMetadata' => ['bool'], 'PharFileInfo::isCompressed' => ['bool', 'compression_type='=>'int'], 'PharFileInfo::isCompressedBZIP2' => ['bool'], 'PharFileInfo::isCompressedGZ' => ['bool'], 'PharFileInfo::isCRCChecked' => ['bool'], 'PharFileInfo::setCompressedBZIP2' => ['bool'], 'PharFileInfo::setCompressedGZ' => ['bool'], 'PharFileInfo::setMetadata' => ['void', 'metadata'=>'mixed'], 'PharFileInfo::setUncompressed' => ['bool'], 'phdfs::__construct' => ['void', 'ip'=>'string', 'port'=>'string'], 'phdfs::__destruct' => ['void'], 'phdfs::connect' => ['bool'], 'phdfs::copy' => ['bool', 'source_file'=>'string', 'destination_file'=>'string'], 'phdfs::create_directory' => ['bool', 'path'=>'string'], 'phdfs::delete' => ['bool', 'path'=>'string'], 'phdfs::disconnect' => ['bool'], 'phdfs::exists' => ['bool', 'path'=>'string'], 'phdfs::file_info' => ['array', 'path'=>'string'], 'phdfs::list_directory' => ['array', 'path'=>'string'], 'phdfs::read' => ['string', 'path'=>'string', 'length='=>'string'], 'phdfs::rename' => ['bool', 'old_path'=>'string', 'new_path'=>'string'], 'phdfs::tell' => ['int', 'path'=>'string'], 'phdfs::write' => ['bool', 'path'=>'string', 'buffer'=>'string', 'mode='=>'string'], 'php_check_syntax' => ['bool', 'filename'=>'string', 'error_message='=>'string'], 'php_ini_loaded_file' => ['string|false'], 'php_ini_scanned_files' => ['string|false'], 'php_logo_guid' => ['string'], 'php_sapi_name' => ['string'], 'php_strip_whitespace' => ['string', 'file_name'=>'string'], 'php_uname' => ['string', 'mode='=>'string'], 'php_user_filter::filter' => ['int', 'in'=>'resource', 'out'=>'resource', '&rw_consumed'=>'int', 'closing'=>'bool'], 'php_user_filter::onClose' => ['void'], 'php_user_filter::onCreate' => ['bool'], 'phpcredits' => ['bool', 'flag='=>'int'], 'phpdbg_break_file' => ['void', 'file'=>'string', 'line'=>'int'], 'phpdbg_break_function' => ['void', 'function'=>'string'], 'phpdbg_break_method' => ['void', 'class'=>'string', 'method'=>'string'], 'phpdbg_break_next' => ['void'], 'phpdbg_clear' => ['void'], 'phpdbg_color' => ['void', 'element'=>'int', 'color'=>'string'], 'phpdbg_end_oplog' => ['array', 'options='=>'array'], 'phpdbg_exec' => ['mixed', 'context='=>'string'], 'phpdbg_get_executable' => ['array', 'options='=>'array'], 'phpdbg_prompt' => ['void', 'prompt'=>'string'], 'phpdbg_start_oplog' => ['void'], 'phpinfo' => ['bool', 'what='=>'int'], 'phpversion' => ['string|false', 'extension='=>'string'], 'pht\AtomicInteger::__construct' => ['void', 'value='=>'int'], 'pht\AtomicInteger::dec' => ['void'], 'pht\AtomicInteger::get' => ['int'], 'pht\AtomicInteger::inc' => ['void'], 'pht\AtomicInteger::lock' => ['void'], 'pht\AtomicInteger::set' => ['void', 'value'=>'int'], 'pht\AtomicInteger::unlock' => ['void'], 'pht\HashTable::lock' => ['void'], 'pht\HashTable::size' => ['int'], 'pht\HashTable::unlock' => ['void'], 'pht\Queue::front' => ['mixed'], 'pht\Queue::lock' => ['void'], 'pht\Queue::pop' => ['mixed'], 'pht\Queue::push' => ['void', 'value'=>'mixed'], 'pht\Queue::size' => ['int'], 'pht\Queue::unlock' => ['void'], 'pht\Runnable::run' => ['void'], 'pht\thread::addClassTask' => ['void', 'className'=>'string', '...ctorArgs='=>'mixed'], 'pht\thread::addFileTask' => ['void', 'fileName'=>'string', '...globals='=>'mixed'], 'pht\thread::addFunctionTask' => ['void', 'func'=>'callable', '...funcArgs='=>'mixed'], 'pht\thread::join' => ['void'], 'pht\thread::start' => ['void'], 'pht\thread::taskCount' => ['int'], 'pht\threaded::lock' => ['void'], 'pht\threaded::unlock' => ['void'], 'pht\Vector::__construct' => ['void', 'size='=>'int', 'value='=>'mixed'], 'pht\Vector::deleteAt' => ['void', 'offset'=>'int'], 'pht\Vector::insertAt' => ['void', 'value'=>'mixed', 'offset'=>'int'], 'pht\Vector::lock' => ['void'], 'pht\Vector::pop' => ['mixed'], 'pht\Vector::push' => ['void', 'value'=>'mixed'], 'pht\Vector::resize' => ['void', 'size'=>'int', 'value='=>'mixed'], 'pht\Vector::shift' => ['mixed'], 'pht\Vector::size' => ['int'], 'pht\Vector::unlock' => ['void'], 'pht\Vector::unshift' => ['void', 'value'=>'mixed'], 'pht\Vector::updateAt' => ['void', 'value'=>'mixed', 'offset'=>'int'], 'pi' => ['float'], 'png2wbmp' => ['bool', 'pngname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'], 'pointObj::__construct' => ['void'], 'pointObj::distanceToLine' => ['float', 'p1'=>'pointObj', 'p2'=>'pointObj'], 'pointObj::distanceToPoint' => ['float', 'poPoint'=>'pointObj'], 'pointObj::distanceToShape' => ['float', 'shape'=>'shapeObj'], 'pointObj::draw' => ['int', 'map'=>'mapObj', 'layer'=>'layerObj', 'img'=>'imageObj', 'class_index'=>'int', 'text'=>'string'], 'pointObj::ms_newPointObj' => ['pointObj'], 'pointObj::project' => ['int', 'in'=>'projectionObj', 'out'=>'projectionObj'], 'pointObj::setXY' => ['int', 'x'=>'float', 'y'=>'float', 'm'=>'float'], 'pointObj::setXYZ' => ['int', 'x'=>'float', 'y'=>'float', 'z'=>'float', 'm'=>'float'], 'Pool::__construct' => ['void', 'size'=>'int', 'class'=>'string', 'ctor='=>'array'], 'Pool::collect' => ['int', 'collector='=>'Callable'], 'Pool::resize' => ['void', 'size'=>'int'], 'Pool::shutdown' => ['void'], 'Pool::submit' => ['int', 'task'=>'Threaded'], 'Pool::submitTo' => ['int', 'worker'=>'int', 'task'=>'Threaded'], 'popen' => ['resource|false', 'command'=>'string', 'mode'=>'string'], 'pos' => ['mixed', 'array'=>'array'], 'posix_access' => ['bool', 'file'=>'string', 'mode='=>'int'], 'posix_ctermid' => ['string|false'], 'posix_errno' => ['int'], 'posix_get_last_error' => ['int'], 'posix_getcwd' => ['string'], 'posix_getegid' => ['int'], 'posix_geteuid' => ['int'], 'posix_getgid' => ['int'], 'posix_getgrgid' => ['array', 'gid'=>'int'], 'posix_getgrnam' => ['array|false', 'groupname'=>'string'], 'posix_getgroups' => ['array'], 'posix_getlogin' => ['string'], 'posix_getpgid' => ['int|false', 'pid'=>'int'], 'posix_getpgrp' => ['int'], 'posix_getpid' => ['int'], 'posix_getppid' => ['int'], 'posix_getpwnam' => ['array|false', 'groupname'=>'string'], 'posix_getpwuid' => ['array', 'uid'=>'int'], 'posix_getrlimit' => ['array'], 'posix_getsid' => ['int', 'pid'=>'int'], 'posix_getuid' => ['int'], 'posix_initgroups' => ['bool', 'name'=>'string', 'base_group_id'=>'int'], 'posix_isatty' => ['bool', 'fd'=>'resource|int'], 'posix_kill' => ['bool', 'pid'=>'int', 'sig'=>'int'], 'posix_mkfifo' => ['bool', 'pathname'=>'string', 'mode'=>'int'], 'posix_mknod' => ['bool', 'pathname'=>'string', 'mode'=>'int', 'major='=>'int', 'minor='=>'int'], 'posix_setegid' => ['bool', 'uid'=>'int'], 'posix_seteuid' => ['bool', 'uid'=>'int'], 'posix_setgid' => ['bool', 'uid'=>'int'], 'posix_setpgid' => ['bool', 'pid'=>'int', 'pgid'=>'int'], 'posix_setrlimit' => ['bool', 'resource'=>'int', 'softlimit'=>'int', 'hardlimit'=>'int'], 'posix_setsid' => ['int'], 'posix_setuid' => ['bool', 'uid'=>'int'], 'posix_strerror' => ['string', 'errno'=>'int'], 'posix_times' => ['array'], 'posix_ttyname' => ['string|false', 'fd'=>'resource|int'], 'posix_uname' => ['array'], 'Postal\Expand::expand_address' => ['string[]', 'address'=>'string', 'options='=>'array'], 'Postal\Parser::parse_address' => ['array', 'address'=>'string', 'options='=>'array'], 'pow' => ['float|int', 'base'=>'int|float', 'exponent'=>'int|float'], 'preg_filter' => ['null|string|string[]', 'regex'=>'mixed', 'replace'=>'mixed', 'subject'=>'mixed', 'limit='=>'int', '&w_count='=>'int'], 'preg_grep' => ['array|false', 'regex'=>'string', 'input'=>'array', 'flags='=>'int'], 'preg_last_error' => ['int'], 'preg_match' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_subpatterns='=>'string[]', 'flags='=>'0|', 'offset='=>'int'], 'preg_match\'1' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_subpatterns='=>'array', 'flags='=>'int', 'offset='=>'int'], 'preg_match_all' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_subpatterns='=>'array', 'flags='=>'int', 'offset='=>'int'], 'preg_quote' => ['string', 'string'=>'string', 'delim_char='=>'string'], 'preg_replace' => ['string|string[]|null', 'regex'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_replace_callback' => ['string|null', 'regex'=>'string|array', 'callback'=>'callable(array):string', 'subject'=>'string', 'limit='=>'int', '&w_count='=>'int'], 'preg_replace_callback\'1' => ['string[]|null', 'regex'=>'string|array', 'callback'=>'callable(array):string', 'subject'=>'string[]', 'limit='=>'int', '&w_count='=>'int'], 'preg_replace_callback_array' => ['string|string[]|null', 'pattern'=>'array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_split' => ['list|false', 'pattern'=>'string', 'subject'=>'string', 'limit'=>'int', 'flags='=>'null'], 'preg_split\'1' => ['list|list>|false', 'pattern'=>'string', 'subject'=>'string', 'limit='=>'int', 'flags='=>'int'], 'prev' => ['mixed', '&r_array'=>'array|object'], 'print' => ['int', 'arg'=>'string'], 'print_r' => ['string', 'value'=>'mixed'], 'print_r\'1' => ['true', 'value'=>'mixed', 'return='=>'bool'], 'printf' => ['int', 'format'=>'string', '...args='=>'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'], 'proc_open' => ['resource|false', 'command'=>'string|array', 'descriptorspec'=>'array', '&w_pipes'=>'resource[]', 'cwd='=>'?string', 'env='=>'?array', 'other_options='=>'array'], 'proc_terminate' => ['bool', 'process'=>'resource', 'signal='=>'int'], 'projectionObj::__construct' => ['void', 'projectionString'=>'string'], 'projectionObj::getUnits' => ['int'], 'projectionObj::ms_newProjectionObj' => ['projectionObj', 'projectionString'=>'string'], 'property_exists' => ['bool', 'object_or_class'=>'object|string', 'property_name'=>'string'], 'ps_add_bookmark' => ['int', 'psdoc'=>'resource', 'text'=>'string', 'parent='=>'int', 'open='=>'int'], 'ps_add_launchlink' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string'], 'ps_add_locallink' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'page'=>'int', 'dest'=>'string'], 'ps_add_note' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'contents'=>'string', 'title'=>'string', 'icon'=>'string', 'open'=>'int'], 'ps_add_pdflink' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string', 'page'=>'int', 'dest'=>'string'], 'ps_add_weblink' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'url'=>'string'], 'ps_arc' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'ps_arcn' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'ps_begin_page' => ['bool', 'psdoc'=>'resource', 'width'=>'float', 'height'=>'float'], 'ps_begin_pattern' => ['int', 'psdoc'=>'resource', 'width'=>'float', 'height'=>'float', 'xstep'=>'float', 'ystep'=>'float', 'painttype'=>'int'], 'ps_begin_template' => ['int', 'psdoc'=>'resource', 'width'=>'float', 'height'=>'float'], 'ps_circle' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'radius'=>'float'], 'ps_clip' => ['bool', 'psdoc'=>'resource'], 'ps_close' => ['bool', 'psdoc'=>'resource'], 'ps_close_image' => ['void', 'psdoc'=>'resource', 'imageid'=>'int'], 'ps_closepath' => ['bool', 'psdoc'=>'resource'], 'ps_closepath_stroke' => ['bool', 'psdoc'=>'resource'], 'ps_continue_text' => ['bool', 'psdoc'=>'resource', 'text'=>'string'], 'ps_curveto' => ['bool', 'psdoc'=>'resource', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'ps_delete' => ['bool', 'psdoc'=>'resource'], 'ps_end_page' => ['bool', 'psdoc'=>'resource'], 'ps_end_pattern' => ['bool', 'psdoc'=>'resource'], 'ps_end_template' => ['bool', 'psdoc'=>'resource'], 'ps_fill' => ['bool', 'psdoc'=>'resource'], 'ps_fill_stroke' => ['bool', 'psdoc'=>'resource'], 'ps_findfont' => ['int', 'psdoc'=>'resource', 'fontname'=>'string', 'encoding'=>'string', 'embed='=>'bool'], 'ps_get_buffer' => ['string', 'psdoc'=>'resource'], 'ps_get_parameter' => ['string', 'psdoc'=>'resource', 'name'=>'string', 'modifier='=>'float'], 'ps_get_value' => ['float', 'psdoc'=>'resource', 'name'=>'string', 'modifier='=>'float'], 'ps_hyphenate' => ['array', 'psdoc'=>'resource', 'text'=>'string'], 'ps_include_file' => ['bool', 'psdoc'=>'resource', 'file'=>'string'], 'ps_lineto' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'ps_makespotcolor' => ['int', 'psdoc'=>'resource', 'name'=>'string', 'reserved='=>'int'], 'ps_moveto' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'ps_new' => ['resource'], 'ps_open_file' => ['bool', 'psdoc'=>'resource', 'filename='=>'string'], 'ps_open_image' => ['int', 'psdoc'=>'resource', 'type'=>'string', 'source'=>'string', 'data'=>'string', 'length'=>'int', 'width'=>'int', 'height'=>'int', 'components'=>'int', 'bpc'=>'int', 'params'=>'string'], 'ps_open_image_file' => ['int', 'psdoc'=>'resource', 'type'=>'string', 'filename'=>'string', 'stringparam='=>'string', 'intparam='=>'int'], 'ps_open_memory_image' => ['int', 'psdoc'=>'resource', 'gd'=>'int'], 'ps_place_image' => ['bool', 'psdoc'=>'resource', 'imageid'=>'int', 'x'=>'float', 'y'=>'float', 'scale'=>'float'], 'ps_rect' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'ps_restore' => ['bool', 'psdoc'=>'resource'], 'ps_rotate' => ['bool', 'psdoc'=>'resource', 'rot'=>'float'], 'ps_save' => ['bool', 'psdoc'=>'resource'], 'ps_scale' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'ps_set_border_color' => ['bool', 'psdoc'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'ps_set_border_dash' => ['bool', 'psdoc'=>'resource', 'black'=>'float', 'white'=>'float'], 'ps_set_border_style' => ['bool', 'psdoc'=>'resource', 'style'=>'string', 'width'=>'float'], 'ps_set_info' => ['bool', 'p'=>'resource', 'key'=>'string', 'value'=>'string'], 'ps_set_parameter' => ['bool', 'psdoc'=>'resource', 'name'=>'string', 'value'=>'string'], 'ps_set_text_pos' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'ps_set_value' => ['bool', 'psdoc'=>'resource', 'name'=>'string', 'value'=>'float'], 'ps_setcolor' => ['bool', 'psdoc'=>'resource', 'type'=>'string', 'colorspace'=>'string', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float'], 'ps_setdash' => ['bool', 'psdoc'=>'resource', 'on'=>'float', 'off'=>'float'], 'ps_setflat' => ['bool', 'psdoc'=>'resource', 'value'=>'float'], 'ps_setfont' => ['bool', 'psdoc'=>'resource', 'fontid'=>'int', 'size'=>'float'], 'ps_setgray' => ['bool', 'psdoc'=>'resource', 'gray'=>'float'], 'ps_setlinecap' => ['bool', 'psdoc'=>'resource', 'type'=>'int'], 'ps_setlinejoin' => ['bool', 'psdoc'=>'resource', 'type'=>'int'], 'ps_setlinewidth' => ['bool', 'psdoc'=>'resource', 'width'=>'float'], 'ps_setmiterlimit' => ['bool', 'psdoc'=>'resource', 'value'=>'float'], 'ps_setoverprintmode' => ['bool', 'psdoc'=>'resource', 'mode'=>'int'], 'ps_setpolydash' => ['bool', 'psdoc'=>'resource', 'arr'=>'float'], 'ps_shading' => ['int', 'psdoc'=>'resource', 'type'=>'string', 'x0'=>'float', 'y0'=>'float', 'x1'=>'float', 'y1'=>'float', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float', 'optlist'=>'string'], 'ps_shading_pattern' => ['int', 'psdoc'=>'resource', 'shadingid'=>'int', 'optlist'=>'string'], 'ps_shfill' => ['bool', 'psdoc'=>'resource', 'shadingid'=>'int'], 'ps_show' => ['bool', 'psdoc'=>'resource', 'text'=>'string'], 'ps_show2' => ['bool', 'psdoc'=>'resource', 'text'=>'string', 'length'=>'int'], 'ps_show_boxed' => ['int', 'psdoc'=>'resource', 'text'=>'string', 'left'=>'float', 'bottom'=>'float', 'width'=>'float', 'height'=>'float', 'hmode'=>'string', 'feature='=>'string'], 'ps_show_xy' => ['bool', 'psdoc'=>'resource', 'text'=>'string', 'x'=>'float', 'y'=>'float'], 'ps_show_xy2' => ['bool', 'psdoc'=>'resource', 'text'=>'string', 'length'=>'int', 'xcoor'=>'float', 'ycoor'=>'float'], 'ps_string_geometry' => ['array', 'psdoc'=>'resource', 'text'=>'string', 'fontid='=>'int', 'size='=>'float'], 'ps_stringwidth' => ['float', 'psdoc'=>'resource', 'text'=>'string', 'fontid='=>'int', 'size='=>'float'], 'ps_stroke' => ['bool', 'psdoc'=>'resource'], 'ps_symbol' => ['bool', 'psdoc'=>'resource', 'ord'=>'int'], 'ps_symbol_name' => ['string', 'psdoc'=>'resource', 'ord'=>'int', 'fontid='=>'int'], 'ps_symbol_width' => ['float', 'psdoc'=>'resource', 'ord'=>'int', 'fontid='=>'int', 'size='=>'float'], 'ps_translate' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'pspell_add_to_personal' => ['bool', 'pspell'=>'int', 'word'=>'string'], 'pspell_add_to_session' => ['bool', 'pspell'=>'int', 'word'=>'string'], 'pspell_check' => ['bool', 'pspell'=>'int', 'word'=>'string'], 'pspell_clear_session' => ['bool', 'pspell'=>'int'], 'pspell_config_create' => ['int|false', 'language'=>'string', 'spelling='=>'string', 'jargon='=>'string', 'encoding='=>'string'], 'pspell_config_data_dir' => ['bool', 'conf'=>'int', 'directory'=>'string'], 'pspell_config_dict_dir' => ['bool', 'conf'=>'int', 'directory'=>'string'], 'pspell_config_ignore' => ['bool', 'conf'=>'int', 'ignore'=>'int'], 'pspell_config_mode' => ['bool', 'conf'=>'int', 'mode'=>'int'], 'pspell_config_personal' => ['bool', 'conf'=>'int', 'personal'=>'string'], 'pspell_config_repl' => ['bool', 'conf'=>'int', 'repl'=>'string'], 'pspell_config_runtogether' => ['bool', 'conf'=>'int', 'runtogether'=>'bool'], 'pspell_config_save_repl' => ['bool', 'conf'=>'int', 'save'=>'bool'], 'pspell_new' => ['int|false', 'language'=>'string', 'spelling='=>'string', 'jargon='=>'string', 'encoding='=>'string', 'mode='=>'int'], 'pspell_new_config' => ['int|false', 'config'=>'int'], 'pspell_new_personal' => ['int|false', 'personal'=>'string', 'language'=>'string', 'spelling='=>'string', 'jargon='=>'string', 'encoding='=>'string', 'mode='=>'int'], 'pspell_save_wordlist' => ['bool', 'pspell'=>'int'], 'pspell_store_replacement' => ['bool', 'pspell'=>'int', 'misspell'=>'string', 'correct'=>'string'], 'pspell_suggest' => ['array', 'pspell'=>'int', 'word'=>'string'], 'putenv' => ['bool', 'setting'=>'string'], 'px_close' => ['bool', 'pxdoc'=>'resource'], 'px_create_fp' => ['bool', 'pxdoc'=>'resource', 'file'=>'resource', 'fielddesc'=>'array'], 'px_date2string' => ['string', 'pxdoc'=>'resource', 'value'=>'int', 'format'=>'string'], 'px_delete' => ['bool', 'pxdoc'=>'resource'], 'px_delete_record' => ['bool', 'pxdoc'=>'resource', 'num'=>'int'], 'px_get_field' => ['array', 'pxdoc'=>'resource', 'fieldno'=>'int'], 'px_get_info' => ['array', 'pxdoc'=>'resource'], 'px_get_parameter' => ['string', 'pxdoc'=>'resource', 'name'=>'string'], 'px_get_record' => ['array', 'pxdoc'=>'resource', 'num'=>'int', 'mode='=>'int'], 'px_get_schema' => ['array', 'pxdoc'=>'resource', 'mode='=>'int'], 'px_get_value' => ['float', 'pxdoc'=>'resource', 'name'=>'string'], 'px_insert_record' => ['int', 'pxdoc'=>'resource', 'data'=>'array'], 'px_new' => ['resource'], 'px_numfields' => ['int', 'pxdoc'=>'resource'], 'px_numrecords' => ['int', 'pxdoc'=>'resource'], 'px_open_fp' => ['bool', 'pxdoc'=>'resource', 'file'=>'resource'], 'px_put_record' => ['bool', 'pxdoc'=>'resource', 'record'=>'array', 'recpos='=>'int'], 'px_retrieve_record' => ['array', 'pxdoc'=>'resource', 'num'=>'int', 'mode='=>'int'], 'px_set_blob_file' => ['bool', 'pxdoc'=>'resource', 'filename'=>'string'], 'px_set_parameter' => ['bool', 'pxdoc'=>'resource', 'name'=>'string', 'value'=>'string'], 'px_set_tablename' => ['void', 'pxdoc'=>'resource', 'name'=>'string'], 'px_set_targetencoding' => ['bool', 'pxdoc'=>'resource', 'encoding'=>'string'], 'px_set_value' => ['bool', 'pxdoc'=>'resource', 'name'=>'string', 'value'=>'float'], 'px_timestamp2string' => ['string', 'pxdoc'=>'resource', 'value'=>'float', 'format'=>'string'], 'px_update_record' => ['bool', 'pxdoc'=>'resource', 'data'=>'array', 'num'=>'int'], 'qdom_error' => ['string'], 'qdom_tree' => ['QDomDocument', 'doc'=>'string'], 'querymapObj::convertToString' => ['string'], 'querymapObj::free' => ['void'], 'querymapObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'querymapObj::updateFromString' => ['int', 'snippet'=>'string'], 'QuickHashIntHash::__construct' => ['void', 'size'=>'int', 'options='=>'int'], 'QuickHashIntHash::add' => ['bool', 'key'=>'int', 'value='=>'int'], 'QuickHashIntHash::delete' => ['bool', 'key'=>'int'], 'QuickHashIntHash::exists' => ['bool', 'key'=>'int'], 'QuickHashIntHash::get' => ['int', 'key'=>'int'], 'QuickHashIntHash::getSize' => ['int'], 'QuickHashIntHash::loadFromFile' => ['QuickHashIntHash', 'filename'=>'string', 'options='=>'int'], 'QuickHashIntHash::loadFromString' => ['QuickHashIntHash', 'contents'=>'string', 'options='=>'int'], 'QuickHashIntHash::saveToFile' => ['void', 'filename'=>'string'], 'QuickHashIntHash::saveToString' => ['string'], 'QuickHashIntHash::set' => ['bool', 'key'=>'int', 'value'=>'int'], 'QuickHashIntHash::update' => ['bool', 'key'=>'int', 'value'=>'int'], 'QuickHashIntSet::__construct' => ['void', 'size'=>'int', 'options='=>'int'], 'QuickHashIntSet::add' => ['bool', 'key'=>'int'], 'QuickHashIntSet::delete' => ['bool', 'key'=>'int'], 'QuickHashIntSet::exists' => ['bool', 'key'=>'int'], 'QuickHashIntSet::getSize' => ['int'], 'QuickHashIntSet::loadFromFile' => ['QuickHashIntSet', 'filename'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashIntSet::loadFromString' => ['QuickHashIntSet', 'contents'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashIntSet::saveToFile' => ['void', 'filename'=>'string'], 'QuickHashIntSet::saveToString' => ['string'], 'QuickHashIntStringHash::__construct' => ['void', 'size'=>'int', 'options='=>'int'], 'QuickHashIntStringHash::add' => ['bool', 'key'=>'int', 'value'=>'string'], 'QuickHashIntStringHash::delete' => ['bool', 'key'=>'int'], 'QuickHashIntStringHash::exists' => ['bool', 'key'=>'int'], 'QuickHashIntStringHash::get' => ['mixed', 'key'=>'int'], 'QuickHashIntStringHash::getSize' => ['int'], 'QuickHashIntStringHash::loadFromFile' => ['QuickHashIntStringHash', 'filename'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashIntStringHash::loadFromString' => ['QuickHashIntStringHash', 'contents'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashIntStringHash::saveToFile' => ['void', 'filename'=>'string'], 'QuickHashIntStringHash::saveToString' => ['string'], 'QuickHashIntStringHash::set' => ['int', 'key'=>'int', 'value'=>'string'], 'QuickHashIntStringHash::update' => ['bool', 'key'=>'int', 'value'=>'string'], 'QuickHashStringIntHash::__construct' => ['void', 'size'=>'int', 'options='=>'int'], 'QuickHashStringIntHash::add' => ['bool', 'key'=>'string', 'value'=>'int'], 'QuickHashStringIntHash::delete' => ['bool', 'key'=>'string'], 'QuickHashStringIntHash::exists' => ['bool', 'key'=>'string'], 'QuickHashStringIntHash::get' => ['mixed', 'key'=>'string'], 'QuickHashStringIntHash::getSize' => ['int'], 'QuickHashStringIntHash::loadFromFile' => ['QuickHashStringIntHash', 'filename'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashStringIntHash::loadFromString' => ['QuickHashStringIntHash', 'contents'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashStringIntHash::saveToFile' => ['void', 'filename'=>'string'], 'QuickHashStringIntHash::saveToString' => ['string'], 'QuickHashStringIntHash::set' => ['int', 'key'=>'string', 'value'=>'int'], 'QuickHashStringIntHash::update' => ['bool', 'key'=>'string', 'value'=>'int'], 'quoted_printable_decode' => ['string', 'string'=>'string'], 'quoted_printable_encode' => ['string', 'string'=>'string'], 'quotemeta' => ['string', 'string'=>'string'], 'rad2deg' => ['float', 'number'=>'float'], 'radius_acct_open' => ['resource|false'], 'radius_add_server' => ['bool', 'radius_handle'=>'resource', 'hostname'=>'string', 'port'=>'int', 'secret'=>'string', 'timeout'=>'int', 'max_tries'=>'int'], 'radius_auth_open' => ['resource|false'], 'radius_close' => ['bool', 'radius_handle'=>'resource'], 'radius_config' => ['bool', 'radius_handle'=>'resource', 'file'=>'string'], 'radius_create_request' => ['bool', 'radius_handle'=>'resource', 'type'=>'int'], 'radius_cvt_addr' => ['string', 'data'=>'string'], 'radius_cvt_int' => ['int', 'data'=>'string'], 'radius_cvt_string' => ['string', 'data'=>'string'], 'radius_demangle' => ['string', 'radius_handle'=>'resource', 'mangled'=>'string'], 'radius_demangle_mppe_key' => ['string', 'radius_handle'=>'resource', 'mangled'=>'string'], 'radius_get_attr' => ['mixed', 'radius_handle'=>'resource'], 'radius_get_tagged_attr_data' => ['string', 'data'=>'string'], 'radius_get_tagged_attr_tag' => ['int', 'data'=>'string'], 'radius_get_vendor_attr' => ['array', 'data'=>'string'], 'radius_put_addr' => ['bool', 'radius_handle'=>'resource', 'type'=>'int', 'addr'=>'string'], 'radius_put_attr' => ['bool', 'radius_handle'=>'resource', 'type'=>'int', 'value'=>'string'], 'radius_put_int' => ['bool', 'radius_handle'=>'resource', 'type'=>'int', 'value'=>'int'], 'radius_put_string' => ['bool', 'radius_handle'=>'resource', 'type'=>'int', 'value'=>'string'], 'radius_put_vendor_addr' => ['bool', 'radius_handle'=>'resource', 'vendor'=>'int', 'type'=>'int', 'addr'=>'string'], 'radius_put_vendor_attr' => ['bool', 'radius_handle'=>'resource', 'vendor'=>'int', 'type'=>'int', 'value'=>'string'], 'radius_put_vendor_int' => ['bool', 'radius_handle'=>'resource', 'vendor'=>'int', 'type'=>'int', 'value'=>'int'], 'radius_put_vendor_string' => ['bool', 'radius_handle'=>'resource', 'vendor'=>'int', 'type'=>'int', 'value'=>'string'], 'radius_request_authenticator' => ['string', 'radius_handle'=>'resource'], 'radius_salt_encrypt_attr' => ['string', 'radius_handle'=>'resource', 'data'=>'string'], 'radius_send_request' => ['int', 'radius_handle'=>'resource'], 'radius_server_secret' => ['string', 'radius_handle'=>'resource'], 'radius_strerror' => ['string', 'radius_handle'=>'resource'], 'rand' => ['int', 'min'=>'int', 'max'=>'int'], 'rand\'1' => ['int'], 'random_bytes' => ['string', 'length'=>'int'], 'random_int' => ['int', 'min'=>'int', 'max'=>'int'], 'range' => ['array', 'low'=>'mixed', 'high'=>'mixed', 'step='=>'int|float'], 'RangeException::__clone' => ['void'], 'RangeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?RangeException'], 'RangeException::__toString' => ['string'], 'RangeException::getCode' => ['int'], 'RangeException::getFile' => ['string'], 'RangeException::getLine' => ['int'], 'RangeException::getMessage' => ['string'], 'RangeException::getPrevious' => ['Throwable|RangeException|null'], 'RangeException::getTrace' => ['list>'], 'RangeException::getTraceAsString' => ['string'], 'rar_allow_broken_set' => ['bool', 'rarfile'=>'RarArchive', 'allow_broken'=>'bool'], 'rar_broken_is' => ['bool', 'rarfile'=>'rararchive'], 'rar_close' => ['bool', 'rarfile'=>'rararchive'], 'rar_comment_get' => ['string', 'rarfile'=>'rararchive'], 'rar_entry_get' => ['RarEntry', 'rarfile'=>'RarArchive', 'entryname'=>'string'], 'rar_list' => ['RarArchive', 'rarfile'=>'rararchive'], 'rar_open' => ['RarArchive', 'filename'=>'string', 'password='=>'string', 'volume_callback='=>'callable'], 'rar_solid_is' => ['bool', 'rarfile'=>'rararchive'], 'rar_wrapper_cache_stats' => ['string'], 'RarArchive::__toString' => ['string'], 'RarArchive::close' => ['bool'], 'RarArchive::getComment' => ['string|null'], 'RarArchive::getEntries' => ['RarEntry[]|false'], 'RarArchive::getEntry' => ['RarEntry|false', 'entryname'=>'string'], 'RarArchive::isBroken' => ['bool'], 'RarArchive::isSolid' => ['bool'], 'RarArchive::open' => ['RarArchive|false', 'filename'=>'string', 'password='=>'string', 'volume_callback='=>'callable'], 'RarArchive::setAllowBroken' => ['bool', 'allow_broken'=>'bool'], 'RarEntry::__toString' => ['string'], 'RarEntry::extract' => ['bool', 'dir'=>'string', 'filepath='=>'string', 'password='=>'string', 'extended_data='=>'bool'], 'RarEntry::getAttr' => ['int|false'], 'RarEntry::getCrc' => ['string|false'], 'RarEntry::getFileTime' => ['string|false'], 'RarEntry::getHostOs' => ['int|false'], 'RarEntry::getMethod' => ['int|false'], 'RarEntry::getName' => ['string|false'], 'RarEntry::getPackedSize' => ['int|false'], 'RarEntry::getStream' => ['resource|false', 'password='=>'string'], 'RarEntry::getUnpackedSize' => ['int|false'], 'RarEntry::getVersion' => ['int|false'], 'RarEntry::isDirectory' => ['bool'], 'RarEntry::isEncrypted' => ['bool'], 'RarException::getCode' => ['int'], 'RarException::getFile' => ['string'], 'RarException::getLine' => ['int'], 'RarException::getMessage' => ['string'], 'RarException::getPrevious' => ['Exception|Throwable'], 'RarException::getTrace' => ['list>'], 'RarException::getTraceAsString' => ['string'], 'RarException::isUsingExceptions' => ['bool'], 'RarException::setUsingExceptions' => ['RarEntry', 'using_exceptions'=>'bool'], 'rawurldecode' => ['string', 'string'=>'string'], 'rawurlencode' => ['string', 'string'=>'string'], 'rd_kafka_err2str' => ['string', 'err'=>'int'], 'rd_kafka_errno' => ['int'], 'rd_kafka_errno2err' => ['int', 'errnox'=>'int'], 'rd_kafka_offset_tail' => ['int', 'cnt'=>'int'], 'RdKafka::addBrokers' => ['int', 'broker_list'=>'string'], 'RdKafka::flush' => ['int', 'timeout_ms'=>'int'], 'RdKafka::getMetadata' => ['RdKafka\Metadata', 'all_topics'=>'bool', 'only_topic='=>'RdKafka\Topic', 'timeout_ms'=>'int'], 'RdKafka::getOutQLen' => ['int'], 'RdKafka::newQueue' => ['RdKafka\Queue'], 'RdKafka::newTopic' => ['RdKafka\Topic', 'topic_name'=>'string', 'topic_conf='=>'?RdKafka\TopicConf'], 'RdKafka::poll' => ['void', 'timeout_ms'=>'int'], 'RdKafka::setLogLevel' => ['void', 'level'=>'int'], 'RdKafka\Conf::dump' => ['array'], 'RdKafka\Conf::set' => ['void', 'name'=>'string', 'value'=>'string'], 'RdKafka\Conf::setDefaultTopicConf' => ['void', 'topic_conf'=>'RdKafka\TopicConf'], 'RdKafka\Conf::setDrMsgCb' => ['void', 'callback'=>'callable'], 'RdKafka\Conf::setErrorCb' => ['void', 'callback'=>'callable'], 'RdKafka\Conf::setRebalanceCb' => ['void', 'callback'=>'callable'], 'RdKafka\Conf::setStatsCb' => ['void', 'callback'=>'callable'], 'RdKafka\Consumer::__construct' => ['void', 'conf='=>'?RdKafka\Conf'], 'RdKafka\Consumer::addBrokers' => ['int', 'broker_list'=>'string'], 'RdKafka\Consumer::getMetadata' => ['RdKafka\Metadata', 'all_topics'=>'bool', 'only_topic='=>'RdKafka\Topic', 'timeout_ms'=>'int'], 'RdKafka\Consumer::getOutQLen' => ['int'], 'RdKafka\Consumer::newQueue' => ['RdKafka\Queue'], 'RdKafka\Consumer::newTopic' => ['RdKafka\ConsumerTopic', 'topic_name'=>'string', 'topic_conf='=>'?RdKafka\TopicConf'], 'RdKafka\Consumer::poll' => ['void', 'timeout_ms'=>'int'], 'RdKafka\Consumer::setLogLevel' => ['void', 'level'=>'int'], 'RdKafka\ConsumerTopic::__construct' => ['void'], 'RdKafka\ConsumerTopic::consume' => ['RdKafka\Message', 'partition'=>'int', 'timeout_ms'=>'int'], 'RdKafka\ConsumerTopic::consumeQueueStart' => ['void', 'partition'=>'int', 'offset'=>'int', 'queue'=>'RdKafka\Queue'], 'RdKafka\ConsumerTopic::consumeStart' => ['void', 'partition'=>'int', 'offset'=>'int'], 'RdKafka\ConsumerTopic::consumeStop' => ['void', 'partition'=>'int'], 'RdKafka\ConsumerTopic::getName' => ['string'], 'RdKafka\ConsumerTopic::offsetStore' => ['void', 'partition'=>'int', 'offset'=>'int'], 'RdKafka\KafkaConsumer::__construct' => ['void', 'conf'=>'RdKafka\Conf'], 'RdKafka\KafkaConsumer::assign' => ['void', 'topic_partitions='=>'RdKafka\TopicPartition[]|null'], 'RdKafka\KafkaConsumer::commit' => ['void', 'message_or_offsets='=>'RdKafka\Message|RdKafka\TopicPartition[]|null'], 'RdKafka\KafkaConsumer::commitAsync' => ['void', 'message_or_offsets='=>'string'], 'RdKafka\KafkaConsumer::consume' => ['RdKafka\Message', 'timeout_ms'=>'int'], 'RdKafka\KafkaConsumer::getAssignment' => ['RdKafka\TopicPartition[]'], 'RdKafka\KafkaConsumer::getMetadata' => ['RdKafka\Metadata', 'all_topics'=>'bool', 'only_topic='=>'RdKafka\KafkaConsumerTopic', 'timeout_ms'=>'int'], 'RdKafka\KafkaConsumer::getSubscription' => ['array'], 'RdKafka\KafkaConsumer::subscribe' => ['void', 'topics'=>'array'], 'RdKafka\KafkaConsumer::unsubscribe' => ['void'], 'RdKafka\KafkaConsumerTopic::getName' => ['string'], 'RdKafka\KafkaConsumerTopic::offsetStore' => ['void', 'partition'=>'int', 'offset'=>'int'], 'RdKafka\Message::errstr' => ['string'], 'RdKafka\Metadata::getBrokers' => ['RdKafka\Metadata\Collection'], 'RdKafka\Metadata::getOrigBrokerId' => ['int'], 'RdKafka\Metadata::getOrigBrokerName' => ['string'], 'RdKafka\Metadata::getTopics' => ['RdKafka\Metadata\Collection|RdKafka\Metadata\Topic[]'], 'RdKafka\Metadata\Collection::__construct' => ['void'], 'RdKafka\Metadata\Collection::count' => ['int'], 'RdKafka\Metadata\Collection::current' => ['mixed'], 'RdKafka\Metadata\Collection::key' => ['mixed'], 'RdKafka\Metadata\Collection::next' => ['void'], 'RdKafka\Metadata\Collection::rewind' => ['void'], 'RdKafka\Metadata\Collection::valid' => ['bool'], 'RdKafka\Metadata\Partition::getErr' => ['mixed'], 'RdKafka\Metadata\Partition::getId' => ['int'], 'RdKafka\Metadata\Partition::getIsrs' => ['mixed'], 'RdKafka\Metadata\Partition::getLeader' => ['mixed'], 'RdKafka\Metadata\Partition::getReplicas' => ['mixed'], 'RdKafka\Metadata\Topic::getErr' => ['mixed'], 'RdKafka\Metadata\Topic::getPartitions' => ['RdKafka\Metadata\Partition[]'], 'RdKafka\Metadata\Topic::getTopic' => ['string'], 'RdKafka\Producer::__construct' => ['void', 'conf='=>'?RdKafka\Conf'], 'RdKafka\Producer::addBrokers' => ['int', 'broker_list'=>'string'], 'RdKafka\Producer::getMetadata' => ['RdKafka\Metadata', 'all_topics'=>'bool', 'only_topic='=>'RdKafka\Topic', 'timeout_ms'=>'int'], 'RdKafka\Producer::getOutQLen' => ['int'], 'RdKafka\Producer::newQueue' => ['RdKafka\Queue'], 'RdKafka\Producer::newTopic' => ['RdKafka\ProducerTopic', 'topic_name'=>'string', 'topic_conf='=>'?RdKafka\TopicConf'], 'RdKafka\Producer::poll' => ['void', 'timeout_ms'=>'int'], 'RdKafka\Producer::setLogLevel' => ['void', 'level'=>'int'], 'RdKafka\ProducerTopic::__construct' => ['void'], 'RdKafka\ProducerTopic::getName' => ['string'], 'RdKafka\ProducerTopic::produce' => ['void', 'partition'=>'int', 'msgflags'=>'int', 'payload'=>'string', 'key='=>'?string'], 'RdKafka\ProducerTopic::producev' => ['void', 'partition'=>'int', 'msgflags'=>'int', 'payload'=>'string', 'key='=>'?string', 'headers'=>'?array', 'timestamp_ms'=>'?int'], 'RdKafka\Queue::__construct' => ['void'], 'RdKafka\Queue::consume' => ['?RdKafka\Message', 'timeout_ms'=>'string'], 'RdKafka\Topic::getName' => ['string'], 'RdKafka\TopicConf::dump' => ['array'], 'RdKafka\TopicConf::set' => ['void', 'name'=>'string', 'value'=>'string'], 'RdKafka\TopicConf::setPartitioner' => ['void', 'partitioner'=>'int'], 'RdKafka\TopicPartition::__construct' => ['void', 'topic'=>'string', 'partition'=>'int', 'offset='=>'int'], 'RdKafka\TopicPartition::getOffset' => ['int'], 'RdKafka\TopicPartition::getPartition' => ['int'], 'RdKafka\TopicPartition::getTopic' => ['string'], 'RdKafka\TopicPartition::setOffset' => ['void', 'offset'=>'string'], 'RdKafka\TopicPartition::setPartition' => ['void', 'partition'=>'string'], 'RdKafka\TopicPartition::setTopic' => ['void', 'topic_name'=>'string'], 'read_exif_data' => ['array', 'filename'=>'string|resource', 'sections_needed='=>'string', 'sub_arrays='=>'bool', 'read_thumbnail='=>'bool'], 'readdir' => ['string|false', 'dir_handle='=>'resource'], 'readfile' => ['int|false', 'filename'=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'readgzfile' => ['int|false', 'filename'=>'string', 'use_include_path='=>'int'], 'readline' => ['string|false', 'prompt='=>'?string'], 'readline_add_history' => ['bool', 'prompt'=>'string'], 'readline_callback_handler_install' => ['bool', 'prompt'=>'string', 'callback'=>'callable'], 'readline_callback_handler_remove' => ['bool'], 'readline_callback_read_char' => ['void'], 'readline_clear_history' => ['bool'], 'readline_completion_function' => ['bool', 'funcname'=>'callable'], 'readline_info' => ['mixed', 'varname='=>'string', 'newvalue='=>'string|int|bool'], 'readline_list_history' => ['array'], 'readline_on_new_line' => ['void'], 'readline_read_history' => ['bool', 'filename='=>'string'], 'readline_redisplay' => ['void'], 'readline_write_history' => ['bool', 'filename='=>'string'], 'readlink' => ['string|false', 'filename'=>'string'], 'realpath' => ['string|false', 'path'=>'string'], 'realpath_cache_get' => ['array'], 'realpath_cache_size' => ['int'], 'recode' => ['string', 'request'=>'string', 'string'=>'string'], 'recode_file' => ['bool', 'request'=>'string', 'input'=>'resource', 'output'=>'resource'], 'recode_string' => ['string|false', 'request'=>'string', 'string'=>'string'], 'rectObj::__construct' => ['void'], 'rectObj::draw' => ['int', 'map'=>'mapObj', 'layer'=>'layerObj', 'img'=>'imageObj', 'class_index'=>'int', 'text'=>'string'], 'rectObj::fit' => ['float', 'width'=>'int', 'height'=>'int'], 'rectObj::ms_newRectObj' => ['rectObj'], 'rectObj::project' => ['int', 'in'=>'projectionObj', 'out'=>'projectionObj'], 'rectObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'rectObj::setextent' => ['void', 'minx'=>'float', 'miny'=>'float', 'maxx'=>'float', 'maxy'=>'float'], 'RecursiveArrayIterator::__construct' => ['void', 'array='=>'array|object', 'flags='=>'int'], 'RecursiveArrayIterator::append' => ['void', 'value'=>'mixed'], 'RecursiveArrayIterator::asort' => ['void'], 'RecursiveArrayIterator::count' => ['int'], 'RecursiveArrayIterator::current' => ['mixed'], 'RecursiveArrayIterator::getArrayCopy' => ['array'], 'RecursiveArrayIterator::getChildren' => ['RecursiveArrayIterator'], 'RecursiveArrayIterator::getFlags' => ['void'], 'RecursiveArrayIterator::hasChildren' => ['bool'], 'RecursiveArrayIterator::key' => ['false|int|string'], 'RecursiveArrayIterator::ksort' => ['void'], 'RecursiveArrayIterator::natcasesort' => ['void'], 'RecursiveArrayIterator::natsort' => ['void'], 'RecursiveArrayIterator::next' => ['void'], 'RecursiveArrayIterator::offsetExists' => ['void', 'index'=>'string'], 'RecursiveArrayIterator::offsetGet' => ['mixed', 'index'=>'string'], 'RecursiveArrayIterator::offsetSet' => ['void', 'index'=>'string', 'newval'=>'string'], 'RecursiveArrayIterator::offsetUnset' => ['void', 'index'=>'string'], 'RecursiveArrayIterator::rewind' => ['void'], 'RecursiveArrayIterator::seek' => ['void', 'position'=>'int'], 'RecursiveArrayIterator::serialize' => ['string'], 'RecursiveArrayIterator::setFlags' => ['void', 'flags'=>'string'], 'RecursiveArrayIterator::uasort' => ['void', 'cmp_function'=>'callable(mixed,mixed):int'], 'RecursiveArrayIterator::uksort' => ['void', 'cmp_function'=>'callable(mixed,mixed):int'], 'RecursiveArrayIterator::unserialize' => ['string', 'serialized'=>'string'], 'RecursiveArrayIterator::valid' => ['bool'], 'RecursiveCachingIterator::__construct' => ['void', 'it'=>'Iterator', 'flags='=>'int'], 'RecursiveCachingIterator::__toString' => ['string'], 'RecursiveCachingIterator::count' => ['int'], 'RecursiveCachingIterator::current' => ['void'], 'RecursiveCachingIterator::getCache' => ['array'], 'RecursiveCachingIterator::getChildren' => ['RecursiveCachingIterator'], 'RecursiveCachingIterator::getFlags' => ['int'], 'RecursiveCachingIterator::getInnerIterator' => ['Iterator'], 'RecursiveCachingIterator::hasChildren' => ['bool'], 'RecursiveCachingIterator::hasNext' => ['bool'], 'RecursiveCachingIterator::key' => ['bool|float|int|string'], 'RecursiveCachingIterator::next' => ['void'], 'RecursiveCachingIterator::offsetExists' => ['bool', 'index'=>'string'], 'RecursiveCachingIterator::offsetGet' => ['string', 'index'=>'string'], 'RecursiveCachingIterator::offsetSet' => ['void', 'index'=>'string', 'newval'=>'string'], 'RecursiveCachingIterator::offsetUnset' => ['void', 'index'=>'string'], 'RecursiveCachingIterator::rewind' => ['void'], 'RecursiveCachingIterator::setFlags' => ['void', 'flags'=>'int'], 'RecursiveCachingIterator::valid' => ['bool'], 'RecursiveCallbackFilterIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator', 'func'=>'callable'], 'RecursiveCallbackFilterIterator::accept' => ['bool'], 'RecursiveCallbackFilterIterator::current' => ['mixed'], 'RecursiveCallbackFilterIterator::getChildren' => ['RecursiveCallbackFilterIterator'], 'RecursiveCallbackFilterIterator::getInnerIterator' => ['Iterator'], 'RecursiveCallbackFilterIterator::hasChildren' => ['bool'], 'RecursiveCallbackFilterIterator::key' => ['bool|float|int|string'], 'RecursiveCallbackFilterIterator::next' => ['void'], 'RecursiveCallbackFilterIterator::rewind' => ['void'], 'RecursiveCallbackFilterIterator::valid' => ['bool'], 'RecursiveDirectoryIterator::__construct' => ['void', 'path'=>'string', 'flags='=>'int'], 'RecursiveDirectoryIterator::__toString' => ['string'], 'RecursiveDirectoryIterator::_bad_state_ex' => [''], 'RecursiveDirectoryIterator::current' => ['string|SplFileInfo|FilesystemIterator'], 'RecursiveDirectoryIterator::getATime' => ['int'], 'RecursiveDirectoryIterator::getBasename' => ['string', 'suffix='=>'string'], 'RecursiveDirectoryIterator::getChildren' => ['RecursiveDirectoryIterator'], 'RecursiveDirectoryIterator::getCTime' => ['int'], 'RecursiveDirectoryIterator::getExtension' => ['string'], 'RecursiveDirectoryIterator::getFileInfo' => ['SplFileInfo', 'class_name='=>'string'], 'RecursiveDirectoryIterator::getFilename' => ['string'], 'RecursiveDirectoryIterator::getFlags' => ['int'], 'RecursiveDirectoryIterator::getGroup' => ['int'], 'RecursiveDirectoryIterator::getInode' => ['int'], 'RecursiveDirectoryIterator::getLinkTarget' => ['string'], 'RecursiveDirectoryIterator::getMTime' => ['int'], 'RecursiveDirectoryIterator::getOwner' => ['int'], 'RecursiveDirectoryIterator::getPath' => ['string'], 'RecursiveDirectoryIterator::getPathInfo' => ['SplFileInfo', 'class_name='=>'string'], 'RecursiveDirectoryIterator::getPathname' => ['string'], 'RecursiveDirectoryIterator::getPerms' => ['int'], 'RecursiveDirectoryIterator::getRealPath' => ['string'], 'RecursiveDirectoryIterator::getSize' => ['int'], 'RecursiveDirectoryIterator::getSubPath' => ['string'], 'RecursiveDirectoryIterator::getSubPathname' => ['string'], 'RecursiveDirectoryIterator::getType' => ['string'], 'RecursiveDirectoryIterator::hasChildren' => ['bool', 'allow_links='=>'bool'], 'RecursiveDirectoryIterator::isDir' => ['bool'], 'RecursiveDirectoryIterator::isDot' => ['bool'], 'RecursiveDirectoryIterator::isExecutable' => ['bool'], 'RecursiveDirectoryIterator::isFile' => ['bool'], 'RecursiveDirectoryIterator::isLink' => ['bool'], 'RecursiveDirectoryIterator::isReadable' => ['bool'], 'RecursiveDirectoryIterator::isWritable' => ['bool'], 'RecursiveDirectoryIterator::key' => ['string'], 'RecursiveDirectoryIterator::next' => ['void'], 'RecursiveDirectoryIterator::openFile' => ['SplFileObject', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'RecursiveDirectoryIterator::rewind' => ['void'], 'RecursiveDirectoryIterator::seek' => ['void', 'position'=>'int'], 'RecursiveDirectoryIterator::setFileClass' => ['void', 'class_name='=>'string'], 'RecursiveDirectoryIterator::setFlags' => ['void', 'flags='=>'int'], 'RecursiveDirectoryIterator::setInfoClass' => ['void', 'class_name='=>'string'], 'RecursiveDirectoryIterator::valid' => ['bool'], 'RecursiveFilterIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator'], 'RecursiveFilterIterator::accept' => ['bool'], 'RecursiveFilterIterator::current' => ['mixed'], 'RecursiveFilterIterator::getChildren' => ['RecursiveFilterIterator'], 'RecursiveFilterIterator::getInnerIterator' => ['Iterator'], 'RecursiveFilterIterator::hasChildren' => ['bool'], 'RecursiveFilterIterator::key' => ['mixed'], 'RecursiveFilterIterator::next' => ['void'], 'RecursiveFilterIterator::rewind' => ['void'], 'RecursiveFilterIterator::valid' => ['bool'], 'RecursiveIterator::__construct' => ['void'], 'RecursiveIterator::current' => ['mixed'], 'RecursiveIterator::getChildren' => ['RecursiveIterator'], 'RecursiveIterator::hasChildren' => ['bool'], 'RecursiveIterator::key' => ['int|string'], 'RecursiveIterator::next' => ['void'], 'RecursiveIterator::rewind' => ['void'], 'RecursiveIterator::valid' => ['bool'], 'RecursiveIteratorIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator|IteratorAggregate', 'mode='=>'int', 'flags='=>'int'], 'RecursiveIteratorIterator::beginChildren' => ['void'], 'RecursiveIteratorIterator::beginIteration' => ['RecursiveIterator'], 'RecursiveIteratorIterator::callGetChildren' => ['RecursiveIterator'], 'RecursiveIteratorIterator::callHasChildren' => ['bool'], 'RecursiveIteratorIterator::current' => ['mixed'], 'RecursiveIteratorIterator::endChildren' => ['void'], 'RecursiveIteratorIterator::endIteration' => ['RecursiveIterator'], 'RecursiveIteratorIterator::getDepth' => ['int'], 'RecursiveIteratorIterator::getInnerIterator' => ['RecursiveIterator'], 'RecursiveIteratorIterator::getMaxDepth' => ['int|false'], 'RecursiveIteratorIterator::getSubIterator' => ['RecursiveIterator', 'level='=>'int'], 'RecursiveIteratorIterator::key' => ['mixed'], 'RecursiveIteratorIterator::next' => ['void'], 'RecursiveIteratorIterator::nextElement' => ['void'], 'RecursiveIteratorIterator::rewind' => ['void'], 'RecursiveIteratorIterator::setMaxDepth' => ['void', 'max_depth='=>'int'], 'RecursiveIteratorIterator::valid' => ['bool'], 'RecursiveRegexIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator', 'regex'=>'string', 'mode='=>'int', 'flags='=>'int', 'preg_flags='=>'int'], 'RecursiveRegexIterator::accept' => ['bool'], 'RecursiveRegexIterator::current' => [''], 'RecursiveRegexIterator::getChildren' => ['RecursiveRegexIterator'], 'RecursiveRegexIterator::getFlags' => ['int'], 'RecursiveRegexIterator::getInnerIterator' => [''], 'RecursiveRegexIterator::getMode' => ['int'], 'RecursiveRegexIterator::getPregFlags' => ['int'], 'RecursiveRegexIterator::getRegex' => ['string'], 'RecursiveRegexIterator::hasChildren' => ['bool'], 'RecursiveRegexIterator::key' => [''], 'RecursiveRegexIterator::next' => [''], 'RecursiveRegexIterator::rewind' => [''], 'RecursiveRegexIterator::setFlags' => ['void', 'new_flags'=>'int'], 'RecursiveRegexIterator::setMode' => ['void', 'new_mode'=>'int'], 'RecursiveRegexIterator::setPregFlags' => ['void', 'new_flags'=>'int'], 'RecursiveRegexIterator::valid' => [''], 'RecursiveTreeIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator|IteratorAggregate', 'flags='=>'int', 'cit_flags='=>'int', 'mode'=>'int'], 'RecursiveTreeIterator::beginChildren' => ['void'], 'RecursiveTreeIterator::beginIteration' => ['RecursiveIterator'], 'RecursiveTreeIterator::callGetChildren' => ['RecursiveIterator'], 'RecursiveTreeIterator::callHasChildren' => ['bool'], 'RecursiveTreeIterator::current' => ['string'], 'RecursiveTreeIterator::endChildren' => ['void'], 'RecursiveTreeIterator::endIteration' => ['void'], 'RecursiveTreeIterator::getDepth' => ['int'], 'RecursiveTreeIterator::getEntry' => ['string'], 'RecursiveTreeIterator::getInnerIterator' => ['RecursiveIterator'], 'RecursiveTreeIterator::getMaxDepth' => ['false|int'], 'RecursiveTreeIterator::getPostfix' => ['string'], 'RecursiveTreeIterator::getPrefix' => ['string'], 'RecursiveTreeIterator::getSubIterator' => ['RecursiveIterator', 'level='=>'int'], 'RecursiveTreeIterator::key' => ['string'], 'RecursiveTreeIterator::next' => ['void'], 'RecursiveTreeIterator::nextElement' => ['void'], 'RecursiveTreeIterator::rewind' => ['void'], 'RecursiveTreeIterator::setMaxDepth' => ['void', 'max_depth='=>'int'], 'RecursiveTreeIterator::setPostfix' => ['void', 'prefix'=>'string'], 'RecursiveTreeIterator::setPrefixPart' => ['void', 'part'=>'int', 'prefix'=>'string'], 'RecursiveTreeIterator::valid' => ['bool'], 'Redis::__construct' => ['void'], 'Redis::__destruct' => ['void'], 'Redis::_prefix' => ['string', 'value'=>'mixed'], 'Redis::_serialize' => ['mixed', 'value'=>'mixed'], 'Redis::_unserialize' => ['mixed', 'value'=>'string'], 'Redis::append' => ['int', 'key'=>'string', 'value'=>'string'], 'Redis::auth' => ['bool', 'password'=>'string'], 'Redis::bgRewriteAOF' => ['bool'], 'Redis::bgSave' => ['bool'], 'Redis::bitCount' => ['int', 'key'=>'string'], 'Redis::bitOp' => ['int', 'operation'=>'string', 'ret_key'=>'string', 'key'=>'string', '...other_keys='=>'string'], 'Redis::bitpos' => ['int', 'key'=>'string', 'bit'=>'int', 'start='=>'int', 'end='=>'int'], 'Redis::blPop' => ['array', 'keys'=>'string[]', 'timeout'=>'int'], 'Redis::blPop\'1' => ['array', 'key'=>'string', 'timeout_or_key'=>'int|string', '...extra_args'=>'int|string'], 'Redis::brPop' => ['array', 'keys'=>'string[]', 'timeout'=>'int'], 'Redis::brPop\'1' => ['array', 'key'=>'string', 'timeout_or_key'=>'int|string', '...extra_args'=>'int|string'], 'Redis::brpoplpush' => ['string|false', 'srcKey'=>'string', 'dstKey'=>'string', 'timeout'=>'int'], 'Redis::clearLastError' => ['bool'], 'Redis::client' => ['mixed', 'command'=>'string', 'arg='=>'string'], 'Redis::close' => ['bool'], 'Redis::command' => ['', '...args'=>''], 'Redis::config' => ['string', 'operation'=>'string', 'key'=>'string', 'value='=>'string'], 'Redis::connect' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'float', 'reserved='=>'null', 'retry_interval='=>'?int', 'read_timeout='=>'float'], 'Redis::dbSize' => ['int'], 'Redis::debug' => ['', 'key'=>''], 'Redis::decr' => ['int', 'key'=>'string'], 'Redis::decrBy' => ['int', 'key'=>'string', 'value'=>'int'], 'Redis::decrByFloat' => ['float', 'key'=>'string', 'value'=>'float'], 'Redis::del' => ['int', 'key'=>'string', '...args'=>'string'], 'Redis::del\'1' => ['int', 'key'=>'string[]'], 'Redis::delete' => ['int', 'key'=>'string', '...args'=>'string'], 'Redis::delete\'1' => ['int', 'key'=>'string[]'], 'Redis::discard' => [''], 'Redis::dump' => ['string|false', 'key'=>'string'], 'Redis::echo' => ['string', 'message'=>'string'], 'Redis::eval' => ['mixed', 'script'=>'', 'args='=>'', 'numKeys='=>''], 'Redis::evalSha' => ['mixed', 'scriptSha'=>'string', 'args='=>'array', 'numKeys='=>'int'], 'Redis::evaluate' => ['mixed', 'script'=>'string', 'args='=>'array', 'numKeys='=>'int'], 'Redis::evaluateSha' => ['', 'scriptSha'=>'string', 'args='=>'array', 'numKeys='=>'int'], 'Redis::exec' => ['array'], 'Redis::exists' => ['int', 'keys'=>'string|string[]'], 'Redis::exists\'1' => ['int', '...keys'=>'string'], 'Redis::expire' => ['bool', 'key'=>'string', 'ttl'=>'int'], 'Redis::expireAt' => ['bool', 'key'=>'string', 'expiry'=>'int'], 'Redis::flushAll' => ['bool', 'async='=>'bool'], 'Redis::flushDb' => ['bool', 'async='=>'bool'], 'Redis::geoAdd' => ['int', 'key'=>'string', 'longitude'=>'float', 'latitude'=>'float', 'member'=>'string', '...other_triples='=>'string|int|float'], 'Redis::geoDist' => ['float', 'key'=>'string', 'member1'=>'string', 'member2'=>'string', 'unit='=>'string'], 'Redis::geoHash' => ['array', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::geoPos' => ['array', 'key'=>'string', 'member'=>'string', '...members='=>'string'], 'Redis::geoRadius' => ['array|int', 'key'=>'string', 'longitude'=>'float', 'latitude'=>'float', 'radius'=>'float', 'unit'=>'float', 'options='=>'array'], 'Redis::geoRadiusByMember' => ['array|int', 'key'=>'string', 'member'=>'string', 'radius'=>'float', 'units'=>'string', 'options='=>'array'], 'Redis::get' => ['string|false', 'key'=>'string'], 'Redis::getAuth' => ['string|false|null'], 'Redis::getBit' => ['int', 'key'=>'string', 'offset'=>'int'], 'Redis::getDBNum' => ['int|false'], 'Redis::getHost' => ['string|false'], 'Redis::getKeys' => ['array', 'pattern'=>'string'], 'Redis::getLastError' => ['?string'], 'Redis::getMode' => ['int'], 'Redis::getMultiple' => ['array', 'keys'=>'string[]'], 'Redis::getOption' => ['int', 'name'=>'int'], 'Redis::getPersistentID' => ['string|false|null'], 'Redis::getPort' => ['int|false'], 'Redis::getRange' => ['int', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::getReadTimeout' => ['float|false'], 'Redis::getSet' => ['string', 'key'=>'string', 'string'=>'string'], 'Redis::getTimeout' => ['float|false'], 'Redis::hDel' => ['int|false', 'key'=>'string', 'hashKey1'=>'string', '...otherHashKeys='=>'string'], 'Redis::hExists' => ['bool', 'key'=>'string', 'hashKey'=>'string'], 'Redis::hGet' => ['string|false', 'key'=>'string', 'hashKey'=>'string'], 'Redis::hGetAll' => ['array', 'key'=>'string'], 'Redis::hIncrBy' => ['int', 'key'=>'string', 'hashKey'=>'string', 'value'=>'int'], 'Redis::hIncrByFloat' => ['float', 'key'=>'string', 'field'=>'string', 'increment'=>'float'], 'Redis::hKeys' => ['array', 'key'=>'string'], 'Redis::hLen' => ['int|false', 'key'=>'string'], 'Redis::hMGet' => ['array', 'key'=>'string', 'hashKeys'=>'array'], 'Redis::hMSet' => ['bool', 'key'=>'string', 'hashKeys'=>'array'], 'Redis::hScan' => ['array', 'key'=>'string', '&iterator'=>'int', 'pattern='=>'string', 'count='=>'int'], 'Redis::hSet' => ['int|false', 'key'=>'string', 'hashKey'=>'string', 'value'=>'string'], 'Redis::hSetNx' => ['bool', 'key'=>'string', 'hashKey'=>'string', 'value'=>'string'], 'Redis::hStrLen' => ['', 'key'=>'', 'member'=>''], 'Redis::hVals' => ['array', 'key'=>'string'], 'Redis::incr' => ['int', 'key'=>'string'], 'Redis::incrBy' => ['int', 'key'=>'string', 'value'=>'int'], 'Redis::incrByFloat' => ['float', 'key'=>'string', 'value'=>'float'], 'Redis::info' => ['array', 'option='=>'string'], 'Redis::isConnected' => ['bool'], 'Redis::keys' => ['array', 'pattern'=>'string'], 'Redis::lastSave' => ['int'], 'Redis::lGet' => ['string', 'key'=>'string', 'index'=>'int'], 'Redis::lGetRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::lIndex' => ['string|false', 'key'=>'string', 'index'=>'int'], 'Redis::lInsert' => ['int', 'key'=>'string', 'position'=>'int', 'pivot'=>'string', 'value'=>'string'], 'Redis::listTrim' => ['', 'key'=>'string', 'start'=>'int', 'stop'=>'int'], 'Redis::lLen' => ['int|false', 'key'=>'string'], 'Redis::lPop' => ['string|false', 'key'=>'string'], 'Redis::lPush' => ['int|false', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string'], 'Redis::lPushx' => ['int|false', 'key'=>'string', 'value'=>'string'], 'Redis::lRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::lRem' => ['int|false', 'key'=>'string', 'value'=>'string', 'count'=>'int'], 'Redis::lRemove' => ['int', 'key'=>'string', 'value'=>'string', 'count'=>'int'], 'Redis::lSet' => ['bool', 'key'=>'string', 'index'=>'int', 'value'=>'string'], 'Redis::lSize' => ['int', 'key'=>'string'], 'Redis::lTrim' => ['array|false', 'key'=>'string', 'start'=>'int', 'stop'=>'int'], 'Redis::mGet' => ['array', 'keys'=>'string[]'], 'Redis::migrate' => ['bool', 'host'=>'string', 'port'=>'int', 'key'=>'string|string[]', 'db'=>'int', 'timeout'=>'int', 'copy='=>'bool', 'replace='=>'bool'], 'Redis::move' => ['bool', 'key'=>'string', 'dbindex'=>'int'], 'Redis::mSet' => ['bool', 'pairs'=>'array'], 'Redis::mSetNx' => ['bool', 'pairs'=>'array'], 'Redis::multi' => ['Redis', 'mode='=>'int'], 'Redis::object' => ['string|long|false', 'info'=>'string', 'key'=>'string'], 'Redis::open' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'float', 'reserved='=>'null', 'retry_interval='=>'?int', 'read_timeout='=>'float'], 'Redis::pconnect' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'float', 'persistent_id='=>'string', 'retry_interval='=>'?int'], 'Redis::persist' => ['bool', 'key'=>'string'], 'Redis::pExpire' => ['bool', 'key'=>'string', 'ttl'=>'int'], 'Redis::pexpireAt' => ['bool', 'key'=>'string', 'expiry'=>'int'], 'Redis::pfAdd' => ['bool', 'key'=>'string', 'elements'=>'array'], 'Redis::pfCount' => ['int', 'key'=>'array|string'], 'Redis::pfMerge' => ['bool', 'destkey'=>'string', 'sourcekeys'=>'array'], 'Redis::ping' => ['string'], 'Redis::pipeline' => ['Redis'], 'Redis::popen' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'float', 'persistent_id='=>'string', 'retry_interval='=>'?int'], 'Redis::psetex' => ['bool', 'key'=>'string', 'ttl'=>'int', 'value'=>'string'], 'Redis::psubscribe' => ['', 'patterns'=>'array', 'callback'=>'array|string'], 'Redis::pttl' => ['int|false', 'key'=>'string'], 'Redis::publish' => ['int', 'channel'=>'string', 'message'=>'string'], 'Redis::pubsub' => ['array|int', 'keyword'=>'string', 'argument='=>'array|string'], 'Redis::punsubscribe' => ['', 'pattern'=>'string', '...other_patterns='=>'string'], 'Redis::randomKey' => ['string'], 'Redis::rawCommand' => ['mixed', 'command'=>'string', '...arguments='=>'mixed'], 'Redis::rename' => ['bool', 'srckey'=>'string', 'dstkey'=>'string'], 'Redis::renameKey' => ['bool', 'srckey'=>'string', 'dstkey'=>'string'], 'Redis::renameNx' => ['bool', 'srckey'=>'string', 'dstkey'=>'string'], 'Redis::resetStat' => ['bool'], 'Redis::restore' => ['bool', 'key'=>'string', 'ttl'=>'int', 'value'=>'string'], 'Redis::role' => ['array', 'nodeParams'=>'string|array{0:string,1:int}'], 'Redis::rPop' => ['string|false', 'key'=>'string'], 'Redis::rpoplpush' => ['string', 'srcKey'=>'string', 'dstKey'=>'string'], 'Redis::rPush' => ['int|false', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string'], 'Redis::rPushx' => ['int|false', 'key'=>'string', 'value'=>'string'], 'Redis::sAdd' => ['int|false', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string'], 'Redis::sAddArray' => ['bool', 'key'=>'string', 'values'=>'array'], 'Redis::save' => ['bool'], 'Redis::scan' => ['array|false', '&rw_iterator'=>'?int', 'pattern='=>'?string', 'count='=>'?int'], 'Redis::sCard' => ['int', 'key'=>'string'], 'Redis::sContains' => ['', 'key'=>'string', 'value'=>'string'], 'Redis::script' => ['mixed', 'command'=>'string', '...args='=>'mixed'], 'Redis::sDiff' => ['array', 'key1'=>'string', '...other_keys='=>'string'], 'Redis::sDiffStore' => ['int|false', 'dstKey'=>'string', 'key'=>'string', '...other_keys='=>'string'], 'Redis::select' => ['bool', 'dbindex'=>'int'], 'Redis::sendEcho' => ['string', 'msg'=>'string'], 'Redis::set' => ['bool', 'key'=>'string', 'value'=>'mixed', 'options='=>'array'], 'Redis::set\'1' => ['bool', 'key'=>'string', 'value'=>'mixed', 'timeout='=>'int'], 'Redis::setBit' => ['int', 'key'=>'string', 'offset'=>'int', 'value'=>'int'], 'Redis::setEx' => ['bool', 'key'=>'string', 'ttl'=>'int', 'value'=>'string'], 'Redis::setNx' => ['bool', 'key'=>'string', 'value'=>'string'], 'Redis::setOption' => ['bool', 'name'=>'int', 'value'=>'mixed'], 'Redis::setRange' => ['int', 'key'=>'string', 'offset'=>'int', 'end'=>'int'], 'Redis::setTimeout' => ['', 'key'=>'string', 'ttl'=>'int'], 'Redis::sGetMembers' => ['', 'key'=>'string'], 'Redis::sInter' => ['array|false', 'key'=>'string', '...other_keys='=>'string'], 'Redis::sInterStore' => ['int|false', 'dstKey'=>'string', 'key'=>'string', '...other_keys='=>'string'], 'Redis::sIsMember' => ['bool', 'key'=>'string', 'value'=>'string'], 'Redis::slave' => ['bool', 'host'=>'string', 'port'=>'int'], 'Redis::slave\'1' => ['bool', 'host'=>'string', 'port'=>'int'], 'Redis::slaveof' => ['bool', 'host='=>'string', 'port='=>'int'], 'Redis::slowLog' => ['mixed', 'operation'=>'string', 'length='=>'int'], 'Redis::sMembers' => ['array', 'key'=>'string'], 'Redis::sMove' => ['bool', 'srcKey'=>'string', 'dstKey'=>'string', 'member'=>'string'], 'Redis::sort' => ['array|int', 'key'=>'string', 'options='=>'array'], 'Redis::sortAsc' => ['array', 'key'=>'string', 'pattern='=>'string', 'get='=>'string', 'start='=>'int', 'end='=>'int', 'getList='=>'bool'], 'Redis::sortAscAlpha' => ['array', 'key'=>'string', 'pattern='=>'', 'get='=>'string', 'start='=>'int', 'end='=>'int', 'getList='=>'bool'], 'Redis::sortDesc' => ['array', 'key'=>'string', 'pattern='=>'', 'get='=>'string', 'start='=>'int', 'end='=>'int', 'getList='=>'bool'], 'Redis::sortDescAlpha' => ['array', 'key'=>'string', 'pattern='=>'', 'get='=>'string', 'start='=>'int', 'end='=>'int', 'getList='=>'bool'], 'Redis::sPop' => ['string|false', 'key'=>'string'], 'Redis::sRandMember' => ['array|string|false', 'key'=>'string', 'count='=>'int'], 'Redis::sRem' => ['int', 'key'=>'string', 'member1'=>'string', '...other_members='=>'string'], 'Redis::sRemove' => ['int', 'key'=>'string', 'member1'=>'string', '...other_members='=>'string'], 'Redis::sScan' => ['array|bool', 'key'=>'string', '&iterator'=>'int', 'pattern='=>'string', 'count='=>'int'], 'Redis::sSize' => ['int', 'key'=>'string'], 'Redis::strLen' => ['int', 'key'=>'string'], 'Redis::subscribe' => ['mixed|null', 'channels'=>'array', 'callback'=>'string|array'], 'Redis::substr' => ['', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::sUnion' => ['array', 'key'=>'string', '...other_keys='=>'string'], 'Redis::sUnionStore' => ['int', 'dstKey'=>'string', 'key'=>'string', '...other_keys='=>'string'], 'Redis::swapdb' => ['bool', 'srcdb'=>'int', 'dstdb'=>'int'], 'Redis::time' => ['array'], 'Redis::ttl' => ['int|false', 'key'=>'string'], 'Redis::type' => ['int', 'key'=>'string'], 'Redis::unlink' => ['int', 'key'=>'string', '...args'=>'string'], 'Redis::unlink\'1' => ['int', 'key'=>'string[]'], 'Redis::unsubscribe' => ['', 'channel'=>'string', '...other_channels='=>'string'], 'Redis::unwatch' => [''], 'Redis::wait' => ['int', 'numSlaves'=>'int', 'timeout'=>'int'], 'Redis::watch' => ['void', 'key'=>'string', '...other_keys='=>'string'], 'Redis::xack' => ['', 'str_key'=>'string', 'str_group'=>'string', 'arr_ids'=>'array'], 'Redis::xadd' => ['', 'str_key'=>'string', 'str_id'=>'string', 'arr_fields'=>'array', 'i_maxlen='=>'', 'boo_approximate='=>''], 'Redis::xclaim' => ['', 'str_key'=>'string', 'str_group'=>'string', 'str_consumer'=>'string', 'i_min_idle'=>'', 'arr_ids'=>'array', 'arr_opts='=>'array'], 'Redis::xdel' => ['', 'str_key'=>'string', 'arr_ids'=>'array'], 'Redis::xgroup' => ['', 'str_operation'=>'string', 'str_key='=>'string', 'str_arg1='=>'', 'str_arg2='=>'', 'str_arg3='=>''], 'Redis::xinfo' => ['', 'str_cmd'=>'string', 'str_key='=>'string', 'str_group='=>'string'], 'Redis::xlen' => ['', 'key'=>''], 'Redis::xpending' => ['', 'str_key'=>'string', 'str_group'=>'string', 'str_start='=>'', 'str_end='=>'', 'i_count='=>'', 'str_consumer='=>'string'], 'Redis::xrange' => ['', 'str_key'=>'string', 'str_start'=>'', 'str_end'=>'', 'i_count='=>''], 'Redis::xread' => ['', 'arr_streams'=>'array', 'i_count='=>'', 'i_block='=>''], 'Redis::xreadgroup' => ['', 'str_group'=>'string', 'str_consumer'=>'string', 'arr_streams'=>'array', 'i_count='=>'', 'i_block='=>''], 'Redis::xrevrange' => ['', 'str_key'=>'string', 'str_start'=>'', 'str_end'=>'', 'i_count='=>''], 'Redis::xtrim' => ['', 'str_key'=>'string', 'i_maxlen'=>'', 'boo_approximate='=>''], 'Redis::zAdd' => ['int', 'key'=>'string', 'score1'=>'float', 'value1'=>'string', 'score2='=>'float', 'value2='=>'string', 'scoreN='=>'float', 'valueN='=>'string'], 'Redis::zAdd\'1' => ['int', 'options'=>'array', 'key'=>'string', 'score1'=>'float', 'value1'=>'string', 'score2='=>'float', 'value2='=>'string', 'scoreN='=>'float', 'valueN='=>'string'], 'Redis::zCard' => ['int', 'key'=>'string'], 'Redis::zCount' => ['int', 'key'=>'string', 'start'=>'string', 'end'=>'string'], 'Redis::zDelete' => ['int', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::zDeleteRangeByRank' => ['', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::zDeleteRangeByScore' => ['', 'key'=>'string', 'start'=>'float', 'end'=>'float'], 'Redis::zIncrBy' => ['float', 'key'=>'string', 'value'=>'float', 'member'=>'string'], 'Redis::zInter' => ['int', 'Output'=>'string', 'ZSetKeys'=>'array', 'Weights='=>'?array', 'aggregateFunction='=>'string'], 'Redis::zInterStore' => ['int', 'Output'=>'string', 'ZSetKeys'=>'array', 'Weights='=>'?array', 'aggregateFunction='=>'string'], 'Redis::zLexCount' => ['int', 'key'=>'string', 'min'=>'string', 'max'=>'string'], 'Redis::zRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'withscores='=>'bool'], 'Redis::zRangeByLex' => ['array|false', 'key'=>'string', 'min'=>'int', 'max'=>'int', 'offset='=>'int', 'limit='=>'int'], 'Redis::zRangeByScore' => ['array', 'key'=>'string', 'start'=>'int|string', 'end'=>'int|string', 'options='=>'array'], 'Redis::zRank' => ['int', 'key'=>'string', 'member'=>'string'], 'Redis::zRem' => ['int', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::zRemove' => ['int', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::zRemoveRangeByRank' => ['int', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::zRemoveRangeByScore' => ['int', 'key'=>'string', 'start'=>'float|string', 'end'=>'float|string'], 'Redis::zRemRangeByLex' => ['int', 'key'=>'string', 'min'=>'string', 'max'=>'string'], 'Redis::zRemRangeByRank' => ['int', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::zRemRangeByScore' => ['int', 'key'=>'string', 'start'=>'float|string', 'end'=>'float|string'], 'Redis::zReverseRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'withscore='=>'bool'], 'Redis::zRevRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'withscore='=>'bool'], 'Redis::zRevRangeByLex' => ['array', 'key'=>'string', 'min'=>'string', 'max'=>'string', 'offset='=>'int', 'limit='=>'int'], 'Redis::zRevRangeByScore' => ['array', 'key'=>'string', 'start'=>'string', 'end'=>'string', 'options='=>'array'], 'Redis::zRevRank' => ['int', 'key'=>'string', 'member'=>'string'], 'Redis::zScan' => ['array|bool', 'key'=>'string', '&iterator'=>'int', 'pattern='=>'string', 'count='=>'int'], 'Redis::zScore' => ['float|false', 'key'=>'string', 'member'=>'string'], 'Redis::zSize' => ['', 'key'=>'string'], 'Redis::zUnion' => ['int', 'Output'=>'string', 'ZSetKeys'=>'array', 'Weights='=>'?array', 'aggregateFunction='=>'string'], 'Redis::zUnionStore' => ['int', 'Output'=>'string', 'ZSetKeys'=>'array', 'Weights='=>'?array', 'aggregateFunction='=>'string'], 'RedisArray::__call' => ['mixed', 'function_name'=>'string', 'arguments'=>'array'], 'RedisArray::__construct' => ['void', 'name='=>'string', 'hosts='=>'?array', 'opts='=>'?array'], 'RedisArray::_continuum' => [''], 'RedisArray::_distributor' => [''], 'RedisArray::_function' => ['string'], 'RedisArray::_hosts' => ['array'], 'RedisArray::_instance' => ['', 'host'=>''], 'RedisArray::_rehash' => ['', 'callable='=>'callable'], 'RedisArray::_target' => ['string', 'key'=>'string'], 'RedisArray::bgsave' => [''], 'RedisArray::del' => ['bool', 'key'=>'string', '...args'=>'string'], 'RedisArray::delete' => ['bool', 'key'=>'string', '...args'=>'string'], 'RedisArray::delete\'1' => ['bool', 'key'=>'string[]'], 'RedisArray::discard' => [''], 'RedisArray::exec' => ['array'], 'RedisArray::flushAll' => ['bool', 'async='=>'bool'], 'RedisArray::flushDb' => ['bool', 'async='=>'bool'], 'RedisArray::getMultiple' => ['', 'keys'=>''], 'RedisArray::getOption' => ['', 'opt'=>''], 'RedisArray::info' => ['array'], 'RedisArray::keys' => ['array', 'pattern'=>''], 'RedisArray::mGet' => ['array', 'keys'=>'string[]'], 'RedisArray::mSet' => ['bool', 'pairs'=>'array'], 'RedisArray::multi' => ['RedisArray', 'host'=>'string', 'mode='=>'int'], 'RedisArray::ping' => ['string'], 'RedisArray::save' => ['bool'], 'RedisArray::select' => ['', 'index'=>''], 'RedisArray::setOption' => ['', 'opt'=>'', 'value'=>''], 'RedisArray::unlink' => ['int', 'key'=>'string', '...other_keys='=>'string'], 'RedisArray::unlink\'1' => ['int', 'key'=>'string[]'], 'RedisArray::unwatch' => [''], 'RedisCluster::__construct' => ['void', 'name'=>'?string', 'seeds='=>'string[]', 'timeout='=>'float', 'readTimeout='=>'float', 'persistent='=>'bool', 'auth='=>'?string'], 'RedisCluster::_masters' => ['array'], 'RedisCluster::_prefix' => ['string', 'value'=>'mixed'], 'RedisCluster::_redir' => [''], 'RedisCluster::_serialize' => ['mixed', 'value'=>'mixed'], 'RedisCluster::_unserialize' => ['mixed', 'value'=>'string'], 'RedisCluster::append' => ['int', 'key'=>'string', 'value'=>'string'], 'RedisCluster::bgrewriteaof' => ['bool', 'nodeParams'=>'string|array{0:string,1:int}'], 'RedisCluster::bgsave' => ['bool', 'nodeParams'=>'string|array{0:string,1:int}'], 'RedisCluster::bitCount' => ['int', 'key'=>'string'], 'RedisCluster::bitOp' => ['int', 'operation'=>'string', 'retKey'=>'string', 'key1'=>'string', '...other_keys='=>'string'], 'RedisCluster::bitpos' => ['int', 'key'=>'string', 'bit'=>'int', 'start='=>'int', 'end='=>'int'], 'RedisCluster::blPop' => ['array', 'keys'=>'array', 'timeout'=>'int'], 'RedisCluster::brPop' => ['array', 'keys'=>'array', 'timeout'=>'int'], 'RedisCluster::brpoplpush' => ['string|false', 'srcKey'=>'string', 'dstKey'=>'string', 'timeout'=>'int'], 'RedisCluster::clearLastError' => ['bool'], 'RedisCluster::client' => ['', 'nodeParams'=>'string|array{0:string,1:int}', 'subCmd='=>'string', '...args='=>''], 'RedisCluster::close' => [''], 'RedisCluster::cluster' => ['mixed', 'nodeParams'=>'string|array{0:string,1:int}', 'command'=>'string', 'arguments='=>'mixed'], 'RedisCluster::command' => ['array|bool'], 'RedisCluster::config' => ['array|bool', 'nodeParams'=>'string|array{0:string,1:int}', 'operation'=>'string', 'key'=>'string', 'value='=>'string'], 'RedisCluster::dbSize' => ['int', 'nodeParams'=>'string|array{0:string,1:int}'], 'RedisCluster::decr' => ['int', 'key'=>'string'], 'RedisCluster::decrBy' => ['int', 'key'=>'string', 'value'=>'int'], 'RedisCluster::del' => ['int', 'key'=>'string', '...other_keys='=>'string'], 'RedisCluster::del\'1' => ['int', 'key'=>'string[]'], 'RedisCluster::discard' => [''], 'RedisCluster::dump' => ['string|false', 'key'=>'string'], 'RedisCluster::echo' => ['string', 'nodeParams'=>'string|array{0:string,1:int}', 'msg'=>'string'], 'RedisCluster::eval' => ['mixed', 'script'=>'', 'args='=>'', 'numKeys='=>''], 'RedisCluster::evalSha' => ['mixed', 'scriptSha'=>'string', 'args='=>'array', 'numKeys='=>'int'], 'RedisCluster::exec' => ['array|void'], 'RedisCluster::exists' => ['bool', 'key'=>'string'], 'RedisCluster::expire' => ['bool', 'key'=>'string', 'ttl'=>'int'], 'RedisCluster::expireAt' => ['bool', 'key'=>'string', 'timestamp'=>'int'], 'RedisCluster::flushAll' => ['bool', 'nodeParams'=>'string|array{0:string,1:int}', 'async='=>'bool'], 'RedisCluster::flushDB' => ['bool', 'nodeParams'=>'string|array{0:string,1:int}', 'async='=>'bool'], 'RedisCluster::geoAdd' => ['int', 'key'=>'string', 'longitude'=>'float', 'latitude'=>'float', 'member'=>'string', '...other_members='=>'float|string'], 'RedisCluster::geoDist' => ['', 'key'=>'string', 'member1'=>'string', 'member2'=>'string', 'unit='=>'string'], 'RedisCluster::geohash' => ['array', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'RedisCluster::geopos' => ['array', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'RedisCluster::geoRadius' => ['', 'key'=>'string', 'longitude'=>'float', 'latitude'=>'float', 'radius'=>'float', 'radiusUnit'=>'string', 'options='=>'array'], 'RedisCluster::geoRadiusByMember' => ['string[]', 'key'=>'string', 'member'=>'string', 'radius'=>'float', 'radiusUnit'=>'string', 'options='=>'array'], 'RedisCluster::get' => ['string|false', 'key'=>'string'], 'RedisCluster::getBit' => ['int', 'key'=>'string', 'offset'=>'int'], 'RedisCluster::getLastError' => ['?string'], 'RedisCluster::getMode' => ['int'], 'RedisCluster::getOption' => ['int', 'name'=>'string'], 'RedisCluster::getRange' => ['string', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'RedisCluster::getSet' => ['string', 'key'=>'string', 'value'=>'string'], 'RedisCluster::hDel' => ['int|false', 'key'=>'string', 'hashKey'=>'string', '...other_hashKeys='=>'string[]'], 'RedisCluster::hExists' => ['bool', 'key'=>'string', 'hashKey'=>'string'], 'RedisCluster::hGet' => ['string|false', 'key'=>'string', 'hashKey'=>'string'], 'RedisCluster::hGetAll' => ['array', 'key'=>'string'], 'RedisCluster::hIncrBy' => ['int', 'key'=>'string', 'hashKey'=>'string', 'value'=>'int'], 'RedisCluster::hIncrByFloat' => ['float', 'key'=>'string', 'field'=>'string', 'increment'=>'float'], 'RedisCluster::hKeys' => ['array', 'key'=>'string'], 'RedisCluster::hLen' => ['int|false', 'key'=>'string'], 'RedisCluster::hMGet' => ['array', 'key'=>'string', 'hashKeys'=>'array'], 'RedisCluster::hMSet' => ['bool', 'key'=>'string', 'hashKeys'=>'array'], 'RedisCluster::hScan' => ['array', 'key'=>'string', '&iterator'=>'int', 'pattern='=>'string', 'count='=>'int'], 'RedisCluster::hSet' => ['int', 'key'=>'string', 'hashKey'=>'string', 'value'=>'string'], 'RedisCluster::hSetNx' => ['bool', 'key'=>'string', 'hashKey'=>'string', 'value'=>'string'], 'RedisCluster::hStrlen' => ['int', 'key'=>'string', 'member'=>'string'], 'RedisCluster::hVals' => ['array', 'key'=>'string'], 'RedisCluster::incr' => ['int', 'key'=>'string'], 'RedisCluster::incrBy' => ['int', 'key'=>'string', 'value'=>'int'], 'RedisCluster::incrByFloat' => ['float', 'key'=>'string', 'increment'=>'float'], 'RedisCluster::info' => ['array', 'nodeParams'=>'string|array{0:string,1:int}', 'option='=>'string'], 'RedisCluster::keys' => ['array', 'pattern'=>'string'], 'RedisCluster::lastSave' => ['int', 'nodeParams'=>'string|array{0:string,1:int}'], 'RedisCluster::lGet' => ['', 'key'=>'string', 'index'=>'int'], 'RedisCluster::lIndex' => ['string|false', 'key'=>'string', 'index'=>'int'], 'RedisCluster::lInsert' => ['int', 'key'=>'string', 'position'=>'int', 'pivot'=>'string', 'value'=>'string'], 'RedisCluster::lLen' => ['int', 'key'=>'string'], 'RedisCluster::lPop' => ['string|false', 'key'=>'string'], 'RedisCluster::lPush' => ['int|false', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string'], 'RedisCluster::lPushx' => ['int|false', 'key'=>'string', 'value'=>'string'], 'RedisCluster::lRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'RedisCluster::lRem' => ['int|false', 'key'=>'string', 'value'=>'string', 'count'=>'int'], 'RedisCluster::lSet' => ['bool', 'key'=>'string', 'index'=>'int', 'value'=>'string'], 'RedisCluster::lTrim' => ['array|false', 'key'=>'string', 'start'=>'int', 'stop'=>'int'], 'RedisCluster::mget' => ['array', 'array'=>'array'], 'RedisCluster::mset' => ['bool', 'array'=>'array'], 'RedisCluster::msetnx' => ['int', 'array'=>'array'], 'RedisCluster::multi' => ['Redis', 'mode='=>'int'], 'RedisCluster::object' => ['string|int|false', 'string'=>'string', 'key'=>'string'], 'RedisCluster::persist' => ['bool', 'key'=>'string'], 'RedisCluster::pExpire' => ['bool', 'key'=>'string', 'ttl'=>'int'], 'RedisCluster::pExpireAt' => ['bool', 'key'=>'string', 'timestamp'=>'int'], 'RedisCluster::pfAdd' => ['bool', 'key'=>'string', 'elements'=>'array'], 'RedisCluster::pfCount' => ['int', 'key'=>'string'], 'RedisCluster::pfMerge' => ['bool', 'destKey'=>'string', 'sourceKeys'=>'array'], 'RedisCluster::ping' => ['string', 'nodeParams'=>'string|array{0:string,1:int}'], 'RedisCluster::psetex' => ['bool', 'key'=>'string', 'ttl'=>'int', 'value'=>'string'], 'RedisCluster::psubscribe' => ['mixed', 'patterns'=>'array', 'callback'=>'string'], 'RedisCluster::pttl' => ['int', 'key'=>'string'], 'RedisCluster::publish' => ['int', 'channel'=>'string', 'message'=>'string'], 'RedisCluster::pubsub' => ['array', 'nodeParams'=>'string', 'keyword'=>'string', '...argument='=>'string'], 'RedisCluster::punSubscribe' => ['', 'channels'=>'', 'callback'=>''], 'RedisCluster::randomKey' => ['string', 'nodeParams'=>'string|array{0:string,1:int}'], 'RedisCluster::rawCommand' => ['mixed', 'nodeParams'=>'string|array{0:string,1:int}', 'command'=>'string', 'arguments='=>'mixed'], 'RedisCluster::rename' => ['bool', 'srcKey'=>'string', 'dstKey'=>'string'], 'RedisCluster::renameNx' => ['bool', 'srcKey'=>'string', 'dstKey'=>'string'], 'RedisCluster::restore' => ['bool', 'key'=>'string', 'ttl'=>'int', 'value'=>'string'], 'RedisCluster::role' => ['array'], 'RedisCluster::rPop' => ['string|false', 'key'=>'string'], 'RedisCluster::rpoplpush' => ['string|false', 'srcKey'=>'string', 'dstKey'=>'string'], 'RedisCluster::rPush' => ['int|false', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string'], 'RedisCluster::rPushx' => ['int|false', 'key'=>'string', 'value'=>'string'], 'RedisCluster::sAdd' => ['int|false', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string'], 'RedisCluster::sAddArray' => ['int|false', 'key'=>'string', 'valueArray'=>'array'], 'RedisCluster::save' => ['bool', 'nodeParams'=>'string|array{0:string,1:int}'], 'RedisCluster::scan' => ['array|false', '&iterator'=>'int', 'nodeParams'=>'string|array{0:string,1:int}', 'pattern='=>'string', 'count='=>'int'], 'RedisCluster::sCard' => ['int', 'key'=>'string'], 'RedisCluster::script' => ['string|bool|array', 'nodeParams'=>'string|array{0:string,1:int}', 'command'=>'string', 'script='=>'string', '...other_scripts='=>'string[]'], 'RedisCluster::sDiff' => ['list', 'key1'=>'string', 'key2'=>'string', '...other_keys='=>'string'], 'RedisCluster::sDiffStore' => ['int', 'dstKey'=>'string', 'key1'=>'string', '...other_keys='=>'string'], 'RedisCluster::set' => ['bool', 'key'=>'string', 'value'=>'string', 'timeout='=>'array|int'], 'RedisCluster::setBit' => ['int', 'key'=>'string', 'offset'=>'int', 'value'=>'bool|int'], 'RedisCluster::setex' => ['bool', 'key'=>'string', 'ttl'=>'int', 'value'=>'string'], 'RedisCluster::setnx' => ['bool', 'key'=>'string', 'value'=>'string'], 'RedisCluster::setOption' => ['bool', 'name'=>'string', 'value'=>'string'], 'RedisCluster::setRange' => ['string', 'key'=>'string', 'offset'=>'int', 'value'=>'string'], 'RedisCluster::sInter' => ['list', 'key'=>'string', '...other_keys='=>'string'], 'RedisCluster::sInterStore' => ['int', 'dstKey'=>'string', 'key'=>'string', '...other_keys='=>'string'], 'RedisCluster::sIsMember' => ['bool', 'key'=>'string', 'value'=>'string'], 'RedisCluster::slowLog' => ['array|int|bool', 'nodeParams'=>'string|array{0:string,1:int}', 'command'=>'string', 'length='=>'int'], 'RedisCluster::sMembers' => ['list', 'key'=>'string'], 'RedisCluster::sMove' => ['bool', 'srcKey'=>'string', 'dstKey'=>'string', 'member'=>'string'], 'RedisCluster::sort' => ['array', 'key'=>'string', 'option='=>'array'], 'RedisCluster::sPop' => ['string', 'key'=>'string'], 'RedisCluster::sRandMember' => ['array|string', 'key'=>'string', 'count='=>'int'], 'RedisCluster::sRem' => ['int', 'key'=>'string', 'member1'=>'string', '...other_members='=>'string'], 'RedisCluster::sScan' => ['array|false', 'key'=>'string', '&iterator'=>'int', 'pattern='=>'null', 'count='=>'int'], 'RedisCluster::strlen' => ['int', 'key'=>'string'], 'RedisCluster::subscribe' => ['mixed', 'channels'=>'array', 'callback'=>'string'], 'RedisCluster::sUnion' => ['list', 'key1'=>'string', '...other_keys='=>'string'], 'RedisCluster::sUnion\'1' => ['list', 'keys'=>'string[]'], 'RedisCluster::sUnionStore' => ['int', 'dstKey'=>'string', 'key1'=>'string', '...other_keys='=>'string'], 'RedisCluster::time' => ['array'], 'RedisCluster::ttl' => ['int', 'key'=>'string'], 'RedisCluster::type' => ['int', 'key'=>'string'], 'RedisCluster::unlink' => ['int', 'key'=>'string', '...other_keys='=>'string'], 'RedisCluster::unSubscribe' => ['', 'channels'=>'', '...other_channels='=>''], 'RedisCluster::unwatch' => [''], 'RedisCluster::watch' => ['void', 'key'=>'string', '...other_keys='=>'string'], 'RedisCluster::xack' => ['', 'str_key'=>'string', 'str_group'=>'string', 'arr_ids'=>'array'], 'RedisCluster::xadd' => ['', 'str_key'=>'string', 'str_id'=>'string', 'arr_fields'=>'array', 'i_maxlen='=>'', 'boo_approximate='=>''], 'RedisCluster::xclaim' => ['', 'str_key'=>'string', 'str_group'=>'string', 'str_consumer'=>'string', 'i_min_idle'=>'', 'arr_ids'=>'array', 'arr_opts='=>'array'], 'RedisCluster::xdel' => ['', 'str_key'=>'string', 'arr_ids'=>'array'], 'RedisCluster::xgroup' => ['', 'str_operation'=>'string', 'str_key='=>'string', 'str_arg1='=>'', 'str_arg2='=>'', 'str_arg3='=>''], 'RedisCluster::xinfo' => ['', 'str_cmd'=>'string', 'str_key='=>'string', 'str_group='=>'string'], 'RedisCluster::xlen' => ['', 'key'=>''], 'RedisCluster::xpending' => ['', 'str_key'=>'string', 'str_group'=>'string', 'str_start='=>'', 'str_end='=>'', 'i_count='=>'', 'str_consumer='=>'string'], 'RedisCluster::xrange' => ['', 'str_key'=>'string', 'str_start'=>'', 'str_end'=>'', 'i_count='=>''], 'RedisCluster::xread' => ['', 'arr_streams'=>'array', 'i_count='=>'', 'i_block='=>''], 'RedisCluster::xreadgroup' => ['', 'str_group'=>'string', 'str_consumer'=>'string', 'arr_streams'=>'array', 'i_count='=>'', 'i_block='=>''], 'RedisCluster::xrevrange' => ['', 'str_key'=>'string', 'str_start'=>'', 'str_end'=>'', 'i_count='=>''], 'RedisCluster::xtrim' => ['', 'str_key'=>'string', 'i_maxlen'=>'', 'boo_approximate='=>''], 'RedisCluster::zAdd' => ['int', 'key'=>'string', 'score1'=>'float', 'value1'=>'string', 'score2='=>'float', 'value2='=>'string', 'scoreN='=>'float', 'valueN='=>'string'], 'RedisCluster::zCard' => ['int', 'key'=>'string'], 'RedisCluster::zCount' => ['int', 'key'=>'string', 'start'=>'string', 'end'=>'string'], 'RedisCluster::zIncrBy' => ['float', 'key'=>'string', 'value'=>'float', 'member'=>'string'], 'RedisCluster::zInterStore' => ['int', 'Output'=>'string', 'ZSetKeys'=>'array', 'Weights='=>'?array', 'aggregateFunction='=>'string'], 'RedisCluster::zLexCount' => ['int', 'key'=>'string', 'min'=>'int', 'max'=>'int'], 'RedisCluster::zRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'withscores='=>'bool'], 'RedisCluster::zRangeByLex' => ['array', 'key'=>'string', 'min'=>'int', 'max'=>'int', 'offset='=>'int', 'limit='=>'int'], 'RedisCluster::zRangeByScore' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'options='=>'array'], 'RedisCluster::zRank' => ['int', 'key'=>'string', 'member'=>'string'], 'RedisCluster::zRem' => ['int', 'key'=>'string', 'member1'=>'string', '...other_members='=>'string'], 'RedisCluster::zRemRangeByLex' => ['array', 'key'=>'string', 'min'=>'int', 'max'=>'int'], 'RedisCluster::zRemRangeByRank' => ['int', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'RedisCluster::zRemRangeByScore' => ['int', 'key'=>'string', 'start'=>'float|string', 'end'=>'float|string'], 'RedisCluster::zRevRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'withscore='=>'bool'], 'RedisCluster::zRevRangeByLex' => ['array', 'key'=>'string', 'min'=>'int', 'max'=>'int', 'offset='=>'int', 'limit='=>'int'], 'RedisCluster::zRevRangeByScore' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'options='=>'array'], 'RedisCluster::zRevRank' => ['int', 'key'=>'string', 'member'=>'string'], 'RedisCluster::zScan' => ['array|false', 'key'=>'string', '&iterator'=>'int', 'pattern='=>'string', 'count='=>'int'], 'RedisCluster::zScore' => ['float', 'key'=>'string', 'member'=>'string'], 'RedisCluster::zUnionStore' => ['int', 'Output'=>'string', 'ZSetKeys'=>'array', 'Weights='=>'?array', 'aggregateFunction='=>'string'], 'Reflection::export' => ['?string', 'r'=>'reflector', 'return='=>'bool'], 'Reflection::getModifierNames' => ['array', 'modifiers'=>'int'], 'ReflectionClass::__clone' => ['void'], 'ReflectionClass::__construct' => ['void', 'argument'=>'object|class-string'], 'ReflectionClass::__toString' => ['string'], 'ReflectionClass::export' => ['?string', 'argument'=>'string|object', 'return='=>'bool'], 'ReflectionClass::getConstant' => ['mixed', 'name'=>'string'], 'ReflectionClass::getConstants' => ['array'], 'ReflectionClass::getConstructor' => ['?ReflectionMethod'], 'ReflectionClass::getDefaultProperties' => ['array'], 'ReflectionClass::getDocComment' => ['string|false'], 'ReflectionClass::getEndLine' => ['int|false'], 'ReflectionClass::getExtension' => ['?ReflectionExtension'], 'ReflectionClass::getExtensionName' => ['string|false'], 'ReflectionClass::getFileName' => ['string|false'], 'ReflectionClass::getInterfaceNames' => ['list'], 'ReflectionClass::getInterfaces' => ['array'], 'ReflectionClass::getMethod' => ['ReflectionMethod', 'name'=>'string'], 'ReflectionClass::getMethods' => ['list', 'filter='=>'int'], 'ReflectionClass::getModifiers' => ['int'], 'ReflectionClass::getName' => ['class-string'], 'ReflectionClass::getNamespaceName' => ['string'], 'ReflectionClass::getParentClass' => ['ReflectionClass|false'], 'ReflectionClass::getProperties' => ['list', 'filter='=>'int'], 'ReflectionClass::getProperty' => ['ReflectionProperty', 'name'=>'string'], 'ReflectionClass::getReflectionConstant' => ['ReflectionClassConstant|false', 'name'=>'string'], 'ReflectionClass::getReflectionConstants' => ['list'], 'ReflectionClass::getShortName' => ['string'], 'ReflectionClass::getStartLine' => ['int|false'], 'ReflectionClass::getStaticProperties' => ['array'], 'ReflectionClass::getStaticPropertyValue' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'ReflectionClass::getTraitAliases' => ['array|null'], 'ReflectionClass::getTraitNames' => ['list|null'], 'ReflectionClass::getTraits' => ['array'], 'ReflectionClass::hasConstant' => ['bool', 'name'=>'string'], 'ReflectionClass::hasMethod' => ['bool', 'name'=>'string'], 'ReflectionClass::hasProperty' => ['bool', 'name'=>'string'], 'ReflectionClass::implementsInterface' => ['bool', 'interface_name'=>'class-string|ReflectionClass'], 'ReflectionClass::inNamespace' => ['bool'], 'ReflectionClass::isAbstract' => ['bool'], 'ReflectionClass::isAnonymous' => ['bool'], 'ReflectionClass::isCloneable' => ['bool'], 'ReflectionClass::isFinal' => ['bool'], 'ReflectionClass::isInstance' => ['bool', 'object'=>'object'], 'ReflectionClass::isInstantiable' => ['bool'], 'ReflectionClass::isInterface' => ['bool'], 'ReflectionClass::isInternal' => ['bool'], 'ReflectionClass::isIterable' => ['bool'], 'ReflectionClass::isIterateable' => ['bool'], 'ReflectionClass::isSubclassOf' => ['bool', 'class'=>'class-string|ReflectionClass'], 'ReflectionClass::isTrait' => ['bool'], 'ReflectionClass::isUserDefined' => ['bool'], 'ReflectionClass::newInstance' => ['object', '...args='=>'mixed'], 'ReflectionClass::newInstanceArgs' => ['object', 'args='=>'list'], 'ReflectionClass::newInstanceWithoutConstructor' => ['object'], 'ReflectionClass::setStaticPropertyValue' => ['void', 'name'=>'string', 'value'=>'mixed'], 'ReflectionClassConstant::__construct' => ['void', 'class'=>'mixed', 'name'=>'string'], 'ReflectionClassConstant::__toString' => ['string'], 'ReflectionClassConstant::export' => ['string', 'class'=>'mixed', 'name'=>'string', 'return='=>'bool'], 'ReflectionClassConstant::getDeclaringClass' => ['ReflectionClass'], 'ReflectionClassConstant::getDocComment' => ['string|false'], 'ReflectionClassConstant::getModifiers' => ['int'], 'ReflectionClassConstant::getName' => ['string'], 'ReflectionClassConstant::getValue' => ['scalar|array|null'], 'ReflectionClassConstant::isPrivate' => ['bool'], 'ReflectionClassConstant::isProtected' => ['bool'], 'ReflectionClassConstant::isPublic' => ['bool'], 'ReflectionExtension::__clone' => ['void'], 'ReflectionExtension::__construct' => ['void', 'name'=>'string'], 'ReflectionExtension::__toString' => ['string'], 'ReflectionExtension::export' => ['?string', 'name'=>'string', 'return='=>'bool'], 'ReflectionExtension::getClasses' => ['array'], 'ReflectionExtension::getClassNames' => ['list'], 'ReflectionExtension::getConstants' => ['array'], 'ReflectionExtension::getDependencies' => ['array'], 'ReflectionExtension::getFunctions' => ['array'], 'ReflectionExtension::getINIEntries' => ['array'], 'ReflectionExtension::getName' => ['string'], 'ReflectionExtension::getVersion' => ['string'], 'ReflectionExtension::info' => ['void'], 'ReflectionExtension::isPersistent' => ['bool'], 'ReflectionExtension::isTemporary' => ['bool'], 'ReflectionFunction::__construct' => ['void', 'name'=>'callable-string|Closure'], 'ReflectionFunction::__toString' => ['string'], 'ReflectionFunction::export' => ['?string', 'name'=>'string', 'return='=>'bool'], 'ReflectionFunction::getClosure' => ['?Closure'], 'ReflectionFunction::getClosureScopeClass' => ['ReflectionClass'], 'ReflectionFunction::getClosureThis' => ['bool'], 'ReflectionFunction::getDocComment' => ['string|false'], 'ReflectionFunction::getEndLine' => ['int|false'], 'ReflectionFunction::getExtension' => ['?ReflectionExtension'], 'ReflectionFunction::getExtensionName' => ['string|false'], 'ReflectionFunction::getFileName' => ['string|false'], 'ReflectionFunction::getName' => ['callable-string'], 'ReflectionFunction::getNamespaceName' => ['string'], 'ReflectionFunction::getNumberOfParameters' => ['int'], 'ReflectionFunction::getNumberOfRequiredParameters' => ['int'], 'ReflectionFunction::getParameters' => ['list'], 'ReflectionFunction::getReturnType' => ['?ReflectionType'], 'ReflectionFunction::getShortName' => ['string'], 'ReflectionFunction::getStartLine' => ['int|false'], 'ReflectionFunction::getStaticVariables' => ['array'], 'ReflectionFunction::hasReturnType' => ['bool'], 'ReflectionFunction::inNamespace' => ['bool'], 'ReflectionFunction::invoke' => ['mixed', '...args='=>'mixed'], 'ReflectionFunction::invokeArgs' => ['mixed', 'args'=>'array'], 'ReflectionFunction::isClosure' => ['bool'], 'ReflectionFunction::isDeprecated' => ['bool'], 'ReflectionFunction::isDisabled' => ['bool'], 'ReflectionFunction::isGenerator' => ['bool'], 'ReflectionFunction::isInternal' => ['bool'], 'ReflectionFunction::isUserDefined' => ['bool'], 'ReflectionFunction::isVariadic' => ['bool'], 'ReflectionFunction::returnsReference' => ['bool'], 'ReflectionFunctionAbstract::__clone' => ['void'], 'ReflectionFunctionAbstract::__toString' => ['string'], 'ReflectionFunctionAbstract::export' => ['?string'], 'ReflectionFunctionAbstract::getClosureScopeClass' => ['ReflectionClass|null'], 'ReflectionFunctionAbstract::getClosureThis' => ['object|null'], 'ReflectionFunctionAbstract::getDocComment' => ['string|false'], 'ReflectionFunctionAbstract::getEndLine' => ['int|false'], 'ReflectionFunctionAbstract::getExtension' => ['ReflectionExtension'], 'ReflectionFunctionAbstract::getExtensionName' => ['string'], 'ReflectionFunctionAbstract::getFileName' => ['string|false'], 'ReflectionFunctionAbstract::getName' => ['string'], 'ReflectionFunctionAbstract::getNamespaceName' => ['string'], 'ReflectionFunctionAbstract::getNumberOfParameters' => ['int'], 'ReflectionFunctionAbstract::getNumberOfRequiredParameters' => ['int'], 'ReflectionFunctionAbstract::getParameters' => ['list'], 'ReflectionFunctionAbstract::getReturnType' => ['?ReflectionType'], 'ReflectionFunctionAbstract::getShortName' => ['string'], 'ReflectionFunctionAbstract::getStartLine' => ['int|false'], 'ReflectionFunctionAbstract::getStaticVariables' => ['array'], 'ReflectionFunctionAbstract::hasReturnType' => ['bool'], 'ReflectionFunctionAbstract::inNamespace' => ['bool'], 'ReflectionFunctionAbstract::isClosure' => ['bool'], 'ReflectionFunctionAbstract::isDeprecated' => ['bool'], 'ReflectionFunctionAbstract::isGenerator' => ['bool'], 'ReflectionFunctionAbstract::isInternal' => ['bool'], 'ReflectionFunctionAbstract::isUserDefined' => ['bool'], 'ReflectionFunctionAbstract::isVariadic' => ['bool'], 'ReflectionFunctionAbstract::returnsReference' => ['bool'], 'ReflectionGenerator::__construct' => ['void', 'generator'=>'object'], 'ReflectionGenerator::getExecutingFile' => ['string'], 'ReflectionGenerator::getExecutingGenerator' => ['Generator'], 'ReflectionGenerator::getExecutingLine' => ['int'], 'ReflectionGenerator::getFunction' => ['ReflectionFunctionAbstract'], 'ReflectionGenerator::getThis' => ['?object'], 'ReflectionGenerator::getTrace' => ['array', 'options='=>'int'], 'ReflectionMethod::__construct' => ['void', 'class'=>'class-string|object', 'name'=>'string'], 'ReflectionMethod::__construct\'1' => ['void', 'class_method'=>'string'], 'ReflectionMethod::__toString' => ['string'], 'ReflectionMethod::export' => ['?string', 'class'=>'string', 'name'=>'string', 'return='=>'bool'], 'ReflectionMethod::getClosure' => ['?Closure', 'object='=>'object'], 'ReflectionMethod::getClosureScopeClass' => ['ReflectionClass'], 'ReflectionMethod::getClosureThis' => ['object'], 'ReflectionMethod::getDeclaringClass' => ['ReflectionClass'], 'ReflectionMethod::getDocComment' => ['false|string'], 'ReflectionMethod::getEndLine' => ['false|int'], 'ReflectionMethod::getExtension' => ['ReflectionExtension'], 'ReflectionMethod::getExtensionName' => ['string'], 'ReflectionMethod::getFileName' => ['false|string'], 'ReflectionMethod::getModifiers' => ['int'], 'ReflectionMethod::getName' => ['string'], 'ReflectionMethod::getNamespaceName' => ['string'], 'ReflectionMethod::getNumberOfParameters' => ['int'], 'ReflectionMethod::getNumberOfRequiredParameters' => ['int'], 'ReflectionMethod::getParameters' => ['list<\ReflectionParameter>'], 'ReflectionMethod::getPrototype' => ['ReflectionMethod'], 'ReflectionMethod::getReturnType' => ['?ReflectionType'], 'ReflectionMethod::getShortName' => ['string'], 'ReflectionMethod::getStartLine' => ['false|int'], 'ReflectionMethod::getStaticVariables' => ['array'], 'ReflectionMethod::hasReturnType' => ['bool'], 'ReflectionMethod::inNamespace' => ['bool'], 'ReflectionMethod::invoke' => ['mixed', 'object'=>'?object', '...args='=>'mixed'], 'ReflectionMethod::invokeArgs' => ['mixed', 'object'=>'?object', 'args'=>'array'], 'ReflectionMethod::isAbstract' => ['bool'], 'ReflectionMethod::isClosure' => ['bool'], 'ReflectionMethod::isConstructor' => ['bool'], 'ReflectionMethod::isDeprecated' => ['bool'], 'ReflectionMethod::isDestructor' => ['bool'], 'ReflectionMethod::isFinal' => ['bool'], 'ReflectionMethod::isGenerator' => ['bool'], 'ReflectionMethod::isInternal' => ['bool'], 'ReflectionMethod::isPrivate' => ['bool'], 'ReflectionMethod::isProtected' => ['bool'], 'ReflectionMethod::isPublic' => ['bool'], 'ReflectionMethod::isStatic' => ['bool'], 'ReflectionMethod::isUserDefined' => ['bool'], 'ReflectionMethod::isVariadic' => ['bool'], 'ReflectionMethod::returnsReference' => ['bool'], 'ReflectionMethod::setAccessible' => ['void', 'visible'=>'bool'], 'ReflectionNamedType::__clone' => ['void'], 'ReflectionNamedType::__toString' => ['string'], 'ReflectionNamedType::allowsNull' => [''], 'ReflectionNamedType::getName' => ['string'], 'ReflectionNamedType::isBuiltin' => [''], 'ReflectionObject::__clone' => ['void'], 'ReflectionObject::__construct' => ['void', 'argument'=>'object'], 'ReflectionObject::__toString' => ['string'], 'ReflectionObject::export' => ['?string', 'argument'=>'object', 'return='=>'bool'], 'ReflectionObject::getConstant' => ['mixed', 'name'=>'string'], 'ReflectionObject::getConstants' => ['array'], 'ReflectionObject::getConstructor' => ['?ReflectionMethod'], 'ReflectionObject::getDefaultProperties' => ['array'], 'ReflectionObject::getDocComment' => ['false|string'], 'ReflectionObject::getEndLine' => ['false|int'], 'ReflectionObject::getExtension' => ['?ReflectionExtension'], 'ReflectionObject::getExtensionName' => ['false|string'], 'ReflectionObject::getFileName' => ['false|string'], 'ReflectionObject::getInterfaceNames' => ['class-string[]'], 'ReflectionObject::getInterfaces' => ['array'], 'ReflectionObject::getMethod' => ['ReflectionMethod', 'name'=>'string'], 'ReflectionObject::getMethods' => ['ReflectionMethod[]', 'filter='=>'int'], 'ReflectionObject::getModifiers' => ['int'], 'ReflectionObject::getName' => ['string'], 'ReflectionObject::getNamespaceName' => ['string'], 'ReflectionObject::getParentClass' => ['ReflectionClass|false'], 'ReflectionObject::getProperties' => ['ReflectionProperty[]', 'filter='=>'int'], 'ReflectionObject::getProperty' => ['ReflectionProperty', 'name'=>'string'], 'ReflectionObject::getReflectionConstant' => ['ReflectionClassConstant', 'name'=>'string'], 'ReflectionObject::getReflectionConstants' => ['list<\ReflectionClassConstant>'], 'ReflectionObject::getShortName' => ['string'], 'ReflectionObject::getStartLine' => ['false|int'], 'ReflectionObject::getStaticProperties' => ['ReflectionProperty[]'], 'ReflectionObject::getStaticPropertyValue' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'ReflectionObject::getTraitAliases' => ['array'], 'ReflectionObject::getTraitNames' => ['list'], 'ReflectionObject::getTraits' => ['array'], 'ReflectionObject::hasConstant' => ['bool', 'name'=>'string'], 'ReflectionObject::hasMethod' => ['bool', 'name'=>'string'], 'ReflectionObject::hasProperty' => ['bool', 'name'=>'string'], 'ReflectionObject::implementsInterface' => ['bool', 'interface_name'=>'ReflectionClass|string'], 'ReflectionObject::inNamespace' => ['bool'], 'ReflectionObject::isAbstract' => ['bool'], 'ReflectionObject::isAnonymous' => ['bool'], 'ReflectionObject::isCloneable' => ['bool'], 'ReflectionObject::isFinal' => ['bool'], 'ReflectionObject::isInstance' => ['bool', 'object'=>'object'], 'ReflectionObject::isInstantiable' => ['bool'], 'ReflectionObject::isInterface' => ['bool'], 'ReflectionObject::isInternal' => ['bool'], 'ReflectionObject::isIterable' => ['bool'], 'ReflectionObject::isIterateable' => ['bool'], 'ReflectionObject::isSubclassOf' => ['bool', 'class'=>'ReflectionClass|string'], 'ReflectionObject::isTrait' => ['bool'], 'ReflectionObject::isUserDefined' => ['bool'], 'ReflectionObject::newInstance' => ['object', 'args='=>'mixed', '...args='=>'array'], 'ReflectionObject::newInstanceArgs' => ['object', 'args='=>'array'], 'ReflectionObject::newInstanceWithoutConstructor' => ['object'], 'ReflectionObject::setStaticPropertyValue' => ['void', 'name'=>'string', 'value'=>'string'], 'ReflectionParameter::__clone' => ['void'], 'ReflectionParameter::__construct' => ['void', 'function'=>'', 'parameter'=>''], 'ReflectionParameter::__toString' => ['string'], 'ReflectionParameter::allowsNull' => ['bool'], 'ReflectionParameter::canBePassedByValue' => ['bool'], 'ReflectionParameter::export' => ['?string', 'function'=>'string', 'parameter'=>'string', 'return='=>'bool'], 'ReflectionParameter::getClass' => ['?ReflectionClass'], 'ReflectionParameter::getDeclaringClass' => ['?ReflectionClass'], 'ReflectionParameter::getDeclaringFunction' => ['ReflectionFunctionAbstract'], 'ReflectionParameter::getDefaultValue' => ['mixed'], 'ReflectionParameter::getDefaultValueConstantName' => ['?string'], 'ReflectionParameter::getName' => ['string'], 'ReflectionParameter::getPosition' => ['int'], 'ReflectionParameter::getType' => ['?ReflectionType'], 'ReflectionParameter::hasType' => ['bool'], 'ReflectionParameter::isArray' => ['bool'], 'ReflectionParameter::isCallable' => ['?bool'], 'ReflectionParameter::isDefaultValueAvailable' => ['bool'], 'ReflectionParameter::isDefaultValueConstant' => ['bool'], 'ReflectionParameter::isOptional' => ['bool'], 'ReflectionParameter::isPassedByReference' => ['bool'], 'ReflectionParameter::isVariadic' => ['bool'], 'ReflectionProperty::__clone' => ['void'], 'ReflectionProperty::__construct' => ['void', 'class'=>'', 'name'=>'string'], 'ReflectionProperty::__toString' => ['string'], 'ReflectionProperty::export' => ['?string', 'class'=>'mixed', 'name'=>'string', 'return='=>'bool'], 'ReflectionProperty::getDeclaringClass' => ['ReflectionClass'], 'ReflectionProperty::getDocComment' => ['string|false'], 'ReflectionProperty::getModifiers' => ['int'], 'ReflectionProperty::getName' => ['string'], 'ReflectionProperty::getType' => ['?ReflectionType'], 'ReflectionProperty::getValue' => ['mixed', 'object='=>'object'], 'ReflectionProperty::isDefault' => ['bool'], 'ReflectionProperty::isPrivate' => ['bool'], 'ReflectionProperty::isProtected' => ['bool'], 'ReflectionProperty::isPublic' => ['bool'], 'ReflectionProperty::isStatic' => ['bool'], 'ReflectionProperty::setAccessible' => ['void', 'visible'=>'bool'], 'ReflectionProperty::setValue' => ['void', 'object'=>'null|object', 'value'=>''], 'ReflectionProperty::setValue\'1' => ['void', 'value'=>''], 'ReflectionType::__clone' => ['void'], 'ReflectionType::__toString' => ['string'], 'ReflectionType::allowsNull' => ['bool'], 'ReflectionType::getName' => ['string'], 'ReflectionType::isBuiltin' => ['bool'], 'ReflectionZendExtension::__clone' => ['void'], 'ReflectionZendExtension::__construct' => ['void', 'name'=>'string'], 'ReflectionZendExtension::__toString' => ['string'], 'ReflectionZendExtension::export' => ['?string', 'name'=>'string', 'return='=>'bool'], 'ReflectionZendExtension::getAuthor' => ['string'], 'ReflectionZendExtension::getCopyright' => ['string'], 'ReflectionZendExtension::getName' => ['string'], 'ReflectionZendExtension::getURL' => ['string'], 'ReflectionZendExtension::getVersion' => ['string'], 'Reflector::__toString' => ['string'], 'Reflector::export' => ['?string'], 'RegexIterator::__construct' => ['void', 'iterator'=>'Iterator', 'regex'=>'string', 'mode='=>'int', 'flags='=>'int', 'preg_flags='=>'int'], 'RegexIterator::accept' => ['bool'], 'RegexIterator::current' => ['mixed'], 'RegexIterator::getFlags' => ['int'], 'RegexIterator::getInnerIterator' => ['Iterator'], 'RegexIterator::getMode' => ['int'], 'RegexIterator::getPregFlags' => ['int'], 'RegexIterator::getRegex' => ['string'], 'RegexIterator::key' => ['mixed'], 'RegexIterator::next' => ['void'], 'RegexIterator::rewind' => ['void'], 'RegexIterator::setFlags' => ['void', 'new_flags'=>'int'], 'RegexIterator::setMode' => ['void', 'new_mode'=>'int'], 'RegexIterator::setPregFlags' => ['void', 'new_flags'=>'int'], 'RegexIterator::valid' => ['bool'], 'register_event_handler' => ['bool', 'event_handler_func'=>'string', 'handler_register_name'=>'string', 'event_type_mask'=>'int'], 'register_shutdown_function' => ['void', 'function'=>'callable', '...parameter='=>'mixed'], 'register_tick_function' => ['bool', 'function'=>'callable():void', '...args='=>'mixed'], 'rename' => ['bool', 'old_name'=>'string', 'new_name'=>'string', 'context='=>'resource'], 'rename_function' => ['bool', 'original_name'=>'string', 'new_name'=>'string'], 'reset' => ['mixed|false', '&r_array'=>'array|object'], 'ResourceBundle::__construct' => ['void', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'], 'ResourceBundle::count' => ['int'], 'ResourceBundle::create' => ['?ResourceBundle', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'], 'ResourceBundle::get' => ['', 'index'=>'string|int', 'fallback='=>'bool'], 'ResourceBundle::getErrorCode' => ['int'], 'ResourceBundle::getErrorMessage' => ['string'], 'ResourceBundle::getLocales' => ['array', 'bundlename'=>'string'], 'resourcebundle_count' => ['int', 'r'=>'ResourceBundle'], 'resourcebundle_create' => ['?ResourceBundle', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'], 'resourcebundle_get' => ['mixed|null', 'r'=>'ResourceBundle', 'index'=>'string|int', 'fallback='=>'bool'], 'resourcebundle_get_error_code' => ['int', 'r'=>'ResourceBundle'], 'resourcebundle_get_error_message' => ['string', 'r'=>'ResourceBundle'], 'resourcebundle_locales' => ['array', 'bundlename'=>'string'], 'restore_error_handler' => ['true'], 'restore_exception_handler' => ['bool'], 'restore_include_path' => ['void'], 'rewind' => ['bool', 'fp'=>'resource'], 'rewinddir' => ['null|false', 'dir_handle='=>'resource'], 'rmdir' => ['bool', 'dirname'=>'string', 'context='=>'resource'], 'round' => ['float', 'number'=>'float', 'precision='=>'int', 'mode='=>'int'], 'rpm_close' => ['bool', 'rpmr'=>'resource'], 'rpm_get_tag' => ['mixed', 'rpmr'=>'resource', 'tagnum'=>'int'], 'rpm_is_valid' => ['bool', 'filename'=>'string'], 'rpm_open' => ['resource|false', 'filename'=>'string'], 'rpm_version' => ['string'], 'rpmaddtag' => ['bool', 'tag'=>'int'], 'rpmdbinfo' => ['array', 'nevr'=>'string', 'full='=>'bool'], 'rpmdbsearch' => ['array', 'pattern'=>'string', 'rpmtag='=>'int', 'rpmmire='=>'int', 'full='=>'bool'], 'rpminfo' => ['array', 'path'=>'string', 'full='=>'bool', 'error='=>'string'], 'rpmvercmp' => ['int', 'evr1'=>'string', 'evr2'=>'string'], 'rrd_create' => ['bool', 'filename'=>'string', 'options'=>'array'], 'rrd_disconnect' => ['void'], 'rrd_error' => ['string'], 'rrd_fetch' => ['array', 'filename'=>'string', 'options'=>'array'], 'rrd_first' => ['int|false', 'file'=>'string', 'raaindex='=>'int'], 'rrd_graph' => ['array|false', 'filename'=>'string', 'options'=>'array'], 'rrd_info' => ['array|false', 'filename'=>'string'], 'rrd_last' => ['int', 'filename'=>'string'], 'rrd_lastupdate' => ['array|false', 'filename'=>'string'], 'rrd_restore' => ['bool', 'xml_file'=>'string', 'rrd_file'=>'string', 'options='=>'array'], 'rrd_tune' => ['bool', 'filename'=>'string', 'options'=>'array'], 'rrd_update' => ['bool', 'filename'=>'string', 'options'=>'array'], 'rrd_version' => ['string'], 'rrd_xport' => ['array|false', 'options'=>'array'], 'rrdc_disconnect' => ['void'], 'RRDCreator::__construct' => ['void', 'path'=>'string', 'starttime='=>'string', 'step='=>'int'], 'RRDCreator::addArchive' => ['void', 'description'=>'string'], 'RRDCreator::addDataSource' => ['void', 'description'=>'string'], 'RRDCreator::save' => ['bool'], 'RRDGraph::__construct' => ['void', 'path'=>'string'], 'RRDGraph::save' => ['array|false'], 'RRDGraph::saveVerbose' => ['array|false'], 'RRDGraph::setOptions' => ['void', 'options'=>'array'], 'RRDUpdater::__construct' => ['void', 'path'=>'string'], 'RRDUpdater::update' => ['bool', 'values'=>'array', 'time='=>'string'], 'rsort' => ['bool', '&rw_array'=>'array', 'sort_flags='=>'int'], 'rtrim' => ['string', 'string'=>'string', 'character_mask='=>'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'], 'runkit7_constant_remove' => ['bool', 'constant_name'=>'string'], 'runkit7_function_add' => ['bool', 'function_name'=>'string', 'argument_list_or_closure'=>'Closure|string', 'code_or_doc_comment='=>'?string', 'return_by_reference='=>'?bool', 'doc_comment='=>'?string', 'return_type='=>'?string', 'is_strict='=>'?bool'], 'runkit7_function_copy' => ['bool', 'source_name'=>'string', 'target_name'=>'string'], 'runkit7_function_redefine' => ['bool', 'function_name'=>'string', 'argument_list_or_closure'=>'Closure|string', 'code_or_doc_comment='=>'?string', 'return_by_reference='=>'?bool', 'doc_comment='=>'?string', 'return_type='=>'?string', 'is_strict='=>'?bool'], 'runkit7_function_remove' => ['bool', 'function_name'=>'string'], 'runkit7_function_rename' => ['bool', 'source_name'=>'string', 'target_name'=>'string'], 'runkit7_import' => ['bool', 'filename'=>'string', 'flags='=>'?int'], 'runkit7_method_add' => ['bool', 'class_name'=>'string', 'method_name'=>'string', 'argument_list_or_closure'=>'Closure|string', 'code_or_flags='=>'int|null|string', 'flags_or_doc_comment='=>'int|null|string', 'doc_comment='=>'?string', 'return_type='=>'?string', 'is_strict='=>'?bool'], 'runkit7_method_copy' => ['bool', 'destination_class'=>'string', 'destination_method'=>'string', 'source_class'=>'string', 'source_method='=>'?string'], 'runkit7_method_redefine' => ['bool', 'class_name'=>'string', 'method_name'=>'string', 'argument_list_or_closure'=>'Closure|string', 'code_or_flags='=>'int|null|string', 'flags_or_doc_comment='=>'int|null|string', 'doc_comment='=>'?string', 'return_type='=>'?string', 'is_strict='=>'?bool'], 'runkit7_method_remove' => ['bool', 'class_name'=>'string', 'method_name'=>'string'], 'runkit7_method_rename' => ['bool', 'class_name'=>'string', 'source_method_name'=>'string', 'source_target_name'=>'string'], 'runkit7_superglobals' => ['array'], 'runkit7_zval_inspect' => ['array', 'value'=>'mixed'], 'runkit_class_adopt' => ['bool', 'classname'=>'string', 'parentname'=>'string'], 'runkit_class_emancipate' => ['bool', 'classname'=>'string'], 'runkit_constant_add' => ['bool', 'constname'=>'string', 'value'=>'mixed'], 'runkit_constant_redefine' => ['bool', 'constname'=>'string', 'newvalue'=>'mixed'], 'runkit_constant_remove' => ['bool', 'constname'=>'string'], 'runkit_function_add' => ['bool', 'funcname'=>'string', 'arglist'=>'string', 'code'=>'string', 'doccomment='=>'?string'], 'runkit_function_add\'1' => ['bool', 'funcname'=>'string', 'closure'=>'Closure', 'doccomment='=>'?string'], 'runkit_function_copy' => ['bool', 'funcname'=>'string', 'targetname'=>'string'], 'runkit_function_redefine' => ['bool', 'funcname'=>'string', 'arglist'=>'string', 'code'=>'string', 'doccomment='=>'?string'], 'runkit_function_redefine\'1' => ['bool', 'funcname'=>'string', 'closure'=>'Closure', 'doccomment='=>'?string'], 'runkit_function_remove' => ['bool', 'funcname'=>'string'], 'runkit_function_rename' => ['bool', 'funcname'=>'string', 'newname'=>'string'], 'runkit_import' => ['bool', 'filename'=>'string', 'flags='=>'int'], 'runkit_lint' => ['bool', 'code'=>'string'], 'runkit_lint_file' => ['bool', 'filename'=>'string'], 'runkit_method_add' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'args'=>'string', 'code'=>'string', 'flags='=>'int', 'doccomment='=>'?string'], 'runkit_method_add\'1' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'closure'=>'Closure', 'flags='=>'int', 'doccomment='=>'?string'], 'runkit_method_copy' => ['bool', 'dclass'=>'string', 'dmethod'=>'string', 'sclass'=>'string', 'smethod='=>'string'], 'runkit_method_redefine' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'args'=>'string', 'code'=>'string', 'flags='=>'int', 'doccomment='=>'?string'], 'runkit_method_redefine\'1' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'closure'=>'Closure', 'flags='=>'int', 'doccomment='=>'?string'], 'runkit_method_remove' => ['bool', 'classname'=>'string', 'methodname'=>'string'], 'runkit_method_rename' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'newname'=>'string'], 'runkit_return_value_used' => ['bool'], 'Runkit_Sandbox::__construct' => ['void', 'options='=>'array'], 'runkit_sandbox_output_handler' => ['mixed', 'sandbox'=>'object', 'callback='=>'mixed'], 'Runkit_Sandbox_Parent' => [''], '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'], 'RuntimeException::__toString' => ['string'], 'RuntimeException::getCode' => ['int'], 'RuntimeException::getFile' => ['string'], 'RuntimeException::getLine' => ['int'], 'RuntimeException::getMessage' => ['string'], 'RuntimeException::getPrevious' => ['Throwable|RuntimeException|null'], 'RuntimeException::getTrace' => ['list>'], 'RuntimeException::getTraceAsString' => ['string'], 'SAMConnection::commit' => ['bool'], 'SAMConnection::connect' => ['bool', 'protocol'=>'string', 'properties='=>'array'], 'SAMConnection::disconnect' => ['bool'], 'SAMConnection::errno' => ['int'], 'SAMConnection::error' => ['string'], 'SAMConnection::isConnected' => ['bool'], 'SAMConnection::peek' => ['SAMMessage', 'target'=>'string', 'properties='=>'array'], 'SAMConnection::peekAll' => ['array', 'target'=>'string', 'properties='=>'array'], 'SAMConnection::receive' => ['SAMMessage', 'target'=>'string', 'properties='=>'array'], 'SAMConnection::remove' => ['SAMMessage', 'target'=>'string', 'properties='=>'array'], 'SAMConnection::rollback' => ['bool'], 'SAMConnection::send' => ['string', 'target'=>'string', 'msg'=>'sammessage', 'properties='=>'array'], 'SAMConnection::setDebug' => ['', 'switch'=>'bool'], 'SAMConnection::subscribe' => ['string', 'targettopic'=>'string'], 'SAMConnection::unsubscribe' => ['bool', 'subscriptionid'=>'string', 'targettopic='=>'string'], 'SAMMessage::body' => ['string'], 'SAMMessage::header' => ['object'], 'sapi_windows_cp_conv' => ['string', 'in_codepage'=>'int|string', 'out_codepage'=>'int|string', 'subject'=>'string'], 'sapi_windows_cp_get' => ['int'], 'sapi_windows_cp_is_utf8' => ['bool'], 'sapi_windows_cp_set' => ['bool', 'code_page'=>'int'], 'sapi_windows_vt100_support' => ['bool', 'stream'=>'resource', 'enable='=>'bool'], 'Saxon\SaxonProcessor::__construct' => ['void', 'license='=>'bool', 'cwd='=>'string'], 'Saxon\SaxonProcessor::createAtomicValue' => ['Saxon\XdmValue', 'primitive_type_val'=>'bool|float|int|string'], 'Saxon\SaxonProcessor::newSchemaValidator' => ['Saxon\SchemaValidator'], 'Saxon\SaxonProcessor::newXPathProcessor' => ['Saxon\XPathProcessor'], 'Saxon\SaxonProcessor::newXQueryProcessor' => ['Saxon\XQueryProcessor'], 'Saxon\SaxonProcessor::newXsltProcessor' => ['Saxon\XsltProcessor'], 'Saxon\SaxonProcessor::parseXmlFromFile' => ['Saxon\XdmNode', 'fileName'=>'string'], 'Saxon\SaxonProcessor::parseXmlFromString' => ['Saxon\XdmNode', 'value'=>'string'], 'Saxon\SaxonProcessor::registerPHPFunctions' => ['void', 'library'=>'string'], 'Saxon\SaxonProcessor::setConfigurationProperty' => ['void', 'name'=>'string', 'value'=>'string'], 'Saxon\SaxonProcessor::setcwd' => ['void', 'cwd'=>'string'], 'Saxon\SaxonProcessor::setResourceDirectory' => ['void', 'dir'=>'string'], 'Saxon\SaxonProcessor::version' => ['string'], 'Saxon\SchemaValidator::clearParameters' => ['void'], 'Saxon\SchemaValidator::clearProperties' => ['void'], 'Saxon\SchemaValidator::exceptionClear' => ['void'], 'Saxon\SchemaValidator::getErrorCode' => ['string', 'i'=>'int'], 'Saxon\SchemaValidator::getErrorMessage' => ['string', 'i'=>'int'], 'Saxon\SchemaValidator::getExceptionCount' => ['int'], 'Saxon\SchemaValidator::getValidationReport' => ['Saxon\XdmNode'], 'Saxon\SchemaValidator::registerSchemaFromFile' => ['void', 'fileName'=>'string'], 'Saxon\SchemaValidator::registerSchemaFromString' => ['void', 'schemaStr'=>'string'], 'Saxon\SchemaValidator::setOutputFile' => ['void', 'fileName'=>'string'], 'Saxon\SchemaValidator::setParameter' => ['void', 'name'=>'string', 'value'=>'Saxon\XdmValue'], 'Saxon\SchemaValidator::setProperty' => ['void', 'name'=>'string', 'value'=>'string'], 'Saxon\SchemaValidator::setSourceNode' => ['void', 'node'=>'Saxon\XdmNode'], 'Saxon\SchemaValidator::validate' => ['void', 'filename='=>'?string'], 'Saxon\SchemaValidator::validateToNode' => ['Saxon\XdmNode', 'filename='=>'?string'], 'Saxon\XdmAtomicValue::addXdmItem' => ['', 'item'=>'Saxon\XdmItem'], 'Saxon\XdmAtomicValue::getAtomicValue' => ['?Saxon\XdmAtomicValue'], 'Saxon\XdmAtomicValue::getBooleanValue' => ['bool'], 'Saxon\XdmAtomicValue::getDoubleValue' => ['float'], 'Saxon\XdmAtomicValue::getHead' => ['Saxon\XdmItem'], 'Saxon\XdmAtomicValue::getLongValue' => ['int'], 'Saxon\XdmAtomicValue::getNodeValue' => ['?Saxon\XdmNode'], 'Saxon\XdmAtomicValue::getStringValue' => ['string'], 'Saxon\XdmAtomicValue::isAtomic' => ['true'], 'Saxon\XdmAtomicValue::isNode' => ['bool'], 'Saxon\XdmAtomicValue::itemAt' => ['Saxon\XdmItem', 'index'=>'int'], 'Saxon\XdmAtomicValue::size' => ['int'], 'Saxon\XdmItem::addXdmItem' => ['', 'item'=>'Saxon\XdmItem'], 'Saxon\XdmItem::getAtomicValue' => ['?Saxon\XdmAtomicValue'], 'Saxon\XdmItem::getHead' => ['Saxon\XdmItem'], 'Saxon\XdmItem::getNodeValue' => ['?Saxon\XdmNode'], 'Saxon\XdmItem::getStringValue' => ['string'], 'Saxon\XdmItem::isAtomic' => ['bool'], 'Saxon\XdmItem::isNode' => ['bool'], 'Saxon\XdmItem::itemAt' => ['Saxon\XdmItem', 'index'=>'int'], 'Saxon\XdmItem::size' => ['int'], 'Saxon\XdmNode::addXdmItem' => ['', 'item'=>'Saxon\XdmItem'], 'Saxon\XdmNode::getAtomicValue' => ['?Saxon\XdmAtomicValue'], 'Saxon\XdmNode::getAttributeCount' => ['int'], 'Saxon\XdmNode::getAttributeNode' => ['?Saxon\XdmNode', 'index'=>'int'], 'Saxon\XdmNode::getAttributeValue' => ['?string', 'index'=>'int'], 'Saxon\XdmNode::getChildCount' => ['int'], 'Saxon\XdmNode::getChildNode' => ['?Saxon\XdmNode', 'index'=>'int'], 'Saxon\XdmNode::getHead' => ['Saxon\XdmItem'], 'Saxon\XdmNode::getNodeKind' => ['int'], 'Saxon\XdmNode::getNodeName' => ['string'], 'Saxon\XdmNode::getNodeValue' => ['?Saxon\XdmNode'], 'Saxon\XdmNode::getParent' => ['?Saxon\XdmNode'], 'Saxon\XdmNode::getStringValue' => ['string'], 'Saxon\XdmNode::isAtomic' => ['false'], 'Saxon\XdmNode::isNode' => ['bool'], 'Saxon\XdmNode::itemAt' => ['Saxon\XdmItem', 'index'=>'int'], 'Saxon\XdmNode::size' => ['int'], 'Saxon\XdmValue::addXdmItem' => ['', 'item'=>'Saxon\XdmItem'], 'Saxon\XdmValue::getHead' => ['Saxon\XdmItem'], 'Saxon\XdmValue::itemAt' => ['Saxon\XdmItem', 'index'=>'int'], 'Saxon\XdmValue::size' => ['int'], 'Saxon\XPathProcessor::clearParameters' => ['void'], 'Saxon\XPathProcessor::clearProperties' => ['void'], 'Saxon\XPathProcessor::declareNamespace' => ['void', 'prefix'=>'', 'namespace'=>''], 'Saxon\XPathProcessor::effectiveBooleanValue' => ['bool', 'xpathStr'=>'string'], 'Saxon\XPathProcessor::evaluate' => ['Saxon\XdmValue', 'xpathStr'=>'string'], 'Saxon\XPathProcessor::evaluateSingle' => ['Saxon\XdmItem', 'xpathStr'=>'string'], 'Saxon\XPathProcessor::exceptionClear' => ['void'], 'Saxon\XPathProcessor::getErrorCode' => ['string', 'i'=>'int'], 'Saxon\XPathProcessor::getErrorMessage' => ['string', 'i'=>'int'], 'Saxon\XPathProcessor::getExceptionCount' => ['int'], 'Saxon\XPathProcessor::setBaseURI' => ['void', 'uri'=>'string'], 'Saxon\XPathProcessor::setContextFile' => ['void', 'fileName'=>'string'], 'Saxon\XPathProcessor::setContextItem' => ['void', 'item'=>'Saxon\XdmItem'], 'Saxon\XPathProcessor::setParameter' => ['void', 'name'=>'string', 'value'=>'Saxon\XdmValue'], 'Saxon\XPathProcessor::setProperty' => ['void', 'name'=>'string', 'value'=>'string'], 'Saxon\XQueryProcessor::clearParameters' => ['void'], 'Saxon\XQueryProcessor::clearProperties' => ['void'], 'Saxon\XQueryProcessor::declareNamespace' => ['void', 'prefix'=>'string', 'namespace'=>'string'], 'Saxon\XQueryProcessor::exceptionClear' => ['void'], 'Saxon\XQueryProcessor::getErrorCode' => ['string', 'i'=>'int'], 'Saxon\XQueryProcessor::getErrorMessage' => ['string', 'i'=>'int'], 'Saxon\XQueryProcessor::getExceptionCount' => ['int'], 'Saxon\XQueryProcessor::runQueryToFile' => ['void', 'outfilename'=>'string'], 'Saxon\XQueryProcessor::runQueryToString' => ['?string'], 'Saxon\XQueryProcessor::runQueryToValue' => ['?Saxon\XdmValue'], 'Saxon\XQueryProcessor::setContextItem' => ['void', 'object'=>'Saxon\XdmAtomicValue|Saxon\XdmItem|Saxon\XdmNode|Saxon\XdmValue'], 'Saxon\XQueryProcessor::setContextItemFromFile' => ['void', 'fileName'=>'string'], 'Saxon\XQueryProcessor::setParameter' => ['void', 'name'=>'string', 'value'=>'Saxon\XdmValue'], 'Saxon\XQueryProcessor::setProperty' => ['void', 'name'=>'string', 'value'=>'string'], 'Saxon\XQueryProcessor::setQueryBaseURI' => ['void', 'uri'=>'string'], 'Saxon\XQueryProcessor::setQueryContent' => ['void', 'string'=>'string'], 'Saxon\XQueryProcessor::setQueryFile' => ['void', 'filename'=>'string'], 'Saxon\XQueryProcessor::setQueryItem' => ['void', 'item'=>'Saxon\XdmItem'], 'Saxon\XsltProcessor::clearParameters' => ['void'], 'Saxon\XsltProcessor::clearProperties' => ['void'], 'Saxon\XsltProcessor::compileFromFile' => ['void', 'fileName'=>'string'], 'Saxon\XsltProcessor::compileFromString' => ['void', 'string'=>'string'], 'Saxon\XsltProcessor::compileFromValue' => ['void', 'node'=>'Saxon\XdmNode'], 'Saxon\XsltProcessor::exceptionClear' => ['void'], 'Saxon\XsltProcessor::getErrorCode' => ['string', 'i'=>'int'], 'Saxon\XsltProcessor::getErrorMessage' => ['string', 'i'=>'int'], 'Saxon\XsltProcessor::getExceptionCount' => ['int'], 'Saxon\XsltProcessor::setOutputFile' => ['void', 'fileName'=>'string'], 'Saxon\XsltProcessor::setParameter' => ['void', 'name'=>'string', 'value'=>'Saxon\XdmValue'], 'Saxon\XsltProcessor::setProperty' => ['void', 'name'=>'string', 'value'=>'string'], 'Saxon\XsltProcessor::setSourceFromFile' => ['void', 'filename'=>'string'], 'Saxon\XsltProcessor::setSourceFromXdmValue' => ['void', 'value'=>'Saxon\XdmValue'], 'Saxon\XsltProcessor::transformFileToFile' => ['void', 'sourceFileName'=>'string', 'stylesheetFileName'=>'string', 'outputfileName'=>'string'], 'Saxon\XsltProcessor::transformFileToString' => ['?string', 'sourceFileName'=>'string', 'stylesheetFileName'=>'string'], 'Saxon\XsltProcessor::transformFileToValue' => ['Saxon\XdmValue', 'fileName'=>'string'], 'Saxon\XsltProcessor::transformToFile' => ['void'], 'Saxon\XsltProcessor::transformToString' => ['string'], 'Saxon\XsltProcessor::transformToValue' => ['?Saxon\XdmValue'], 'SCA::createDataObject' => ['SDO_DataObject', 'type_namespace_uri'=>'string', 'type_name'=>'string'], 'SCA::getService' => ['', 'target'=>'string', 'binding='=>'string', 'config='=>'array'], 'SCA_LocalProxy::createDataObject' => ['SDO_DataObject', 'type_namespace_uri'=>'string', 'type_name'=>'string'], 'SCA_SoapProxy::createDataObject' => ['SDO_DataObject', 'type_namespace_uri'=>'string', 'type_name'=>'string'], 'scalebarObj::convertToString' => ['string'], 'scalebarObj::free' => ['void'], 'scalebarObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'scalebarObj::setImageColor' => ['int', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'scalebarObj::updateFromString' => ['int', 'snippet'=>'string'], 'scandir' => ['list|false', 'dir'=>'string', 'sorting_order='=>'int', 'context='=>'resource'], 'SDO_DAS_ChangeSummary::beginLogging' => [''], 'SDO_DAS_ChangeSummary::endLogging' => [''], 'SDO_DAS_ChangeSummary::getChangedDataObjects' => ['SDO_List'], 'SDO_DAS_ChangeSummary::getChangeType' => ['int', 'dataobject'=>'sdo_dataobject'], 'SDO_DAS_ChangeSummary::getOldContainer' => ['SDO_DataObject', 'data_object'=>'sdo_dataobject'], 'SDO_DAS_ChangeSummary::getOldValues' => ['SDO_List', 'data_object'=>'sdo_dataobject'], 'SDO_DAS_ChangeSummary::isLogging' => ['bool'], 'SDO_DAS_DataFactory::addPropertyToType' => ['', 'parent_type_namespace_uri'=>'string', 'parent_type_name'=>'string', 'property_name'=>'string', 'type_namespace_uri'=>'string', 'type_name'=>'string', 'options='=>'array'], 'SDO_DAS_DataFactory::addType' => ['', 'type_namespace_uri'=>'string', 'type_name'=>'string', 'options='=>'array'], 'SDO_DAS_DataFactory::getDataFactory' => ['SDO_DAS_DataFactory'], 'SDO_DAS_DataObject::getChangeSummary' => ['SDO_DAS_ChangeSummary'], 'SDO_DAS_Relational::__construct' => ['void', 'database_metadata'=>'array', 'application_root_type='=>'string', 'sdo_containment_references_metadata='=>'array'], 'SDO_DAS_Relational::applyChanges' => ['', 'database_handle'=>'pdo', 'root_data_object'=>'sdodataobject'], 'SDO_DAS_Relational::createRootDataObject' => ['SDODataObject'], 'SDO_DAS_Relational::executePreparedQuery' => ['SDODataObject', 'database_handle'=>'pdo', 'prepared_statement'=>'pdostatement', 'value_list'=>'array', 'column_specifier='=>'array'], 'SDO_DAS_Relational::executeQuery' => ['SDODataObject', 'database_handle'=>'pdo', 'sql_statement'=>'string', 'column_specifier='=>'array'], 'SDO_DAS_Setting::getListIndex' => ['int'], 'SDO_DAS_Setting::getPropertyIndex' => ['int'], 'SDO_DAS_Setting::getPropertyName' => ['string'], 'SDO_DAS_Setting::getValue' => [''], 'SDO_DAS_Setting::isSet' => ['bool'], 'SDO_DAS_XML::addTypes' => ['', 'xsd_file'=>'string'], 'SDO_DAS_XML::create' => ['SDO_DAS_XML', 'xsd_file='=>'mixed', 'key='=>'string'], 'SDO_DAS_XML::createDataObject' => ['SDO_DataObject', 'namespace_uri'=>'string', 'type_name'=>'string'], 'SDO_DAS_XML::createDocument' => ['SDO_DAS_XML_Document', 'document_element_name'=>'string', 'document_element_namespace_uri'=>'string', 'dataobject='=>'sdo_dataobject'], 'SDO_DAS_XML::loadFile' => ['SDO_XMLDocument', 'xml_file'=>'string'], 'SDO_DAS_XML::loadString' => ['SDO_DAS_XML_Document', 'xml_string'=>'string'], 'SDO_DAS_XML::saveFile' => ['', 'xdoc'=>'sdo_xmldocument', 'xml_file'=>'string', 'indent='=>'int'], 'SDO_DAS_XML::saveString' => ['string', 'xdoc'=>'sdo_xmldocument', 'indent='=>'int'], 'SDO_DAS_XML_Document::getRootDataObject' => ['SDO_DataObject'], 'SDO_DAS_XML_Document::getRootElementName' => ['string'], 'SDO_DAS_XML_Document::getRootElementURI' => ['string'], 'SDO_DAS_XML_Document::setEncoding' => ['', 'encoding'=>'string'], 'SDO_DAS_XML_Document::setXMLDeclaration' => ['', 'xmldeclatation'=>'bool'], 'SDO_DAS_XML_Document::setXMLVersion' => ['', 'xmlversion'=>'string'], 'SDO_DataFactory::create' => ['void', 'type_namespace_uri'=>'string', 'type_name'=>'string'], 'SDO_DataObject::clear' => ['void'], 'SDO_DataObject::createDataObject' => ['SDO_DataObject', 'identifier'=>''], 'SDO_DataObject::getContainer' => ['SDO_DataObject'], 'SDO_DataObject::getSequence' => ['SDO_Sequence'], 'SDO_DataObject::getTypeName' => ['string'], 'SDO_DataObject::getTypeNamespaceURI' => ['string'], 'SDO_Exception::getCause' => [''], 'SDO_List::insert' => ['void', 'value'=>'mixed', 'index='=>'int'], 'SDO_Model_Property::getContainingType' => ['SDO_Model_Type'], 'SDO_Model_Property::getDefault' => [''], 'SDO_Model_Property::getName' => ['string'], 'SDO_Model_Property::getType' => ['SDO_Model_Type'], 'SDO_Model_Property::isContainment' => ['bool'], 'SDO_Model_Property::isMany' => ['bool'], 'SDO_Model_ReflectionDataObject::__construct' => ['void', 'data_object'=>'sdo_dataobject'], 'SDO_Model_ReflectionDataObject::export' => ['mixed', 'rdo'=>'sdo_model_reflectiondataobject', 'return='=>'bool'], 'SDO_Model_ReflectionDataObject::getContainmentProperty' => ['SDO_Model_Property'], 'SDO_Model_ReflectionDataObject::getInstanceProperties' => ['array'], 'SDO_Model_ReflectionDataObject::getType' => ['SDO_Model_Type'], 'SDO_Model_Type::getBaseType' => ['SDO_Model_Type'], 'SDO_Model_Type::getName' => ['string'], 'SDO_Model_Type::getNamespaceURI' => ['string'], 'SDO_Model_Type::getProperties' => ['array'], 'SDO_Model_Type::getProperty' => ['SDO_Model_Property', 'identifier'=>''], 'SDO_Model_Type::isAbstractType' => ['bool'], 'SDO_Model_Type::isDataType' => ['bool'], 'SDO_Model_Type::isInstance' => ['bool', 'data_object'=>'sdo_dataobject'], 'SDO_Model_Type::isOpenType' => ['bool'], 'SDO_Model_Type::isSequencedType' => ['bool'], 'SDO_Sequence::getProperty' => ['SDO_Model_Property', 'sequence_index'=>'int'], 'SDO_Sequence::insert' => ['void', 'value'=>'mixed', 'sequenceindex='=>'int', 'propertyidentifier='=>'mixed'], 'SDO_Sequence::move' => ['void', 'toindex'=>'int', 'fromindex'=>'int'], 'SeasLog::__destruct' => ['void'], 'SeasLog::alert' => ['bool', 'message'=>'string', 'content='=>'array', 'logger='=>'string'], 'SeasLog::analyzerCount' => ['mixed', 'level'=>'string', 'log_path='=>'string', 'key_word='=>'string'], 'SeasLog::analyzerDetail' => ['mixed', 'level'=>'string', 'log_path='=>'string', 'key_word='=>'string', 'start='=>'int', 'limit='=>'int', 'order='=>'int'], 'SeasLog::closeLoggerStream' => ['bool', 'model'=>'int', 'logger'=>'string'], 'SeasLog::critical' => ['bool', 'message'=>'string', 'content='=>'array', 'logger='=>'string'], 'SeasLog::debug' => ['bool', 'message'=>'string', 'content='=>'array', 'logger='=>'string'], 'SeasLog::emergency' => ['bool', 'message'=>'string', 'content='=>'array', 'logger='=>'string'], 'SeasLog::error' => ['bool', 'message'=>'string', 'content='=>'array', 'logger='=>'string'], 'SeasLog::flushBuffer' => ['bool'], 'SeasLog::getBasePath' => ['string'], 'SeasLog::getBuffer' => ['array'], 'SeasLog::getBufferEnabled' => ['bool'], 'SeasLog::getDatetimeFormat' => ['string'], 'SeasLog::getLastLogger' => ['string'], 'SeasLog::getRequestID' => ['string'], 'SeasLog::getRequestVariable' => ['bool', 'key'=>'int'], 'SeasLog::info' => ['bool', 'message'=>'string', 'content='=>'array', 'logger='=>'string'], 'SeasLog::log' => ['bool', 'level'=>'string', 'message='=>'string', 'content='=>'array', 'logger='=>'string'], 'SeasLog::notice' => ['bool', 'message'=>'string', 'content='=>'array', 'logger='=>'string'], 'SeasLog::setBasePath' => ['bool', 'base_path'=>'string'], 'SeasLog::setDatetimeFormat' => ['bool', 'format'=>'string'], 'SeasLog::setLogger' => ['bool', 'logger'=>'string'], 'SeasLog::setRequestID' => ['bool', 'request_id'=>'string'], 'SeasLog::setRequestVariable' => ['bool', 'key'=>'int', 'value'=>'string'], 'SeasLog::warning' => ['bool', 'message'=>'string', 'content='=>'array', 'logger='=>'string'], 'seaslog_get_author' => ['string'], 'seaslog_get_version' => ['string'], 'SeekableIterator::__construct' => ['void'], 'SeekableIterator::current' => ['mixed'], 'SeekableIterator::key' => ['int|string'], 'SeekableIterator::next' => ['void'], 'SeekableIterator::rewind' => ['void'], 'SeekableIterator::seek' => ['void', 'position'=>'int'], 'SeekableIterator::valid' => ['bool'], 'sem_acquire' => ['bool', 'sem_identifier'=>'resource', 'nowait='=>'bool'], 'sem_get' => ['resource|false', 'key'=>'int', 'max_acquire='=>'int', 'perm='=>'int', 'auto_release='=>'int'], 'sem_release' => ['bool', 'sem_identifier'=>'resource'], 'sem_remove' => ['bool', 'sem_identifier'=>'resource'], 'Serializable::__construct' => ['void'], 'Serializable::serialize' => ['?string'], 'Serializable::unserialize' => ['void', 'serialized'=>'string'], 'serialize' => ['string', 'variable'=>'mixed'], 'ServerRequest::withInput' => ['ServerRequest', 'input'=>'mixed'], 'ServerRequest::withoutParams' => ['ServerRequest', 'params'=>'int|string'], 'ServerRequest::withParam' => ['ServerRequest', 'key'=>'int|string', 'value'=>'mixed'], 'ServerRequest::withParams' => ['ServerRequest', 'params'=>'mixed'], 'ServerRequest::withUrl' => ['ServerRequest', 'url'=>'array'], 'ServerResponse::addHeader' => ['void', 'label'=>'string', 'value'=>'string'], 'ServerResponse::date' => ['string', 'date'=>'string|DateTimeInterface'], 'ServerResponse::getHeader' => ['string', 'label'=>'string'], 'ServerResponse::getHeaders' => ['string[]'], 'ServerResponse::getStatus' => ['int'], 'ServerResponse::getVersion' => ['string'], 'ServerResponse::setHeader' => ['void', 'label'=>'string', 'value'=>'string'], 'ServerResponse::setStatus' => ['void', 'status'=>'int'], 'ServerResponse::setVersion' => ['void', 'version'=>'string'], 'session_abort' => ['bool'], 'session_cache_expire' => ['int', 'new_cache_expire='=>'int'], 'session_cache_limiter' => ['string', 'new_cache_limiter='=>'string'], 'session_commit' => ['bool'], 'session_create_id' => ['string', 'prefix='=>'string'], 'session_decode' => ['bool', 'data'=>'string'], 'session_destroy' => ['bool'], 'session_encode' => ['string'], 'session_gc' => ['int|false'], 'session_get_cookie_params' => ['array'], 'session_id' => ['string', 'newid='=>'string'], 'session_is_registered' => ['bool', 'name'=>'string'], 'session_module_name' => ['string', 'newname='=>'string'], 'session_name' => ['string', 'newname='=>'string'], 'session_pgsql_add_error' => ['bool', 'error_level'=>'int', 'error_message='=>'string'], 'session_pgsql_get_error' => ['array', 'with_error_message='=>'bool'], 'session_pgsql_get_field' => ['string'], 'session_pgsql_reset' => ['bool'], 'session_pgsql_set_field' => ['bool', 'value'=>'string'], 'session_pgsql_status' => ['array'], 'session_regenerate_id' => ['bool', 'delete_old_session='=>'bool'], 'session_register' => ['bool', 'name'=>'mixed', '...args='=>'mixed'], 'session_register_shutdown' => ['void'], 'session_reset' => ['bool'], 'session_save_path' => ['string', 'newname='=>'string'], 'session_set_cookie_params' => ['bool', 'lifetime'=>'int', 'path='=>'string', 'domain='=>'?string', 'secure='=>'bool', 'httponly='=>'bool'], 'session_set_cookie_params\'1' => ['bool', 'options'=>'array{lifetime?:int,path?:string,domain?:?string,secure?:bool,httponly?:bool}'], 'session_set_save_handler' => ['bool', 'open'=>'callable(string,string):bool', 'close'=>'callable():bool', 'read'=>'callable(string):string', 'write'=>'callable(string,string):bool', 'destroy'=>'callable(string):bool', 'gc'=>'callable(string):bool', 'create_sid='=>'callable():string', 'validate_sid='=>'callable(string):bool', 'update_timestamp='=>'callable(string):bool'], 'session_set_save_handler\'1' => ['bool', 'sessionhandler'=>'SessionHandlerInterface', 'register_shutdown='=>'bool'], 'session_start' => ['bool', 'options='=>'array'], 'session_status' => ['int'], 'session_unregister' => ['bool', 'name'=>'string'], 'session_unset' => ['bool'], 'session_write_close' => ['bool'], 'SessionHandler::close' => ['bool'], 'SessionHandler::create_sid' => ['char'], 'SessionHandler::destroy' => ['bool', 'id'=>'string'], 'SessionHandler::gc' => ['bool', 'maxlifetime'=>'int'], 'SessionHandler::open' => ['bool', 'save_path'=>'string', 'session_name'=>'string'], 'SessionHandler::read' => ['string', 'id'=>'string'], 'SessionHandler::updateTimestamp' => ['bool', 'session_id'=>'string', 'session_data'=>'string'], 'SessionHandler::validateId' => ['bool', 'session_id'=>'string'], 'SessionHandler::write' => ['bool', 'id'=>'string', 'data'=>'string'], 'SessionHandlerInterface::close' => ['bool'], 'SessionHandlerInterface::destroy' => ['bool', 'session_id'=>'string'], 'SessionHandlerInterface::gc' => ['bool', 'maxlifetime'=>'int'], 'SessionHandlerInterface::open' => ['bool', 'save_path'=>'string', 'name'=>'string'], 'SessionHandlerInterface::read' => ['string', 'session_id'=>'string'], 'SessionHandlerInterface::write' => ['bool', 'session_id'=>'string', 'session_data'=>'string'], 'SessionIdInterface::create_sid' => ['string'], 'SessionUpdateTimestampHandler::updateTimestamp' => ['bool', 'id'=>'string', 'data'=>'string'], 'SessionUpdateTimestampHandler::validateId' => ['char', 'id'=>'string'], 'SessionUpdateTimestampHandlerInterface::updateTimestamp' => ['bool', 'key'=>'string', 'value'=>'string'], 'SessionUpdateTimestampHandlerInterface::validateId' => ['bool', 'key'=>'string'], 'set_error_handler' => ['null|callable(int,string,string=,int=,array=):bool', 'error_handler'=>'null|callable(int,string,string=,int=,array=):bool', 'error_types='=>'int'], 'set_exception_handler' => ['null|callable(Throwable):void', 'exception_handler'=>'null|callable(Throwable):void'], 'set_file_buffer' => ['int', 'fp'=>'resource', 'buffer'=>'int'], 'set_include_path' => ['string|false', 'new_include_path'=>'string'], 'set_magic_quotes_runtime' => ['bool', 'new_setting'=>'bool'], 'set_time_limit' => ['bool', 'seconds'=>'int'], 'setcookie' => ['bool', 'name'=>'string', 'value='=>'string', 'expires='=>'int', 'path='=>'string', 'domain='=>'string', 'secure='=>'bool', 'httponly='=>'bool', 'samesite='=>'string', 'url_encode='=>'int'], 'setcookie\'1' => ['bool', 'name'=>'string', 'value='=>'string', 'options='=>'array'], 'setLeftFill' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'setLine' => ['void', 'width'=>'int', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'setlocale' => ['string|false', 'category'=>'int', 'locale'=>'string|0|null', '...args='=>'string'], 'setlocale\'1' => ['string|false', 'category'=>'int', 'locale'=>'?array'], 'setproctitle' => ['void', 'title'=>'string'], 'setrawcookie' => ['bool', 'name'=>'string', 'value='=>'string', 'expires='=>'int', 'path='=>'string', 'domain='=>'string', 'secure='=>'bool', 'httponly='=>'bool'], 'setRightFill' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'setthreadtitle' => ['bool', 'title'=>'string'], 'settype' => ['bool', '&rw_var'=>'mixed', 'type'=>'string'], 'sha1' => ['string', 'string'=>'string', 'raw_output='=>'bool'], 'sha1_file' => ['string|false', 'filename'=>'string', 'raw_output='=>'bool'], 'sha256' => ['string', 'string'=>'string', 'raw_output='=>'bool'], 'sha256_file' => ['string', 'filename'=>'string', 'raw_output='=>'bool'], 'shapefileObj::__construct' => ['void', 'filename'=>'string', 'type'=>'int'], 'shapefileObj::addPoint' => ['int', 'point'=>'pointObj'], 'shapefileObj::addShape' => ['int', 'shape'=>'shapeObj'], 'shapefileObj::free' => ['void'], 'shapefileObj::getExtent' => ['rectObj', 'i'=>'int'], 'shapefileObj::getPoint' => ['shapeObj', 'i'=>'int'], 'shapefileObj::getShape' => ['shapeObj', 'i'=>'int'], 'shapefileObj::getTransformed' => ['shapeObj', 'map'=>'mapObj', 'i'=>'int'], 'shapefileObj::ms_newShapefileObj' => ['shapefileObj', 'filename'=>'string', 'type'=>'int'], 'shapeObj::__construct' => ['void', 'type'=>'int'], 'shapeObj::add' => ['int', 'line'=>'lineObj'], 'shapeObj::boundary' => ['shapeObj'], 'shapeObj::contains' => ['bool', 'point'=>'pointObj'], 'shapeObj::containsShape' => ['int', 'shape2'=>'shapeObj'], 'shapeObj::convexhull' => ['shapeObj'], 'shapeObj::crosses' => ['int', 'shape'=>'shapeObj'], 'shapeObj::difference' => ['shapeObj', 'shape'=>'shapeObj'], 'shapeObj::disjoint' => ['int', 'shape'=>'shapeObj'], 'shapeObj::draw' => ['int', 'map'=>'mapObj', 'layer'=>'layerObj', 'img'=>'imageObj'], 'shapeObj::equals' => ['int', 'shape'=>'shapeObj'], 'shapeObj::free' => ['void'], 'shapeObj::getArea' => ['float'], 'shapeObj::getCentroid' => ['pointObj'], 'shapeObj::getLabelPoint' => ['pointObj'], 'shapeObj::getLength' => ['float'], 'shapeObj::getPointUsingMeasure' => ['pointObj', 'm'=>'float'], 'shapeObj::getValue' => ['string', 'layer'=>'layerObj', 'filedname'=>'string'], 'shapeObj::intersection' => ['shapeObj', 'shape'=>'shapeObj'], 'shapeObj::intersects' => ['bool', 'shape'=>'shapeObj'], 'shapeObj::line' => ['lineObj', 'i'=>'int'], 'shapeObj::ms_shapeObjFromWkt' => ['shapeObj', 'wkt'=>'string'], 'shapeObj::overlaps' => ['int', 'shape'=>'shapeObj'], 'shapeObj::project' => ['int', 'in'=>'projectionObj', 'out'=>'projectionObj'], 'shapeObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'shapeObj::setBounds' => ['int'], 'shapeObj::simplify' => ['shapeObj|null', 'tolerance'=>'float'], 'shapeObj::symdifference' => ['shapeObj', 'shape'=>'shapeObj'], 'shapeObj::topologyPreservingSimplify' => ['shapeObj|null', 'tolerance'=>'float'], 'shapeObj::touches' => ['int', 'shape'=>'shapeObj'], 'shapeObj::toWkt' => ['string'], 'shapeObj::union' => ['shapeObj', 'shape'=>'shapeObj'], 'shapeObj::within' => ['int', 'shape2'=>'shapeObj'], 'shell_exec' => ['?string', 'cmd'=>'string'], 'shm_attach' => ['resource', 'key'=>'int', 'memsize='=>'int', 'perm='=>'int'], 'shm_detach' => ['bool', 'shm_identifier'=>'resource'], 'shm_get_var' => ['mixed', 'id'=>'resource', 'variable_key'=>'int'], 'shm_has_var' => ['bool', 'shm_identifier'=>'resource', 'variable_key'=>'int'], 'shm_put_var' => ['bool', 'shm_identifier'=>'resource', 'variable_key'=>'int', 'variable'=>'mixed'], 'shm_remove' => ['bool', 'shm_identifier'=>'resource'], 'shm_remove_var' => ['bool', 'shm_identifier'=>'resource', 'variable_key'=>'int'], 'shmop_close' => ['void', 'shmid'=>'resource'], 'shmop_delete' => ['bool', 'shmid'=>'resource'], 'shmop_open' => ['resource|false', 'key'=>'int', 'flags'=>'string', 'mode'=>'int', 'size'=>'int'], 'shmop_read' => ['string|false', 'shmid'=>'resource', 'start'=>'int', 'count'=>'int'], 'shmop_size' => ['int', 'shmid'=>'resource'], 'shmop_write' => ['int|false', 'shmid'=>'resource', 'data'=>'string', 'offset'=>'int'], 'show_source' => ['string|bool', 'file_name'=>'string', 'return='=>'bool'], 'shuffle' => ['bool', '&rw_array'=>'array'], 'signeurlpaiement' => ['string', 'clent'=>'string', 'data'=>'string'], 'similar_text' => ['int', 'string1'=>'string', 'string2'=>'string', '&w_percent='=>'float'], 'simplexml_import_dom' => ['SimpleXMLElement|false', 'node'=>'DOMNode', 'class_name='=>'string'], 'simplexml_load_file' => ['SimpleXMLElement|false', 'filename'=>'string', 'class_name='=>'string', 'options='=>'int', 'ns='=>'string', 'is_prefix='=>'bool'], 'simplexml_load_string' => ['SimpleXMLElement|false', 'data'=>'string', 'class_name='=>'string', 'options='=>'int', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLElement::__construct' => ['void', 'data'=>'string', 'options='=>'int', 'data_is_url='=>'bool', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLElement::__get' => ['SimpleXMLElement', 'name'=>'string'], 'SimpleXMLElement::__toString' => ['string'], 'SimpleXMLElement::addAttribute' => ['void', 'name'=>'string', 'value='=>'string', 'ns='=>'string'], 'SimpleXMLElement::addChild' => ['SimpleXMLElement', 'name'=>'string', 'value='=>'string', 'ns='=>'string'], 'SimpleXMLElement::asXML' => ['bool', 'filename'=>'string'], 'SimpleXMLElement::asXML\'1' => ['string|false'], 'SimpleXMLElement::attributes' => ['?SimpleXMLElement', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLElement::children' => ['SimpleXMLElement', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLElement::count' => ['int'], 'SimpleXMLElement::getDocNamespaces' => ['string[]', 'recursive='=>'bool', 'from_root='=>'bool'], 'SimpleXMLElement::getName' => ['string'], 'SimpleXMLElement::getNamespaces' => ['string[]', 'recursive='=>'bool'], 'SimpleXMLElement::offsetExists' => ['bool', 'offset'=>'int|string'], 'SimpleXMLElement::offsetGet' => ['SimpleXMLElement', 'offset'=>'int|string'], 'SimpleXMLElement::offsetSet' => ['void', 'offset'=>'int|string', 'value'=>'mixed'], 'SimpleXMLElement::offsetUnset' => ['void', 'offset'=>'int|string'], 'SimpleXMLElement::registerXPathNamespace' => ['bool', 'prefix'=>'string', 'ns'=>'string'], 'SimpleXMLElement::saveXML' => ['mixed', 'filename='=>'string'], 'SimpleXMLElement::xpath' => ['SimpleXMLElement[]|false', 'path'=>'string'], 'SimpleXMLIterator::__construct' => ['void', 'data'=>'string', 'options='=>'int', 'data_is_url='=>'bool', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLIterator::__toString' => ['string'], 'SimpleXMLIterator::addAttribute' => ['void', 'name'=>'string', 'value='=>'string', 'ns='=>'string'], 'SimpleXMLIterator::addChild' => ['SimpleXMLElement', 'name'=>'string', 'value='=>'string', 'ns='=>'string'], 'SimpleXMLIterator::asXML' => ['bool|string', 'filename='=>'string'], 'SimpleXMLIterator::attributes' => ['?SimpleXMLElement', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLIterator::children' => ['SimpleXMLElement', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLIterator::count' => ['int'], 'SimpleXMLIterator::current' => ['?SimpleXMLIterator'], 'SimpleXMLIterator::getChildren' => ['SimpleXMLIterator'], 'SimpleXMLIterator::getDocNamespaces' => ['string[]', 'recursive='=>'bool', 'from_root='=>'bool'], 'SimpleXMLIterator::getName' => ['string'], 'SimpleXMLIterator::getNamespaces' => ['string[]', 'recursive='=>'bool'], 'SimpleXMLIterator::hasChildren' => ['bool'], 'SimpleXMLIterator::key' => ['string|false'], 'SimpleXMLIterator::next' => ['void'], 'SimpleXMLIterator::registerXPathNamespace' => ['bool', 'prefix'=>'string', 'ns'=>'string'], 'SimpleXMLIterator::rewind' => ['void'], 'SimpleXMLIterator::saveXML' => ['mixed', 'filename='=>'string'], 'SimpleXMLIterator::valid' => ['bool'], 'SimpleXMLIterator::xpath' => ['SimpleXMLElement[]|false', 'path'=>'string'], 'sin' => ['float', 'number'=>'float'], 'sinh' => ['float', 'number'=>'float'], 'sizeof' => ['int', 'value'=>'Countable|array', 'mode='=>'int'], 'sleep' => ['int|false', 'seconds'=>'int'], 'snmp2_get' => ['string|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp2_getnext' => ['string|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp2_real_walk' => ['array|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp2_set' => ['bool', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp2_walk' => ['array|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_get' => ['string|false', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_getnext' => ['string|false', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_real_walk' => ['array|false', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_set' => ['bool', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_walk' => ['array|false', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'SNMP::__construct' => ['void', 'version'=>'int', 'hostname'=>'string', 'community'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'SNMP::close' => ['bool'], 'SNMP::get' => ['array|string|false', 'object_id'=>'string|array', 'preserve_keys='=>'bool'], 'SNMP::getErrno' => ['int'], 'SNMP::getError' => ['string'], 'SNMP::getnext' => ['string|array|false', 'object_id'=>'string|array'], 'SNMP::set' => ['bool', 'object_id'=>'string|array', 'type'=>'string|array', 'value'=>'mixed'], 'SNMP::setSecurity' => ['bool', 'sec_level'=>'string', 'auth_protocol='=>'string', 'auth_passphrase='=>'string', 'priv_protocol='=>'string', 'priv_passphrase='=>'string', 'contextname='=>'string', 'contextengineid='=>'string'], 'SNMP::walk' => ['array|false', 'object_id'=>'string', 'suffix_as_key='=>'bool', 'non_repeaters='=>'int', 'max_repetitions='=>'int'], 'snmp_get_quick_print' => ['bool'], 'snmp_get_valueretrieval' => ['int'], 'snmp_read_mib' => ['bool', 'filename'=>'string'], 'snmp_set_enum_print' => ['bool', 'enum_print'=>'int'], 'snmp_set_oid_numeric_print' => ['void', 'oid_format'=>'int'], 'snmp_set_oid_output_format' => ['bool', 'oid_format'=>'int'], 'snmp_set_quick_print' => ['bool', 'quick_print'=>'bool'], 'snmp_set_valueretrieval' => ['bool', 'method='=>'int'], 'snmpget' => ['string|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmpgetnext' => ['string|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmprealwalk' => ['array|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmpset' => ['bool', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'mixed', 'timeout='=>'int', 'retries='=>'int'], 'snmpwalk' => ['array|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmpwalkoid' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'SoapClient::__call' => ['', 'function_name'=>'string', 'arguments'=>'array'], 'SoapClient::__construct' => ['void', 'wsdl'=>'mixed', 'options='=>'array|null'], 'SoapClient::__doRequest' => ['string', 'request'=>'string', 'location'=>'string', 'action'=>'string', 'version'=>'int', 'one_way='=>'int'], 'SoapClient::__getCookies' => ['array'], 'SoapClient::__getFunctions' => ['array'], 'SoapClient::__getLastRequest' => ['string'], 'SoapClient::__getLastRequestHeaders' => ['string'], 'SoapClient::__getLastResponse' => ['string'], 'SoapClient::__getLastResponseHeaders' => ['string'], 'SoapClient::__getTypes' => ['array'], 'SoapClient::__setCookie' => ['', 'name'=>'string', 'value='=>'string'], 'SoapClient::__setLocation' => ['string', 'new_location='=>'string'], 'SoapClient::__setSoapHeaders' => ['bool', 'soapheaders='=>''], 'SoapClient::__soapCall' => ['', 'function_name'=>'string', 'arguments'=>'array', 'options='=>'array', 'input_headers='=>'SoapHeader|array', '&w_output_headers='=>'array'], 'SoapClient::SoapClient' => ['object', 'wsdl'=>'mixed', 'options='=>'array|null'], 'SoapFault::__clone' => ['void'], 'SoapFault::__construct' => ['void', 'faultcode'=>'string', 'faultstring'=>'string', 'faultactor='=>'string', 'detail='=>'string', 'faultname='=>'string', 'headerfault='=>'string'], 'SoapFault::__toString' => ['string'], 'SoapFault::__wakeup' => ['void'], 'SoapFault::getCode' => ['int'], 'SoapFault::getFile' => ['string'], 'SoapFault::getLine' => ['int'], 'SoapFault::getMessage' => ['string'], 'SoapFault::getPrevious' => ['?Exception|?Throwable'], 'SoapFault::getTrace' => ['list>'], 'SoapFault::getTraceAsString' => ['string'], 'SoapFault::SoapFault' => ['object', 'faultcode'=>'string', 'faultstring'=>'string', 'faultactor='=>'string', 'detail='=>'string', 'faultname='=>'string', 'headerfault='=>'string'], 'SoapHeader::__construct' => ['void', 'namespace'=>'string', 'name'=>'string', 'data='=>'mixed', 'mustunderstand='=>'bool', 'actor='=>'string'], 'SoapHeader::SoapHeader' => ['object', 'namespace'=>'string', 'name'=>'string', 'data='=>'mixed', 'mustunderstand='=>'bool', 'actor='=>'string'], 'SoapParam::__construct' => ['void', 'data'=>'mixed', 'name'=>'string'], 'SoapParam::SoapParam' => ['object', 'data'=>'mixed', 'name'=>'string'], 'SoapServer::__construct' => ['void', 'wsdl'=>'?string', 'options='=>'array'], 'SoapServer::addFunction' => ['void', 'functions'=>'mixed'], 'SoapServer::addSoapHeader' => ['void', 'object'=>'SoapHeader'], 'SoapServer::fault' => ['void', 'code'=>'string', 'string'=>'string', 'actor='=>'string', 'details='=>'string', 'name='=>'string'], 'SoapServer::getFunctions' => ['array'], 'SoapServer::handle' => ['void', 'soap_request='=>'string'], 'SoapServer::setClass' => ['void', 'class_name'=>'string', '...args='=>'mixed'], 'SoapServer::setObject' => ['void', 'object'=>'object'], 'SoapServer::setPersistence' => ['void', 'mode'=>'int'], 'SoapServer::SoapServer' => ['object', 'wsdl'=>'?string', 'options='=>'array'], 'SoapVar::__construct' => ['void', 'data'=>'mixed', 'encoding'=>'int', 'type_name='=>'string|null', 'type_namespace='=>'string|null', 'node_name='=>'string|null', 'node_namespace='=>'string|null'], 'SoapVar::SoapVar' => ['object', 'data'=>'mixed', 'encoding'=>'int', 'type_name='=>'string|null', 'type_namespace='=>'string|null', 'node_name='=>'string|null', 'node_namespace='=>'string|null'], 'socket_accept' => ['resource|false', 'socket'=>'resource'], 'socket_addrinfo_bind' => ['?resource', 'addrinfo'=>'resource'], 'socket_addrinfo_connect' => ['?resource', 'addrinfo'=>'resource'], 'socket_addrinfo_explain' => ['array', 'addrinfo'=>'resource'], 'socket_addrinfo_lookup' => ['AddressInfo[]', 'node'=>'string', 'service='=>'mixed', 'hints='=>'array'], 'socket_bind' => ['bool', 'socket'=>'resource', 'addr'=>'string', 'port='=>'int'], 'socket_clear_error' => ['void', 'socket='=>'resource'], 'socket_close' => ['void', 'socket'=>'resource'], 'socket_cmsg_space' => ['int', 'level'=>'int', 'type'=>'int'], 'socket_connect' => ['bool', 'socket'=>'resource', 'addr'=>'string', 'port='=>'int'], 'socket_create' => ['resource|false', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int'], 'socket_create_listen' => ['resource|false', 'port'=>'int', 'backlog='=>'int'], 'socket_create_pair' => ['bool', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int', '&w_fd'=>'resource[]'], 'socket_export_stream' => ['resource|false', 'socket'=>'resource'], 'socket_get_option' => ['mixed|false', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int'], 'socket_get_status' => ['array', 'stream'=>'resource'], 'socket_getopt' => ['mixed', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int'], 'socket_getpeername' => ['bool', 'socket'=>'resource', '&w_addr'=>'string', '&w_port='=>'int'], 'socket_getsockname' => ['bool', 'socket'=>'resource', '&w_addr'=>'string', '&w_port='=>'int'], 'socket_import_stream' => ['resource|false|null', 'stream'=>'resource'], 'socket_last_error' => ['int', 'socket='=>'resource'], 'socket_listen' => ['bool', 'socket'=>'resource', 'backlog='=>'int'], 'socket_read' => ['string|false', 'socket'=>'resource', 'length'=>'int', 'type='=>'int'], 'socket_recv' => ['int|false', 'socket'=>'resource', '&w_buf'=>'string', 'length'=>'int', 'flags'=>'int'], 'socket_recvfrom' => ['int|false', 'socket'=>'resource', '&w_buf'=>'string', 'length'=>'int', 'flags'=>'int', '&w_name'=>'string', '&w_port='=>'int'], 'socket_recvmsg' => ['int|false', 'socket'=>'resource', '&w_message'=>'string', 'flags='=>'int'], 'socket_select' => ['int|false', '&rw_read_fds'=>'resource[]|null', '&rw_write_fds'=>'resource[]|null', '&rw_except_fds'=>'resource[]|null', 'tv_sec'=>'int', 'tv_usec='=>'int'], 'socket_send' => ['int|false', 'socket'=>'resource', 'buf'=>'string', 'length'=>'int', 'flags'=>'int'], 'socket_sendmsg' => ['int|false', 'socket'=>'resource', 'message'=>'array', 'flags'=>'int'], 'socket_sendto' => ['int|false', 'socket'=>'resource', 'buf'=>'string', 'length'=>'int', 'flags'=>'int', 'addr'=>'string', 'port='=>'int'], 'socket_set_block' => ['bool', 'socket'=>'resource'], 'socket_set_blocking' => ['bool', 'socket'=>'resource', 'mode'=>'int'], 'socket_set_nonblock' => ['bool', 'socket'=>'resource'], 'socket_set_option' => ['bool', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int', 'optval'=>'int|string|array'], 'socket_set_timeout' => ['bool', 'stream'=>'resource', 'seconds'=>'int', 'microseconds='=>'int'], 'socket_setopt' => ['void', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int', 'optval'=>'int|string|array'], 'socket_shutdown' => ['bool', 'socket'=>'resource', 'how='=>'int'], 'socket_strerror' => ['string', 'errno'=>'int'], 'socket_write' => ['int|false', 'socket'=>'resource', 'buf'=>'string', 'length='=>'int'], 'socket_wsaprotocol_info_export' => ['string|false', 'stream'=>'resource', 'target_pid'=>'int'], 'socket_wsaprotocol_info_import' => ['resource|false', 'id'=>'string'], 'socket_wsaprotocol_info_release' => ['bool', 'id'=>'string'], 'Sodium\add' => ['void', '&left'=>'string', 'right'=>'string'], 'Sodium\bin2hex' => ['string', 'binary'=>'string'], 'Sodium\compare' => ['int', 'left'=>'string', 'right'=>'string'], 'Sodium\crypto_aead_aes256gcm_decrypt' => ['string|false', 'msg'=>'string', 'nonce'=>'string', 'key'=>'string', 'ad='=>'string'], 'Sodium\crypto_aead_aes256gcm_encrypt' => ['string', 'msg'=>'string', 'nonce'=>'string', 'key'=>'string', 'ad='=>'string'], 'Sodium\crypto_aead_aes256gcm_is_available' => ['bool'], 'Sodium\crypto_aead_chacha20poly1305_decrypt' => ['string', 'msg'=>'string', 'nonce'=>'string', 'key'=>'string', 'ad='=>'string'], 'Sodium\crypto_aead_chacha20poly1305_encrypt' => ['string', 'msg'=>'string', 'nonce'=>'string', 'key'=>'string', 'ad='=>'string'], 'Sodium\crypto_auth' => ['string', 'msg'=>'string', 'key'=>'string'], 'Sodium\crypto_auth_verify' => ['bool', 'mac'=>'string', 'msg'=>'string', 'key'=>'string'], 'Sodium\crypto_box' => ['string', 'msg'=>'string', 'nonce'=>'string', 'keypair'=>'string'], 'Sodium\crypto_box_keypair' => ['string'], 'Sodium\crypto_box_keypair_from_secretkey_and_publickey' => ['string', 'secretkey'=>'string', 'publickey'=>'string'], 'Sodium\crypto_box_open' => ['string', 'msg'=>'string', 'nonce'=>'string', 'keypair'=>'string'], 'Sodium\crypto_box_publickey' => ['string', 'keypair'=>'string'], 'Sodium\crypto_box_publickey_from_secretkey' => ['string', 'secretkey'=>'string'], 'Sodium\crypto_box_seal' => ['string', 'message'=>'string', 'publickey'=>'string'], 'Sodium\crypto_box_seal_open' => ['string', 'encrypted'=>'string', 'keypair'=>'string'], 'Sodium\crypto_box_secretkey' => ['string', 'keypair'=>'string'], 'Sodium\crypto_box_seed_keypair' => ['string', 'seed'=>'string'], 'Sodium\crypto_generichash' => ['string', 'input'=>'string', 'key='=>'string', 'length='=>'int'], 'Sodium\crypto_generichash_final' => ['string', 'state'=>'string', 'length='=>'int'], 'Sodium\crypto_generichash_init' => ['string', 'key='=>'string', 'length='=>'int'], 'Sodium\crypto_generichash_update' => ['bool', '&hashState'=>'string', 'append'=>'string'], 'Sodium\crypto_kx' => ['string', 'secretkey'=>'string', 'publickey'=>'string', 'client_publickey'=>'string', 'server_publickey'=>'string'], 'Sodium\crypto_pwhash' => ['string', 'out_len'=>'int', 'passwd'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'Sodium\crypto_pwhash_scryptsalsa208sha256' => ['string', 'out_len'=>'int', 'passwd'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'Sodium\crypto_pwhash_scryptsalsa208sha256_str' => ['string', 'passwd'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'Sodium\crypto_pwhash_scryptsalsa208sha256_str_verify' => ['bool', 'hash'=>'string', 'passwd'=>'string'], 'Sodium\crypto_pwhash_str' => ['string', 'passwd'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'Sodium\crypto_pwhash_str_verify' => ['bool', 'hash'=>'string', 'passwd'=>'string'], 'Sodium\crypto_scalarmult' => ['string', 'ecdhA'=>'string', 'ecdhB'=>'string'], 'Sodium\crypto_scalarmult_base' => ['string', 'sk'=>'string'], 'Sodium\crypto_secretbox' => ['string', 'plaintext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'Sodium\crypto_secretbox_open' => ['string', 'ciphertext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'Sodium\crypto_shorthash' => ['string', 'message'=>'string', 'key'=>'string'], 'Sodium\crypto_sign' => ['string', 'message'=>'string', 'secretkey'=>'string'], 'Sodium\crypto_sign_detached' => ['string', 'message'=>'string', 'secretkey'=>'string'], 'Sodium\crypto_sign_ed25519_pk_to_curve25519' => ['string', 'sign_pk'=>'string'], 'Sodium\crypto_sign_ed25519_sk_to_curve25519' => ['string', 'sign_sk'=>'string'], 'Sodium\crypto_sign_keypair' => ['string'], 'Sodium\crypto_sign_keypair_from_secretkey_and_publickey' => ['string', 'secretkey'=>'string', 'publickey'=>'string'], 'Sodium\crypto_sign_open' => ['string|false', 'signed_message'=>'string', 'publickey'=>'string'], 'Sodium\crypto_sign_publickey' => ['string', 'keypair'=>'string'], 'Sodium\crypto_sign_publickey_from_secretkey' => ['string', 'secretkey'=>'string'], 'Sodium\crypto_sign_secretkey' => ['string', 'keypair'=>'string'], 'Sodium\crypto_sign_seed_keypair' => ['string', 'seed'=>'string'], 'Sodium\crypto_sign_verify_detached' => ['bool', 'signature'=>'string', 'msg'=>'string', 'publickey'=>'string'], 'Sodium\crypto_stream' => ['string', 'length'=>'int', 'nonce'=>'string', 'key'=>'string'], 'Sodium\crypto_stream_xor' => ['string', 'plaintext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'Sodium\hex2bin' => ['string', 'hex'=>'string'], 'Sodium\increment' => ['string', '&nonce'=>'string'], 'Sodium\library_version_major' => ['int'], 'Sodium\library_version_minor' => ['int'], 'Sodium\memcmp' => ['int', 'left'=>'string', 'right'=>'string'], 'Sodium\memzero' => ['void', '&target'=>'string'], 'Sodium\randombytes_buf' => ['string', 'length'=>'int'], 'Sodium\randombytes_random16' => ['int|string'], 'Sodium\randombytes_uniform' => ['int', 'upperBoundNonInclusive'=>'int'], 'Sodium\version_string' => ['string'], 'sodium_add' => ['string', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_base642bin' => ['string', 'base64'=>'string', 'variant'=>'int', 'ignore='=>'string'], 'sodium_bin2base64' => ['string', 'binary'=>'string', 'variant'=>'int'], 'sodium_bin2hex' => ['string', 'binary'=>'string'], 'sodium_compare' => ['int', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_crypto_aead_aes256gcm_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_aes256gcm_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_aes256gcm_is_available' => ['bool'], 'sodium_crypto_aead_aes256gcm_keygen' => ['string'], 'sodium_crypto_aead_chacha20poly1305_decrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => ['array|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_keygen' => ['string'], 'sodium_crypto_aead_chacha20poly1305_keygen' => ['string'], 'sodium_crypto_aead_xchacha20poly1305_ietf_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_xchacha20poly1305_ietf_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_xchacha20poly1305_ietf_keygen' => ['string'], 'sodium_crypto_auth' => ['string', 'message'=>'string', 'key'=>'string'], 'sodium_crypto_auth_keygen' => ['string'], 'sodium_crypto_auth_verify' => ['bool', 'mac'=>'string', 'message'=>'string', 'key'=>'string'], 'sodium_crypto_box' => ['string', 'string'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_box_keypair' => ['string'], 'sodium_crypto_box_keypair_from_secretkey_and_publickey' => ['string', 'secret_key'=>'string', 'public_key'=>'string'], 'sodium_crypto_box_open' => ['string|false', 'message'=>'string', 'nonce'=>'string', 'message_keypair'=>'string'], 'sodium_crypto_box_publickey' => ['string', 'keypair'=>'string'], 'sodium_crypto_box_publickey_from_secretkey' => ['string', 'secretkey'=>'string'], 'sodium_crypto_box_seal' => ['string', 'message'=>'string', 'publickey'=>'string'], 'sodium_crypto_box_seal_open' => ['string|false', 'message'=>'string', 'recipient_keypair'=>'string'], 'sodium_crypto_box_secretkey' => ['string', 'keypair'=>'string'], 'sodium_crypto_box_seed_keypair' => ['string', 'seed'=>'string'], 'sodium_crypto_generichash' => ['string', 'msg'=>'string', 'key='=>'?string', 'length='=>'?int'], 'sodium_crypto_generichash_final' => ['string', 'state'=>'string', 'length='=>'?int'], 'sodium_crypto_generichash_init' => ['string', 'key='=>'?string', 'length='=>'?int'], 'sodium_crypto_generichash_keygen' => ['string'], 'sodium_crypto_generichash_update' => ['bool', 'state'=>'string', 'string'=>'string'], 'sodium_crypto_kdf_derive_from_key' => ['string', 'subkey_len'=>'int', 'subkey_id'=>'int', 'context'=>'string', 'key'=>'string'], 'sodium_crypto_kdf_keygen' => ['string'], 'sodium_crypto_kx' => ['string', 'secretkey'=>'string', 'publickey'=>'string', 'client_publickey'=>'string', 'server_publickey'=>'string'], 'sodium_crypto_kx_client_session_keys' => ['array', 'client_keypair'=>'string', 'server_key'=>'string'], 'sodium_crypto_kx_keypair' => ['string'], 'sodium_crypto_kx_publickey' => ['string', 'keypair'=>'string'], 'sodium_crypto_kx_secretkey' => ['string', 'keypair'=>'string'], 'sodium_crypto_kx_seed_keypair' => ['string', 'seed'=>'string'], 'sodium_crypto_kx_server_session_keys' => ['array', 'server_keypair'=>'string', 'client_key'=>'string'], 'sodium_crypto_pwhash' => ['string', 'length'=>'int', 'password'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int', 'alg='=>'int'], 'sodium_crypto_pwhash_scryptsalsa208sha256' => ['string', 'length'=>'int', 'password'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_scryptsalsa208sha256_str' => ['string', 'password'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_scryptsalsa208sha256_str_verify' => ['bool', 'hash'=>'string', 'password'=>'string'], 'sodium_crypto_pwhash_str' => ['string', 'password'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_str_needs_rehash' => ['bool', 'password'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_str_verify' => ['bool', 'hash'=>'string', 'password'=>'string'], 'sodium_crypto_scalarmult' => ['string', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_crypto_scalarmult_base' => ['string', 'secretkey'=>'string'], 'sodium_crypto_secretbox' => ['string', 'plaintext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_secretbox_keygen' => ['string'], 'sodium_crypto_secretbox_open' => ['string|false', 'ciphertext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_init_pull' => ['string', 'header'=>'string', 'key'=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_init_push' => ['array', 'key'=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_keygen' => ['string'], 'sodium_crypto_secretstream_xchacha20poly1305_pull' => ['array', 'state'=>'string', 'c'=>'string', 'ad='=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_push' => ['string', 'state'=>'string', 'msg'=>'string', 'ad='=>'string', 'tag='=>'int'], 'sodium_crypto_secretstream_xchacha20poly1305_rekey' => ['void', 'state'=>'string'], 'sodium_crypto_shorthash' => ['string', 'message'=>'string', 'key'=>'string'], 'sodium_crypto_shorthash_keygen' => ['string'], 'sodium_crypto_sign' => ['string', 'message'=>'string', 'secretkey'=>'string'], 'sodium_crypto_sign_detached' => ['string', 'message'=>'string', 'secretkey'=>'string'], 'sodium_crypto_sign_ed25519_pk_to_curve25519' => ['string', 'ed25519pk'=>'string'], 'sodium_crypto_sign_ed25519_sk_to_curve25519' => ['string', 'ed25519sk'=>'string'], 'sodium_crypto_sign_keypair' => ['string'], 'sodium_crypto_sign_keypair_from_secretkey_and_publickey' => ['string', 'secret_key'=>'string', 'public_key'=>'string'], 'sodium_crypto_sign_open' => ['string|false', 'message'=>'string', 'publickey'=>'string'], 'sodium_crypto_sign_publickey' => ['string', 'keypair'=>'string'], 'sodium_crypto_sign_publickey_from_secretkey' => ['string', 'secretkey'=>'string'], 'sodium_crypto_sign_secretkey' => ['string', 'keypair'=>'string'], 'sodium_crypto_sign_seed_keypair' => ['string', 'seed'=>'string'], 'sodium_crypto_sign_verify_detached' => ['bool', 'signature'=>'string', 'message'=>'string', 'publickey'=>'string'], 'sodium_crypto_stream' => ['string', 'length'=>'int', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_stream_keygen' => ['string'], 'sodium_crypto_stream_xor' => ['string', 'message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_hex2bin' => ['string', 'hex'=>'string', 'ignore='=>'string'], 'sodium_increment' => ['string', '&binary_string'=>'string'], 'sodium_library_version_major' => ['int'], 'sodium_library_version_minor' => ['int'], 'sodium_memcmp' => ['int', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_memzero' => ['void', '&secret'=>'string'], 'sodium_pad' => ['string', 'unpadded'=>'string', 'length'=>'int'], 'sodium_randombytes_buf' => ['string', 'length'=>'int'], 'sodium_randombytes_random16' => ['int|string'], 'sodium_randombytes_uniform' => ['int', 'upperBoundNonInclusive'=>'int'], 'sodium_unpad' => ['string', 'padded'=>'string', 'length'=>'int'], 'sodium_version_string' => ['string'], 'solid_fetch_prev' => ['bool', 'result_id'=>''], 'solr_get_version' => ['string|false'], 'SolrClient::__construct' => ['void', 'clientOptions'=>'array'], 'SolrClient::__destruct' => ['void'], 'SolrClient::addDocument' => ['SolrUpdateResponse', 'doc'=>'SolrInputDocument', 'allowdups='=>'bool', 'commitwithin='=>'int'], 'SolrClient::addDocuments' => ['SolrUpdateResponse', 'docs'=>'array', 'allowdups='=>'bool', 'commitwithin='=>'int'], 'SolrClient::commit' => ['SolrUpdateResponse', 'maxsegments='=>'int', 'waitflush='=>'bool', 'waitsearcher='=>'bool'], 'SolrClient::deleteById' => ['SolrUpdateResponse', 'id'=>'string'], 'SolrClient::deleteByIds' => ['SolrUpdateResponse', 'ids'=>'array'], 'SolrClient::deleteByQueries' => ['SolrUpdateResponse', 'queries'=>'array'], 'SolrClient::deleteByQuery' => ['SolrUpdateResponse', 'query'=>'string'], 'SolrClient::getById' => ['SolrQueryResponse', 'id'=>'string'], 'SolrClient::getByIds' => ['SolrQueryResponse', 'ids'=>'array'], 'SolrClient::getDebug' => ['string'], 'SolrClient::getOptions' => ['array'], 'SolrClient::optimize' => ['SolrUpdateResponse', 'maxsegments='=>'int', 'waitflush='=>'bool', 'waitsearcher='=>'bool'], 'SolrClient::ping' => ['SolrPingResponse'], 'SolrClient::query' => ['SolrQueryResponse', 'query'=>'SolrParams'], 'SolrClient::request' => ['SolrUpdateResponse', 'raw_request'=>'string'], 'SolrClient::rollback' => ['SolrUpdateResponse'], 'SolrClient::setResponseWriter' => ['void', 'responsewriter'=>'string'], 'SolrClient::setServlet' => ['bool', 'type'=>'int', 'value'=>'string'], 'SolrClient::system' => ['SolrGenericResponse'], 'SolrClient::threads' => ['SolrGenericResponse'], 'SolrClientException::__clone' => ['void'], 'SolrClientException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'SolrClientException::__toString' => ['string'], 'SolrClientException::__wakeup' => ['void'], 'SolrClientException::getCode' => ['int'], 'SolrClientException::getFile' => ['string'], 'SolrClientException::getInternalInfo' => ['array'], 'SolrClientException::getLine' => ['int'], 'SolrClientException::getMessage' => ['string'], 'SolrClientException::getPrevious' => ['?Exception|?Throwable'], 'SolrClientException::getTrace' => ['list>'], 'SolrClientException::getTraceAsString' => ['string'], 'SolrCollapseFunction::__construct' => ['void', 'field'=>'string'], 'SolrCollapseFunction::__toString' => ['string'], 'SolrCollapseFunction::getField' => ['string'], 'SolrCollapseFunction::getHint' => ['string'], 'SolrCollapseFunction::getMax' => ['string'], 'SolrCollapseFunction::getMin' => ['string'], 'SolrCollapseFunction::getNullPolicy' => ['string'], 'SolrCollapseFunction::getSize' => ['int'], 'SolrCollapseFunction::setField' => ['SolrCollapseFunction', 'fieldName'=>'string'], 'SolrCollapseFunction::setHint' => ['SolrCollapseFunction', 'hint'=>'string'], 'SolrCollapseFunction::setMax' => ['SolrCollapseFunction', 'max'=>'string'], 'SolrCollapseFunction::setMin' => ['SolrCollapseFunction', 'min'=>'string'], 'SolrCollapseFunction::setNullPolicy' => ['SolrCollapseFunction', 'nullPolicy'=>'string'], 'SolrCollapseFunction::setSize' => ['SolrCollapseFunction', 'size'=>'int'], 'SolrDisMaxQuery::__construct' => ['void', 'q='=>'string'], 'SolrDisMaxQuery::__destruct' => ['void'], 'SolrDisMaxQuery::add' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrDisMaxQuery::addBigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost'=>'string', 'slop='=>'string'], 'SolrDisMaxQuery::addBoostQuery' => ['SolrDisMaxQuery', 'field'=>'string', 'value'=>'string', 'boost='=>'string'], 'SolrDisMaxQuery::addExpandFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrDisMaxQuery::addExpandSortField' => ['SolrQuery', 'field'=>'string', 'order'=>'string'], 'SolrDisMaxQuery::addFacetDateField' => ['SolrQuery', 'dateField'=>'string'], 'SolrDisMaxQuery::addFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::addFacetField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addFacetQuery' => ['SolrQuery', 'facetQuery'=>'string'], 'SolrDisMaxQuery::addField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrDisMaxQuery::addGroupField' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::addGroupFunction' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::addGroupQuery' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::addGroupSortField' => ['SolrQuery', 'field'=>'string', 'order'=>'int'], 'SolrDisMaxQuery::addHighlightField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addMltField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addMltQueryField' => ['SolrQuery', 'field'=>'string', 'boost'=>'float'], 'SolrDisMaxQuery::addParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrDisMaxQuery::addPhraseField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost'=>'string', 'slop='=>'string'], 'SolrDisMaxQuery::addQueryField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost='=>'string'], 'SolrDisMaxQuery::addSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'int'], 'SolrDisMaxQuery::addStatsFacet' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addStatsField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addTrigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost'=>'string', 'slop='=>'string'], 'SolrDisMaxQuery::addUserField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::collapse' => ['SolrQuery', 'collapseFunction'=>'SolrCollapseFunction'], 'SolrDisMaxQuery::get' => ['mixed', 'param_name'=>'string'], 'SolrDisMaxQuery::getExpand' => ['bool'], 'SolrDisMaxQuery::getExpandFilterQueries' => ['array'], 'SolrDisMaxQuery::getExpandQuery' => ['array'], 'SolrDisMaxQuery::getExpandRows' => ['int'], 'SolrDisMaxQuery::getExpandSortFields' => ['array'], 'SolrDisMaxQuery::getFacet' => ['bool'], 'SolrDisMaxQuery::getFacetDateEnd' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetDateFields' => ['array'], 'SolrDisMaxQuery::getFacetDateGap' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetDateHardEnd' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetDateOther' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetDateStart' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetFields' => ['array'], 'SolrDisMaxQuery::getFacetLimit' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetMethod' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetMinCount' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetMissing' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetOffset' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetPrefix' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetQueries' => ['string'], 'SolrDisMaxQuery::getFacetSort' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getFields' => ['string'], 'SolrDisMaxQuery::getFilterQueries' => ['string'], 'SolrDisMaxQuery::getGroup' => ['bool'], 'SolrDisMaxQuery::getGroupCachePercent' => ['int'], 'SolrDisMaxQuery::getGroupFacet' => ['bool'], 'SolrDisMaxQuery::getGroupFields' => ['array'], 'SolrDisMaxQuery::getGroupFormat' => ['string'], 'SolrDisMaxQuery::getGroupFunctions' => ['array'], 'SolrDisMaxQuery::getGroupLimit' => ['int'], 'SolrDisMaxQuery::getGroupMain' => ['bool'], 'SolrDisMaxQuery::getGroupNGroups' => ['bool'], 'SolrDisMaxQuery::getGroupOffset' => ['bool'], 'SolrDisMaxQuery::getGroupQueries' => ['array'], 'SolrDisMaxQuery::getGroupSortFields' => ['array'], 'SolrDisMaxQuery::getGroupTruncate' => ['bool'], 'SolrDisMaxQuery::getHighlight' => ['bool'], 'SolrDisMaxQuery::getHighlightAlternateField' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightFields' => ['array'], 'SolrDisMaxQuery::getHighlightFormatter' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightFragmenter' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightFragsize' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightHighlightMultiTerm' => ['bool'], 'SolrDisMaxQuery::getHighlightMaxAlternateFieldLength' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightMaxAnalyzedChars' => ['int'], 'SolrDisMaxQuery::getHighlightMergeContiguous' => ['bool', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightRegexMaxAnalyzedChars' => ['int'], 'SolrDisMaxQuery::getHighlightRegexPattern' => ['string'], 'SolrDisMaxQuery::getHighlightRegexSlop' => ['float'], 'SolrDisMaxQuery::getHighlightRequireFieldMatch' => ['bool'], 'SolrDisMaxQuery::getHighlightSimplePost' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightSimplePre' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightSnippets' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightUsePhraseHighlighter' => ['bool'], 'SolrDisMaxQuery::getMlt' => ['bool'], 'SolrDisMaxQuery::getMltBoost' => ['bool'], 'SolrDisMaxQuery::getMltCount' => ['int'], 'SolrDisMaxQuery::getMltFields' => ['array'], 'SolrDisMaxQuery::getMltMaxNumQueryTerms' => ['int'], 'SolrDisMaxQuery::getMltMaxNumTokens' => ['int'], 'SolrDisMaxQuery::getMltMaxWordLength' => ['int'], 'SolrDisMaxQuery::getMltMinDocFrequency' => ['int'], 'SolrDisMaxQuery::getMltMinTermFrequency' => ['int'], 'SolrDisMaxQuery::getMltMinWordLength' => ['int'], 'SolrDisMaxQuery::getMltQueryFields' => ['array'], 'SolrDisMaxQuery::getParam' => ['mixed', 'param_name'=>'string'], 'SolrDisMaxQuery::getParams' => ['array'], 'SolrDisMaxQuery::getPreparedParams' => ['array'], 'SolrDisMaxQuery::getQuery' => ['string'], 'SolrDisMaxQuery::getRows' => ['int'], 'SolrDisMaxQuery::getSortFields' => ['array'], 'SolrDisMaxQuery::getStart' => ['int'], 'SolrDisMaxQuery::getStats' => ['bool'], 'SolrDisMaxQuery::getStatsFacets' => ['array'], 'SolrDisMaxQuery::getStatsFields' => ['array'], 'SolrDisMaxQuery::getTerms' => ['bool'], 'SolrDisMaxQuery::getTermsField' => ['string'], 'SolrDisMaxQuery::getTermsIncludeLowerBound' => ['bool'], 'SolrDisMaxQuery::getTermsIncludeUpperBound' => ['bool'], 'SolrDisMaxQuery::getTermsLimit' => ['int'], 'SolrDisMaxQuery::getTermsLowerBound' => ['string'], 'SolrDisMaxQuery::getTermsMaxCount' => ['int'], 'SolrDisMaxQuery::getTermsMinCount' => ['int'], 'SolrDisMaxQuery::getTermsPrefix' => ['string'], 'SolrDisMaxQuery::getTermsReturnRaw' => ['bool'], 'SolrDisMaxQuery::getTermsSort' => ['int'], 'SolrDisMaxQuery::getTermsUpperBound' => ['string'], 'SolrDisMaxQuery::getTimeAllowed' => ['int'], 'SolrDisMaxQuery::removeBigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeBoostQuery' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeExpandFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrDisMaxQuery::removeExpandSortField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeFacetDateField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::removeFacetField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeFacetQuery' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::removeField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrDisMaxQuery::removeHighlightField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeMltField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeMltQueryField' => ['SolrQuery', 'queryField'=>'string'], 'SolrDisMaxQuery::removePhraseField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeQueryField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeSortField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeStatsFacet' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::removeStatsField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeTrigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeUserField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::serialize' => ['string'], 'SolrDisMaxQuery::set' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrDisMaxQuery::setBigramPhraseFields' => ['SolrDisMaxQuery', 'fields'=>'string'], 'SolrDisMaxQuery::setBigramPhraseSlop' => ['SolrDisMaxQuery', 'slop'=>'string'], 'SolrDisMaxQuery::setBoostFunction' => ['SolrDisMaxQuery', 'function'=>'string'], 'SolrDisMaxQuery::setBoostQuery' => ['SolrDisMaxQuery', 'q'=>'string'], 'SolrDisMaxQuery::setEchoHandler' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setEchoParams' => ['SolrQuery', 'type'=>'string'], 'SolrDisMaxQuery::setExpand' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setExpandQuery' => ['SolrQuery', 'q'=>'string'], 'SolrDisMaxQuery::setExpandRows' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setExplainOther' => ['SolrQuery', 'query'=>'string'], 'SolrDisMaxQuery::setFacet' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setFacetDateEnd' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetDateGap' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetDateHardEnd' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetDateStart' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetEnumCacheMinDefaultFrequency' => ['SolrQuery', 'frequency'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetLimit' => ['SolrQuery', 'limit'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetMethod' => ['SolrQuery', 'method'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetMinCount' => ['SolrQuery', 'mincount'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetMissing' => ['SolrQuery', 'flag'=>'bool', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetOffset' => ['SolrQuery', 'offset'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetPrefix' => ['SolrQuery', 'prefix'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetSort' => ['SolrQuery', 'facetSort'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setGroup' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setGroupCachePercent' => ['SolrQuery', 'percent'=>'int'], 'SolrDisMaxQuery::setGroupFacet' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setGroupFormat' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::setGroupLimit' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setGroupMain' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::setGroupNGroups' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setGroupOffset' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setGroupTruncate' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setHighlight' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setHighlightAlternateField' => ['SolrQuery', 'field'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightFormatter' => ['SolrQuery', 'formatter'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightFragmenter' => ['SolrQuery', 'fragmenter'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightFragsize' => ['SolrQuery', 'size'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightHighlightMultiTerm' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setHighlightMaxAlternateFieldLength' => ['SolrQuery', 'fieldLength'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightMaxAnalyzedChars' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setHighlightMergeContiguous' => ['SolrQuery', 'flag'=>'bool', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightRegexMaxAnalyzedChars' => ['SolrQuery', 'maxAnalyzedChars'=>'int'], 'SolrDisMaxQuery::setHighlightRegexPattern' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::setHighlightRegexSlop' => ['SolrQuery', 'factor'=>'float'], 'SolrDisMaxQuery::setHighlightRequireFieldMatch' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setHighlightSimplePost' => ['SolrQuery', 'simplePost'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightSimplePre' => ['SolrQuery', 'simplePre'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightSnippets' => ['SolrQuery', 'value'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightUsePhraseHighlighter' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setMinimumMatch' => ['SolrDisMaxQuery', 'value'=>'string'], 'SolrDisMaxQuery::setMlt' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setMltBoost' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setMltCount' => ['SolrQuery', 'count'=>'int'], 'SolrDisMaxQuery::setMltMaxNumQueryTerms' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setMltMaxNumTokens' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setMltMaxWordLength' => ['SolrQuery', 'maxWordLength'=>'int'], 'SolrDisMaxQuery::setMltMinDocFrequency' => ['SolrQuery', 'minDocFrequency'=>'int'], 'SolrDisMaxQuery::setMltMinTermFrequency' => ['SolrQuery', 'minTermFrequency'=>'int'], 'SolrDisMaxQuery::setMltMinWordLength' => ['SolrQuery', 'minWordLength'=>'int'], 'SolrDisMaxQuery::setOmitHeader' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setParam' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrDisMaxQuery::setPhraseFields' => ['SolrDisMaxQuery', 'fields'=>'string'], 'SolrDisMaxQuery::setPhraseSlop' => ['SolrDisMaxQuery', 'slop'=>'string'], 'SolrDisMaxQuery::setQuery' => ['SolrQuery', 'query'=>'string'], 'SolrDisMaxQuery::setQueryAlt' => ['SolrDisMaxQuery', 'q'=>'string'], 'SolrDisMaxQuery::setQueryPhraseSlop' => ['SolrDisMaxQuery', 'slop'=>'string'], 'SolrDisMaxQuery::setRows' => ['SolrQuery', 'rows'=>'int'], 'SolrDisMaxQuery::setShowDebugInfo' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setStart' => ['SolrQuery', 'start'=>'int'], 'SolrDisMaxQuery::setStats' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTerms' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTermsField' => ['SolrQuery', 'fieldname'=>'string'], 'SolrDisMaxQuery::setTermsIncludeLowerBound' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTermsIncludeUpperBound' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTermsLimit' => ['SolrQuery', 'limit'=>'int'], 'SolrDisMaxQuery::setTermsLowerBound' => ['SolrQuery', 'lowerBound'=>'string'], 'SolrDisMaxQuery::setTermsMaxCount' => ['SolrQuery', 'frequency'=>'int'], 'SolrDisMaxQuery::setTermsMinCount' => ['SolrQuery', 'frequency'=>'int'], 'SolrDisMaxQuery::setTermsPrefix' => ['SolrQuery', 'prefix'=>'string'], 'SolrDisMaxQuery::setTermsReturnRaw' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTermsSort' => ['SolrQuery', 'sortType'=>'int'], 'SolrDisMaxQuery::setTermsUpperBound' => ['SolrQuery', 'upperBound'=>'string'], 'SolrDisMaxQuery::setTieBreaker' => ['SolrDisMaxQuery', 'tieBreaker'=>'string'], 'SolrDisMaxQuery::setTimeAllowed' => ['SolrQuery', 'timeAllowed'=>'int'], 'SolrDisMaxQuery::setTrigramPhraseFields' => ['SolrDisMaxQuery', 'fields'=>'string'], 'SolrDisMaxQuery::setTrigramPhraseSlop' => ['SolrDisMaxQuery', 'slop'=>'string'], 'SolrDisMaxQuery::setUserFields' => ['SolrDisMaxQuery', 'fields'=>'string'], 'SolrDisMaxQuery::toString' => ['string', 'url_encode='=>'bool'], 'SolrDisMaxQuery::unserialize' => ['void', 'serialized'=>'string'], 'SolrDisMaxQuery::useDisMaxQueryParser' => ['SolrDisMaxQuery'], 'SolrDisMaxQuery::useEDisMaxQueryParser' => ['SolrDisMaxQuery'], 'SolrDocument::__clone' => ['void'], 'SolrDocument::__construct' => ['void'], 'SolrDocument::__destruct' => ['void'], 'SolrDocument::__get' => ['SolrDocumentField', 'fieldname'=>'string'], 'SolrDocument::__isset' => ['bool', 'fieldname'=>'string'], 'SolrDocument::__set' => ['bool', 'fieldname'=>'string', 'fieldvalue'=>'string'], 'SolrDocument::__unset' => ['bool', 'fieldname'=>'string'], 'SolrDocument::addField' => ['bool', 'fieldname'=>'string', 'fieldvalue'=>'string'], 'SolrDocument::clear' => ['bool'], 'SolrDocument::current' => ['SolrDocumentField'], 'SolrDocument::deleteField' => ['bool', 'fieldname'=>'string'], 'SolrDocument::fieldExists' => ['bool', 'fieldname'=>'string'], 'SolrDocument::getChildDocuments' => ['SolrInputDocument[]'], 'SolrDocument::getChildDocumentsCount' => ['int'], 'SolrDocument::getField' => ['SolrDocumentField|false', 'fieldname'=>'string'], 'SolrDocument::getFieldCount' => ['int|false'], 'SolrDocument::getFieldNames' => ['array|false'], 'SolrDocument::getInputDocument' => ['SolrInputDocument'], 'SolrDocument::hasChildDocuments' => ['bool'], 'SolrDocument::key' => ['string'], 'SolrDocument::merge' => ['bool', 'sourcedoc'=>'solrdocument', 'overwrite='=>'bool'], 'SolrDocument::next' => ['void'], 'SolrDocument::offsetExists' => ['bool', 'fieldname'=>'string'], 'SolrDocument::offsetGet' => ['SolrDocumentField', 'fieldname'=>'string'], 'SolrDocument::offsetSet' => ['void', 'fieldname'=>'string', 'fieldvalue'=>'string'], 'SolrDocument::offsetUnset' => ['void', 'fieldname'=>'string'], 'SolrDocument::reset' => ['bool'], 'SolrDocument::rewind' => ['void'], 'SolrDocument::serialize' => ['string'], 'SolrDocument::sort' => ['bool', 'sortorderby'=>'int', 'sortdirection='=>'int'], 'SolrDocument::toArray' => ['array'], 'SolrDocument::unserialize' => ['void', 'serialized'=>'string'], 'SolrDocument::valid' => ['bool'], 'SolrDocumentField::__construct' => ['void'], 'SolrDocumentField::__destruct' => ['void'], 'SolrException::__clone' => ['void'], 'SolrException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'SolrException::__toString' => ['string'], 'SolrException::__wakeup' => ['void'], 'SolrException::getCode' => ['int'], 'SolrException::getFile' => ['string'], 'SolrException::getInternalInfo' => ['array'], 'SolrException::getLine' => ['int'], 'SolrException::getMessage' => ['string'], 'SolrException::getPrevious' => ['Exception|Throwable'], 'SolrException::getTrace' => ['list>'], 'SolrException::getTraceAsString' => ['string'], 'SolrGenericResponse::__construct' => ['void'], 'SolrGenericResponse::__destruct' => ['void'], 'SolrGenericResponse::getDigestedResponse' => ['string'], 'SolrGenericResponse::getHttpStatus' => ['int'], 'SolrGenericResponse::getHttpStatusMessage' => ['string'], 'SolrGenericResponse::getRawRequest' => ['string'], 'SolrGenericResponse::getRawRequestHeaders' => ['string'], 'SolrGenericResponse::getRawResponse' => ['string'], 'SolrGenericResponse::getRawResponseHeaders' => ['string'], 'SolrGenericResponse::getRequestUrl' => ['string'], 'SolrGenericResponse::getResponse' => ['SolrObject'], 'SolrGenericResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrGenericResponse::success' => ['bool'], 'SolrIllegalArgumentException::__clone' => ['void'], 'SolrIllegalArgumentException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'SolrIllegalArgumentException::__toString' => ['string'], 'SolrIllegalArgumentException::__wakeup' => ['void'], 'SolrIllegalArgumentException::getCode' => ['int'], 'SolrIllegalArgumentException::getFile' => ['string'], 'SolrIllegalArgumentException::getInternalInfo' => ['array'], 'SolrIllegalArgumentException::getLine' => ['int'], 'SolrIllegalArgumentException::getMessage' => ['string'], 'SolrIllegalArgumentException::getPrevious' => ['Exception|Throwable'], 'SolrIllegalArgumentException::getTrace' => ['list>'], 'SolrIllegalArgumentException::getTraceAsString' => ['string'], 'SolrIllegalOperationException::__clone' => ['void'], 'SolrIllegalOperationException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'SolrIllegalOperationException::__toString' => ['string'], 'SolrIllegalOperationException::__wakeup' => ['void'], 'SolrIllegalOperationException::getCode' => ['int'], 'SolrIllegalOperationException::getFile' => ['string'], 'SolrIllegalOperationException::getInternalInfo' => ['array'], 'SolrIllegalOperationException::getLine' => ['int'], 'SolrIllegalOperationException::getMessage' => ['string'], 'SolrIllegalOperationException::getPrevious' => ['Exception|Throwable'], 'SolrIllegalOperationException::getTrace' => ['list>'], 'SolrIllegalOperationException::getTraceAsString' => ['string'], 'SolrInputDocument::__clone' => ['void'], 'SolrInputDocument::__construct' => ['void'], 'SolrInputDocument::__destruct' => ['void'], 'SolrInputDocument::addChildDocument' => ['void', 'child'=>'SolrInputDocument'], 'SolrInputDocument::addChildDocuments' => ['void', 'docs'=>'array'], 'SolrInputDocument::addField' => ['bool', 'fieldname'=>'string', 'fieldvalue'=>'string', 'fieldboostvalue='=>'float'], 'SolrInputDocument::clear' => ['bool'], 'SolrInputDocument::deleteField' => ['bool', 'fieldname'=>'string'], 'SolrInputDocument::fieldExists' => ['bool', 'fieldname'=>'string'], 'SolrInputDocument::getBoost' => ['float|false'], 'SolrInputDocument::getChildDocuments' => ['SolrInputDocument[]'], 'SolrInputDocument::getChildDocumentsCount' => ['int'], 'SolrInputDocument::getField' => ['SolrDocumentField|false', 'fieldname'=>'string'], 'SolrInputDocument::getFieldBoost' => ['float|false', 'fieldname'=>'string'], 'SolrInputDocument::getFieldCount' => ['int|false'], 'SolrInputDocument::getFieldNames' => ['array|false'], 'SolrInputDocument::hasChildDocuments' => ['bool'], 'SolrInputDocument::merge' => ['bool', 'sourcedoc'=>'SolrInputDocument', 'overwrite='=>'bool'], 'SolrInputDocument::reset' => ['bool'], 'SolrInputDocument::setBoost' => ['bool', 'documentboostvalue'=>'float'], 'SolrInputDocument::setFieldBoost' => ['bool', 'fieldname'=>'string', 'fieldboostvalue'=>'float'], 'SolrInputDocument::sort' => ['bool', 'sortorderby'=>'int', 'sortdirection='=>'int'], 'SolrInputDocument::toArray' => ['array|false'], 'SolrModifiableParams::__construct' => ['void'], 'SolrModifiableParams::__destruct' => ['void'], 'SolrModifiableParams::add' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrModifiableParams::addParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrModifiableParams::get' => ['mixed', 'param_name'=>'string'], 'SolrModifiableParams::getParam' => ['mixed', 'param_name'=>'string'], 'SolrModifiableParams::getParams' => ['array'], 'SolrModifiableParams::getPreparedParams' => ['array'], 'SolrModifiableParams::serialize' => ['string'], 'SolrModifiableParams::set' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrModifiableParams::setParam' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrModifiableParams::toString' => ['string', 'url_encode='=>'bool'], 'SolrModifiableParams::unserialize' => ['void', 'serialized'=>'string'], 'SolrObject::__construct' => ['void'], 'SolrObject::__destruct' => ['void'], 'SolrObject::getPropertyNames' => ['array'], 'SolrObject::offsetExists' => ['bool', 'property_name'=>'string'], 'SolrObject::offsetGet' => ['SolrDocumentField', 'property_name'=>'string'], 'SolrObject::offsetSet' => ['void', 'property_name'=>'string', 'property_value'=>'string'], 'SolrObject::offsetUnset' => ['void', 'property_name'=>'string'], 'SolrParams::__construct' => ['void'], 'SolrParams::add' => ['SolrParams|false', 'name'=>'string', 'value'=>'string'], 'SolrParams::addParam' => ['SolrParams|false', 'name'=>'string', 'value'=>'string'], 'SolrParams::get' => ['mixed', 'param_name'=>'string'], 'SolrParams::getParam' => ['mixed', 'param_name='=>'string'], 'SolrParams::getParams' => ['array'], 'SolrParams::getPreparedParams' => ['array'], 'SolrParams::serialize' => ['string'], 'SolrParams::set' => ['SolrParams|false', 'name'=>'string', 'value'=>'string'], 'SolrParams::setParam' => ['SolrParams|false', 'name'=>'string', 'value'=>'string'], 'SolrParams::toString' => ['string|false', 'url_encode='=>'bool'], 'SolrParams::unserialize' => ['void', 'serialized'=>'string'], 'SolrPingResponse::__construct' => ['void'], 'SolrPingResponse::__destruct' => ['void'], 'SolrPingResponse::getDigestedResponse' => ['string'], 'SolrPingResponse::getHttpStatus' => ['int'], 'SolrPingResponse::getHttpStatusMessage' => ['string'], 'SolrPingResponse::getRawRequest' => ['string'], 'SolrPingResponse::getRawRequestHeaders' => ['string'], 'SolrPingResponse::getRawResponse' => ['string'], 'SolrPingResponse::getRawResponseHeaders' => ['string'], 'SolrPingResponse::getRequestUrl' => ['string'], 'SolrPingResponse::getResponse' => ['string'], 'SolrPingResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrPingResponse::success' => ['bool'], 'SolrQuery::__construct' => ['void', 'q='=>'string'], 'SolrQuery::__destruct' => ['void'], 'SolrQuery::add' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrQuery::addExpandFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrQuery::addExpandSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'string'], 'SolrQuery::addFacetDateField' => ['SolrQuery', 'datefield'=>'string'], 'SolrQuery::addFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::addFacetField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addFacetQuery' => ['SolrQuery', 'facetquery'=>'string'], 'SolrQuery::addField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrQuery::addGroupField' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::addGroupFunction' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::addGroupQuery' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::addGroupSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'int'], 'SolrQuery::addHighlightField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addMltField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addMltQueryField' => ['SolrQuery', 'field'=>'string', 'boost'=>'float'], 'SolrQuery::addParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrQuery::addSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'int'], 'SolrQuery::addStatsFacet' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addStatsField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::collapse' => ['SolrQuery', 'collapseFunction'=>'SolrCollapseFunction'], 'SolrQuery::get' => ['mixed', 'param_name'=>'string'], 'SolrQuery::getExpand' => ['bool'], 'SolrQuery::getExpandFilterQueries' => ['array'], 'SolrQuery::getExpandQuery' => ['array'], 'SolrQuery::getExpandRows' => ['int'], 'SolrQuery::getExpandSortFields' => ['array'], 'SolrQuery::getFacet' => ['?bool'], 'SolrQuery::getFacetDateEnd' => ['?string', 'field_override='=>'string'], 'SolrQuery::getFacetDateFields' => ['array'], 'SolrQuery::getFacetDateGap' => ['?string', 'field_override='=>'string'], 'SolrQuery::getFacetDateHardEnd' => ['?string', 'field_override='=>'string'], 'SolrQuery::getFacetDateOther' => ['?string', 'field_override='=>'string'], 'SolrQuery::getFacetDateStart' => ['?string', 'field_override='=>'string'], 'SolrQuery::getFacetFields' => ['array'], 'SolrQuery::getFacetLimit' => ['?int', 'field_override='=>'string'], 'SolrQuery::getFacetMethod' => ['?string', 'field_override='=>'string'], 'SolrQuery::getFacetMinCount' => ['?int', 'field_override='=>'string'], 'SolrQuery::getFacetMissing' => ['?bool', 'field_override='=>'string'], 'SolrQuery::getFacetOffset' => ['?int', 'field_override='=>'string'], 'SolrQuery::getFacetPrefix' => ['?string', 'field_override='=>'string'], 'SolrQuery::getFacetQueries' => ['?array'], 'SolrQuery::getFacetSort' => ['int', 'field_override='=>'string'], 'SolrQuery::getFields' => ['?array'], 'SolrQuery::getFilterQueries' => ['?array'], 'SolrQuery::getGroup' => ['bool'], 'SolrQuery::getGroupCachePercent' => ['int'], 'SolrQuery::getGroupFacet' => ['bool'], 'SolrQuery::getGroupFields' => ['array'], 'SolrQuery::getGroupFormat' => ['string'], 'SolrQuery::getGroupFunctions' => ['array'], 'SolrQuery::getGroupLimit' => ['int'], 'SolrQuery::getGroupMain' => ['bool'], 'SolrQuery::getGroupNGroups' => ['bool'], 'SolrQuery::getGroupOffset' => ['int'], 'SolrQuery::getGroupQueries' => ['array'], 'SolrQuery::getGroupSortFields' => ['array'], 'SolrQuery::getGroupTruncate' => ['bool'], 'SolrQuery::getHighlight' => ['bool'], 'SolrQuery::getHighlightAlternateField' => ['?string', 'field_override='=>'string'], 'SolrQuery::getHighlightFields' => ['?array'], 'SolrQuery::getHighlightFormatter' => ['?string', 'field_override='=>'string'], 'SolrQuery::getHighlightFragmenter' => ['?string', 'field_override='=>'string'], 'SolrQuery::getHighlightFragsize' => ['?int', 'field_override='=>'string'], 'SolrQuery::getHighlightHighlightMultiTerm' => ['?bool'], 'SolrQuery::getHighlightMaxAlternateFieldLength' => ['?int', 'field_override='=>'string'], 'SolrQuery::getHighlightMaxAnalyzedChars' => ['?int'], 'SolrQuery::getHighlightMergeContiguous' => ['?bool', 'field_override='=>'string'], 'SolrQuery::getHighlightRegexMaxAnalyzedChars' => ['?int'], 'SolrQuery::getHighlightRegexPattern' => ['?string'], 'SolrQuery::getHighlightRegexSlop' => ['?float'], 'SolrQuery::getHighlightRequireFieldMatch' => ['?bool'], 'SolrQuery::getHighlightSimplePost' => ['?string', 'field_override='=>'string'], 'SolrQuery::getHighlightSimplePre' => ['?string', 'field_override='=>'string'], 'SolrQuery::getHighlightSnippets' => ['?int', 'field_override='=>'string'], 'SolrQuery::getHighlightUsePhraseHighlighter' => ['?bool'], 'SolrQuery::getMlt' => ['?bool'], 'SolrQuery::getMltBoost' => ['?bool'], 'SolrQuery::getMltCount' => ['?int'], 'SolrQuery::getMltFields' => ['?array'], 'SolrQuery::getMltMaxNumQueryTerms' => ['?int'], 'SolrQuery::getMltMaxNumTokens' => ['?int'], 'SolrQuery::getMltMaxWordLength' => ['?int'], 'SolrQuery::getMltMinDocFrequency' => ['?int'], 'SolrQuery::getMltMinTermFrequency' => ['?int'], 'SolrQuery::getMltMinWordLength' => ['?int'], 'SolrQuery::getMltQueryFields' => ['?array'], 'SolrQuery::getParam' => ['?mixed', 'param_name'=>'string'], 'SolrQuery::getParams' => ['?array'], 'SolrQuery::getPreparedParams' => ['?array'], 'SolrQuery::getQuery' => ['?string'], 'SolrQuery::getRows' => ['?int'], 'SolrQuery::getSortFields' => ['?array'], 'SolrQuery::getStart' => ['?int'], 'SolrQuery::getStats' => ['?bool'], 'SolrQuery::getStatsFacets' => ['?array'], 'SolrQuery::getStatsFields' => ['?array'], 'SolrQuery::getTerms' => ['?bool'], 'SolrQuery::getTermsField' => ['?string'], 'SolrQuery::getTermsIncludeLowerBound' => ['?bool'], 'SolrQuery::getTermsIncludeUpperBound' => ['?bool'], 'SolrQuery::getTermsLimit' => ['?int'], 'SolrQuery::getTermsLowerBound' => ['?string'], 'SolrQuery::getTermsMaxCount' => ['?int'], 'SolrQuery::getTermsMinCount' => ['?int'], 'SolrQuery::getTermsPrefix' => ['?string'], 'SolrQuery::getTermsReturnRaw' => ['?bool'], 'SolrQuery::getTermsSort' => ['?int'], 'SolrQuery::getTermsUpperBound' => ['?string'], 'SolrQuery::getTimeAllowed' => ['?int'], 'SolrQuery::removeExpandFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrQuery::removeExpandSortField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeFacetDateField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::removeFacetField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeFacetQuery' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::removeField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrQuery::removeHighlightField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeMltField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeMltQueryField' => ['SolrQuery', 'queryfield'=>'string'], 'SolrQuery::removeSortField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeStatsFacet' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::removeStatsField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::serialize' => ['string'], 'SolrQuery::set' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrQuery::setEchoHandler' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setEchoParams' => ['SolrQuery', 'type'=>'string'], 'SolrQuery::setExpand' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setExpandQuery' => ['SolrQuery', 'q'=>'string'], 'SolrQuery::setExpandRows' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setExplainOther' => ['SolrQuery', 'query'=>'string'], 'SolrQuery::setFacet' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setFacetDateEnd' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetDateGap' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetDateHardEnd' => ['SolrQuery', 'value'=>'bool', 'field_override='=>'string'], 'SolrQuery::setFacetDateStart' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetEnumCacheMinDefaultFrequency' => ['SolrQuery', 'frequency'=>'int', 'field_override='=>'string'], 'SolrQuery::setFacetLimit' => ['SolrQuery', 'limit'=>'int', 'field_override='=>'string'], 'SolrQuery::setFacetMethod' => ['SolrQuery', 'method'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetMinCount' => ['SolrQuery', 'mincount'=>'int', 'field_override='=>'string'], 'SolrQuery::setFacetMissing' => ['SolrQuery', 'flag'=>'bool', 'field_override='=>'string'], 'SolrQuery::setFacetOffset' => ['SolrQuery', 'offset'=>'int', 'field_override='=>'string'], 'SolrQuery::setFacetPrefix' => ['SolrQuery', 'prefix'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetSort' => ['SolrQuery', 'facetsort'=>'int', 'field_override='=>'string'], 'SolrQuery::setGroup' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setGroupCachePercent' => ['SolrQuery', 'percent'=>'int'], 'SolrQuery::setGroupFacet' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setGroupFormat' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::setGroupLimit' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setGroupMain' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::setGroupNGroups' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setGroupOffset' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setGroupTruncate' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setHighlight' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setHighlightAlternateField' => ['SolrQuery', 'field'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightFormatter' => ['SolrQuery', 'formatter'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightFragmenter' => ['SolrQuery', 'fragmenter'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightFragsize' => ['SolrQuery', 'size'=>'int', 'field_override='=>'string'], 'SolrQuery::setHighlightHighlightMultiTerm' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setHighlightMaxAlternateFieldLength' => ['SolrQuery', 'fieldlength'=>'int', 'field_override='=>'string'], 'SolrQuery::setHighlightMaxAnalyzedChars' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setHighlightMergeContiguous' => ['SolrQuery', 'flag'=>'bool', 'field_override='=>'string'], 'SolrQuery::setHighlightRegexMaxAnalyzedChars' => ['SolrQuery', 'maxanalyzedchars'=>'int'], 'SolrQuery::setHighlightRegexPattern' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::setHighlightRegexSlop' => ['SolrQuery', 'factor'=>'float'], 'SolrQuery::setHighlightRequireFieldMatch' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setHighlightSimplePost' => ['SolrQuery', 'simplepost'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightSimplePre' => ['SolrQuery', 'simplepre'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightSnippets' => ['SolrQuery', 'value'=>'int', 'field_override='=>'string'], 'SolrQuery::setHighlightUsePhraseHighlighter' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setMlt' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setMltBoost' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setMltCount' => ['SolrQuery', 'count'=>'int'], 'SolrQuery::setMltMaxNumQueryTerms' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setMltMaxNumTokens' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setMltMaxWordLength' => ['SolrQuery', 'maxwordlength'=>'int'], 'SolrQuery::setMltMinDocFrequency' => ['SolrQuery', 'mindocfrequency'=>'int'], 'SolrQuery::setMltMinTermFrequency' => ['SolrQuery', 'mintermfrequency'=>'int'], 'SolrQuery::setMltMinWordLength' => ['SolrQuery', 'minwordlength'=>'int'], 'SolrQuery::setOmitHeader' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setParam' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrQuery::setQuery' => ['SolrQuery', 'query'=>'string'], 'SolrQuery::setRows' => ['SolrQuery', 'rows'=>'int'], 'SolrQuery::setShowDebugInfo' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setStart' => ['SolrQuery', 'start'=>'int'], 'SolrQuery::setStats' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTerms' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTermsField' => ['SolrQuery', 'fieldname'=>'string'], 'SolrQuery::setTermsIncludeLowerBound' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTermsIncludeUpperBound' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTermsLimit' => ['SolrQuery', 'limit'=>'int'], 'SolrQuery::setTermsLowerBound' => ['SolrQuery', 'lowerbound'=>'string'], 'SolrQuery::setTermsMaxCount' => ['SolrQuery', 'frequency'=>'int'], 'SolrQuery::setTermsMinCount' => ['SolrQuery', 'frequency'=>'int'], 'SolrQuery::setTermsPrefix' => ['SolrQuery', 'prefix'=>'string'], 'SolrQuery::setTermsReturnRaw' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTermsSort' => ['SolrQuery', 'sorttype'=>'int'], 'SolrQuery::setTermsUpperBound' => ['SolrQuery', 'upperbound'=>'string'], 'SolrQuery::setTimeAllowed' => ['SolrQuery', 'timeallowed'=>'int'], 'SolrQuery::toString' => ['string', 'url_encode='=>'bool'], 'SolrQuery::unserialize' => ['void', 'serialized'=>'string'], 'SolrQueryResponse::__construct' => ['void'], 'SolrQueryResponse::__destruct' => ['void'], 'SolrQueryResponse::getDigestedResponse' => ['string'], 'SolrQueryResponse::getHttpStatus' => ['int'], 'SolrQueryResponse::getHttpStatusMessage' => ['string'], 'SolrQueryResponse::getRawRequest' => ['string'], 'SolrQueryResponse::getRawRequestHeaders' => ['string'], 'SolrQueryResponse::getRawResponse' => ['string'], 'SolrQueryResponse::getRawResponseHeaders' => ['string'], 'SolrQueryResponse::getRequestUrl' => ['string'], 'SolrQueryResponse::getResponse' => ['SolrObject'], 'SolrQueryResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrQueryResponse::success' => ['bool'], 'SolrResponse::getDigestedResponse' => ['string'], 'SolrResponse::getHttpStatus' => ['int'], 'SolrResponse::getHttpStatusMessage' => ['string'], 'SolrResponse::getRawRequest' => ['string'], 'SolrResponse::getRawRequestHeaders' => ['string'], 'SolrResponse::getRawResponse' => ['string'], 'SolrResponse::getRawResponseHeaders' => ['string'], 'SolrResponse::getRequestUrl' => ['string'], 'SolrResponse::getResponse' => ['SolrObject'], 'SolrResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrResponse::success' => ['bool'], 'SolrServerException::__clone' => ['void'], 'SolrServerException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'SolrServerException::__toString' => ['string'], 'SolrServerException::__wakeup' => ['void'], 'SolrServerException::getCode' => ['int'], 'SolrServerException::getFile' => ['string'], 'SolrServerException::getInternalInfo' => ['array'], 'SolrServerException::getLine' => ['int'], 'SolrServerException::getMessage' => ['string'], 'SolrServerException::getPrevious' => ['Exception|Throwable'], 'SolrServerException::getTrace' => ['list>'], 'SolrServerException::getTraceAsString' => ['string'], 'SolrUpdateResponse::__construct' => ['void'], 'SolrUpdateResponse::__destruct' => ['void'], 'SolrUpdateResponse::getDigestedResponse' => ['string'], 'SolrUpdateResponse::getHttpStatus' => ['int'], 'SolrUpdateResponse::getHttpStatusMessage' => ['string'], 'SolrUpdateResponse::getRawRequest' => ['string'], 'SolrUpdateResponse::getRawRequestHeaders' => ['string'], 'SolrUpdateResponse::getRawResponse' => ['string'], 'SolrUpdateResponse::getRawResponseHeaders' => ['string'], 'SolrUpdateResponse::getRequestUrl' => ['string'], 'SolrUpdateResponse::getResponse' => ['SolrObject'], 'SolrUpdateResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrUpdateResponse::success' => ['bool'], 'SolrUtils::digestXmlResponse' => ['SolrObject', 'xmlresponse'=>'string', 'parse_mode='=>'int'], 'SolrUtils::escapeQueryChars' => ['string|false', 'string'=>'string'], 'SolrUtils::getSolrVersion' => ['string'], 'SolrUtils::queryPhrase' => ['string', 'string'=>'string'], 'sort' => ['bool', '&rw_array'=>'array', 'sort_flags='=>'int'], 'soundex' => ['string', 'string'=>'string'], 'SphinxClient::__construct' => ['void'], 'SphinxClient::addQuery' => ['int', 'query'=>'string', 'index='=>'string', 'comment='=>'string'], 'SphinxClient::buildExcerpts' => ['array', 'docs'=>'array', 'index'=>'string', 'words'=>'string', 'opts='=>'array'], 'SphinxClient::buildKeywords' => ['array', 'query'=>'string', 'index'=>'string', 'hits'=>'bool'], 'SphinxClient::close' => ['bool'], 'SphinxClient::escapeString' => ['string', 'string'=>'string'], 'SphinxClient::getLastError' => ['string'], 'SphinxClient::getLastWarning' => ['string'], 'SphinxClient::open' => ['bool'], 'SphinxClient::query' => ['array', 'query'=>'string', 'index='=>'string', 'comment='=>'string'], 'SphinxClient::resetFilters' => ['void'], 'SphinxClient::resetGroupBy' => ['void'], 'SphinxClient::runQueries' => ['array'], 'SphinxClient::setArrayResult' => ['bool', 'array_result'=>'bool'], 'SphinxClient::setConnectTimeout' => ['bool', 'timeout'=>'float'], 'SphinxClient::setFieldWeights' => ['bool', 'weights'=>'array'], 'SphinxClient::setFilter' => ['bool', 'attribute'=>'string', 'values'=>'array', 'exclude='=>'bool'], 'SphinxClient::setFilterFloatRange' => ['bool', 'attribute'=>'string', 'min'=>'float', 'max'=>'float', 'exclude='=>'bool'], 'SphinxClient::setFilterRange' => ['bool', 'attribute'=>'string', 'min'=>'int', 'max'=>'int', 'exclude='=>'bool'], 'SphinxClient::setGeoAnchor' => ['bool', 'attrlat'=>'string', 'attrlong'=>'string', 'latitude'=>'float', 'longitude'=>'float'], 'SphinxClient::setGroupBy' => ['bool', 'attribute'=>'string', 'func'=>'int', 'groupsort='=>'string'], 'SphinxClient::setGroupDistinct' => ['bool', 'attribute'=>'string'], 'SphinxClient::setIDRange' => ['bool', 'min'=>'int', 'max'=>'int'], 'SphinxClient::setIndexWeights' => ['bool', 'weights'=>'array'], 'SphinxClient::setLimits' => ['bool', 'offset'=>'int', 'limit'=>'int', 'max_matches='=>'int', 'cutoff='=>'int'], 'SphinxClient::setMatchMode' => ['bool', 'mode'=>'int'], 'SphinxClient::setMaxQueryTime' => ['bool', 'qtime'=>'int'], 'SphinxClient::setOverride' => ['bool', 'attribute'=>'string', 'type'=>'int', 'values'=>'array'], 'SphinxClient::setRankingMode' => ['bool', 'ranker'=>'int'], 'SphinxClient::setRetries' => ['bool', 'count'=>'int', 'delay='=>'int'], 'SphinxClient::setSelect' => ['bool', 'clause'=>'string'], 'SphinxClient::setServer' => ['bool', 'server'=>'string', 'port'=>'int'], 'SphinxClient::setSortMode' => ['bool', 'mode'=>'int', 'sortby='=>'string'], 'SphinxClient::status' => ['array'], 'SphinxClient::updateAttributes' => ['int', 'index'=>'string', 'attributes'=>'array', 'values'=>'array', 'mva='=>'bool'], 'spl_autoload' => ['void', 'class_name'=>'string', 'file_extensions='=>'string'], 'spl_autoload_call' => ['void', 'class_name'=>'string'], 'spl_autoload_extensions' => ['string', 'file_extensions='=>'string'], 'spl_autoload_functions' => ['false|array'], 'spl_autoload_register' => ['bool', 'autoload_function='=>'callable(string):void', 'throw='=>'bool', 'prepend='=>'bool'], 'spl_autoload_unregister' => ['bool', 'autoload_function'=>'mixed'], 'spl_classes' => ['array'], 'spl_object_hash' => ['string', 'object'=>'object'], 'spl_object_id' => ['int', 'object'=>'object'], 'SplDoublyLinkedList::__construct' => ['void'], 'SplDoublyLinkedList::add' => ['void', 'index'=>'mixed', 'newval'=>'mixed'], 'SplDoublyLinkedList::bottom' => ['mixed'], 'SplDoublyLinkedList::count' => ['int'], 'SplDoublyLinkedList::current' => ['mixed'], 'SplDoublyLinkedList::getIteratorMode' => ['int'], 'SplDoublyLinkedList::isEmpty' => ['bool'], 'SplDoublyLinkedList::key' => ['mixed'], 'SplDoublyLinkedList::next' => ['void'], 'SplDoublyLinkedList::offsetExists' => ['bool', 'index'=>'mixed'], 'SplDoublyLinkedList::offsetGet' => ['mixed', 'index'=>'mixed'], 'SplDoublyLinkedList::offsetSet' => ['void', 'index'=>'mixed', 'newval'=>'mixed'], 'SplDoublyLinkedList::offsetUnset' => ['void', 'index'=>'mixed'], 'SplDoublyLinkedList::pop' => ['mixed'], 'SplDoublyLinkedList::prev' => ['void'], 'SplDoublyLinkedList::push' => ['void', 'value'=>'mixed'], 'SplDoublyLinkedList::rewind' => ['void'], 'SplDoublyLinkedList::serialize' => ['string'], 'SplDoublyLinkedList::setIteratorMode' => ['void', 'flags'=>'int'], 'SplDoublyLinkedList::shift' => ['mixed'], 'SplDoublyLinkedList::top' => ['mixed'], 'SplDoublyLinkedList::unserialize' => ['void', 'serialized'=>'string'], 'SplDoublyLinkedList::unshift' => ['bool', 'value'=>'mixed'], 'SplDoublyLinkedList::valid' => ['bool'], 'SplEnum::__construct' => ['void', 'initial_value='=>'mixed', 'strict='=>'bool'], 'SplEnum::getConstList' => ['array', 'include_default='=>'bool'], 'SplFileInfo::__construct' => ['void', 'file_name'=>'string'], 'SplFileInfo::__toString' => ['string'], 'SplFileInfo::__wakeup' => ['void'], 'SplFileInfo::getATime' => ['int'], 'SplFileInfo::getBasename' => ['string', 'suffix='=>'string'], 'SplFileInfo::getCTime' => ['int'], 'SplFileInfo::getExtension' => ['string'], 'SplFileInfo::getFileInfo' => ['SplFileInfo', 'class_name='=>'string'], 'SplFileInfo::getFilename' => ['string'], 'SplFileInfo::getGroup' => ['int'], 'SplFileInfo::getInode' => ['int'], 'SplFileInfo::getLinkTarget' => ['string'], 'SplFileInfo::getMTime' => ['int'], 'SplFileInfo::getOwner' => ['int'], 'SplFileInfo::getPath' => ['string'], 'SplFileInfo::getPathInfo' => ['SplFileInfo', 'class_name='=>'string'], 'SplFileInfo::getPathname' => ['string'], 'SplFileInfo::getPerms' => ['int'], 'SplFileInfo::getRealPath' => ['string|false'], 'SplFileInfo::getSize' => ['int'], 'SplFileInfo::getType' => ['string'], 'SplFileInfo::isDir' => ['bool'], 'SplFileInfo::isExecutable' => ['bool'], 'SplFileInfo::isFile' => ['bool'], 'SplFileInfo::isLink' => ['bool'], 'SplFileInfo::isReadable' => ['bool'], 'SplFileInfo::isWritable' => ['bool'], 'SplFileInfo::openFile' => ['SplFileObject', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'SplFileInfo::setFileClass' => ['void', 'class_name='=>'string'], 'SplFileInfo::setInfoClass' => ['void', 'class_name='=>'string'], 'SplFileObject::__construct' => ['void', 'filename'=>'string', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>''], 'SplFileObject::__toString' => ['string'], 'SplFileObject::current' => ['string|array|false'], 'SplFileObject::eof' => ['bool'], 'SplFileObject::fflush' => ['bool'], 'SplFileObject::fgetc' => ['string|false'], 'SplFileObject::fgetcsv' => ['list|array{0: null}|false|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplFileObject::fgets' => ['string|false'], 'SplFileObject::fgetss' => ['string|false', 'allowable_tags='=>'string'], 'SplFileObject::flock' => ['bool', 'operation'=>'int', '&w_wouldblock='=>'int'], 'SplFileObject::fpassthru' => ['int|false'], 'SplFileObject::fputcsv' => ['int|false', 'fields'=>'array', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplFileObject::fread' => ['string|false', 'length'=>'int'], 'SplFileObject::fscanf' => ['array|int', 'format'=>'string', '&...w_vars='=>'string|int|float'], 'SplFileObject::fseek' => ['int', 'pos'=>'int', 'whence='=>'int'], 'SplFileObject::fstat' => ['array|false'], 'SplFileObject::ftell' => ['int|false'], 'SplFileObject::ftruncate' => ['bool', 'size'=>'int'], 'SplFileObject::fwrite' => ['int', 'string'=>'string', 'length='=>'int'], 'SplFileObject::getATime' => ['int'], 'SplFileObject::getBasename' => ['string', 'suffix='=>'string'], 'SplFileObject::getChildren' => ['null'], 'SplFileObject::getCsvControl' => ['array'], 'SplFileObject::getCTime' => ['int'], 'SplFileObject::getCurrentLine' => ['string|false'], 'SplFileObject::getExtension' => ['string'], 'SplFileObject::getFileInfo' => ['SplFileInfo', 'class_name='=>'string'], 'SplFileObject::getFilename' => ['string'], 'SplFileObject::getFlags' => ['int'], 'SplFileObject::getGroup' => ['int'], 'SplFileObject::getInode' => ['int'], 'SplFileObject::getLinkTarget' => ['string'], 'SplFileObject::getMaxLineLen' => ['int'], 'SplFileObject::getMTime' => ['int'], 'SplFileObject::getOwner' => ['int'], 'SplFileObject::getPath' => ['string'], 'SplFileObject::getPathInfo' => ['SplFileInfo', 'class_name='=>'string'], 'SplFileObject::getPathname' => ['string'], 'SplFileObject::getPerms' => ['int'], 'SplFileObject::getRealPath' => ['false|string'], 'SplFileObject::getSize' => ['int'], 'SplFileObject::getType' => ['string'], 'SplFileObject::hasChildren' => ['false'], 'SplFileObject::isDir' => ['bool'], 'SplFileObject::isExecutable' => ['bool'], 'SplFileObject::isFile' => ['bool'], 'SplFileObject::isLink' => ['bool'], 'SplFileObject::isReadable' => ['bool'], 'SplFileObject::isWritable' => ['bool'], 'SplFileObject::key' => ['int'], 'SplFileObject::next' => ['void'], 'SplFileObject::openFile' => ['SplFileObject', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'SplFileObject::rewind' => ['void'], 'SplFileObject::seek' => ['void', 'line_pos'=>'int'], 'SplFileObject::setCsvControl' => ['void', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplFileObject::setFileClass' => ['void', 'class_name='=>'string'], 'SplFileObject::setFlags' => ['void', 'flags'=>'int'], 'SplFileObject::setInfoClass' => ['void', 'class_name='=>'string'], 'SplFileObject::setMaxLineLen' => ['void', 'max_len'=>'int'], 'SplFileObject::valid' => ['bool'], 'SplFixedArray::__construct' => ['void', 'size='=>'int'], 'SplFixedArray::__wakeup' => ['void'], 'SplFixedArray::count' => ['int'], 'SplFixedArray::current' => ['mixed'], 'SplFixedArray::fromArray' => ['SplFixedArray', 'data'=>'array', 'save_indexes='=>'bool'], 'SplFixedArray::getSize' => ['int'], 'SplFixedArray::key' => ['int'], 'SplFixedArray::next' => ['void'], 'SplFixedArray::offsetExists' => ['bool', 'index'=>'int'], 'SplFixedArray::offsetGet' => ['mixed', 'index'=>'int'], 'SplFixedArray::offsetSet' => ['void', 'index'=>'int', 'newval'=>'mixed'], 'SplFixedArray::offsetUnset' => ['void', 'index'=>'int'], 'SplFixedArray::rewind' => ['void'], 'SplFixedArray::setSize' => ['bool', 'size'=>'int'], 'SplFixedArray::toArray' => ['array'], 'SplFixedArray::valid' => ['bool'], 'SplHeap::__construct' => ['void'], 'SplHeap::compare' => ['int', 'value1'=>'mixed', 'value2'=>'mixed'], 'SplHeap::count' => ['int'], 'SplHeap::current' => ['mixed'], 'SplHeap::extract' => ['mixed'], 'SplHeap::insert' => ['bool', 'value'=>'mixed'], 'SplHeap::isCorrupted' => ['bool'], 'SplHeap::isEmpty' => ['bool'], 'SplHeap::key' => ['int'], 'SplHeap::next' => ['void'], 'SplHeap::recoverFromCorruption' => ['int'], 'SplHeap::rewind' => ['void'], 'SplHeap::top' => ['mixed'], 'SplHeap::valid' => ['bool'], 'SplMaxHeap::__construct' => ['void'], 'SplMaxHeap::compare' => ['int', 'a'=>'mixed', 'b'=>'mixed'], 'SplMinHeap::compare' => ['int', 'a'=>'mixed', 'b'=>'mixed'], 'SplMinHeap::count' => ['int'], 'SplMinHeap::current' => ['mixed'], 'SplMinHeap::extract' => ['mixed'], 'SplMinHeap::insert' => ['void', 'value'=>'mixed'], 'SplMinHeap::isCorrupted' => ['int'], 'SplMinHeap::isEmpty' => ['bool'], 'SplMinHeap::key' => ['mixed'], 'SplMinHeap::next' => ['void'], 'SplMinHeap::recoverFromCorruption' => ['void'], 'SplMinHeap::rewind' => ['void'], 'SplMinHeap::top' => ['mixed'], 'SplMinHeap::valid' => ['bool'], 'SplObjectStorage::__construct' => ['void'], 'SplObjectStorage::addAll' => ['void', 'os'=>'splobjectstorage'], 'SplObjectStorage::attach' => ['void', 'object'=>'object', 'inf='=>'mixed'], 'SplObjectStorage::contains' => ['bool', 'object'=>'object'], 'SplObjectStorage::count' => ['int'], 'SplObjectStorage::current' => ['object'], 'SplObjectStorage::detach' => ['void', 'object'=>'object'], 'SplObjectStorage::getHash' => ['string', 'object'=>'object'], 'SplObjectStorage::getInfo' => ['mixed'], 'SplObjectStorage::key' => ['int'], 'SplObjectStorage::next' => ['void'], 'SplObjectStorage::offsetExists' => ['bool', 'object'=>'object'], 'SplObjectStorage::offsetGet' => ['mixed', 'object'=>'object'], 'SplObjectStorage::offsetSet' => ['object', 'object'=>'object', 'data='=>'mixed'], 'SplObjectStorage::offsetUnset' => ['object', 'object'=>'object'], 'SplObjectStorage::removeAll' => ['void', 'os'=>'splobjectstorage'], 'SplObjectStorage::removeAllExcept' => ['void', 'os'=>'splobjectstorage'], 'SplObjectStorage::rewind' => ['void'], 'SplObjectStorage::serialize' => ['string'], 'SplObjectStorage::setInfo' => ['void', 'inf'=>'mixed'], 'SplObjectStorage::unserialize' => ['void', 'serialized'=>'string'], 'SplObjectStorage::valid' => ['bool'], 'SplObserver::update' => ['void', 'subject'=>'SplSubject'], 'SplPriorityQueue::__construct' => ['void'], 'SplPriorityQueue::compare' => ['int', 'a'=>'mixed', 'b'=>'mixed'], 'SplPriorityQueue::count' => ['int'], 'SplPriorityQueue::current' => ['mixed'], 'SplPriorityQueue::extract' => ['mixed'], 'SplPriorityQueue::getExtractFlags' => ['int'], 'SplPriorityQueue::insert' => ['bool', 'value'=>'mixed', 'priority'=>'mixed'], 'SplPriorityQueue::isCorrupted' => ['bool'], 'SplPriorityQueue::isEmpty' => ['bool'], 'SplPriorityQueue::key' => ['mixed'], 'SplPriorityQueue::next' => ['void'], 'SplPriorityQueue::recoverFromCorruption' => ['void'], 'SplPriorityQueue::rewind' => ['void'], 'SplPriorityQueue::setExtractFlags' => ['void', 'flags'=>'int'], 'SplPriorityQueue::top' => ['mixed'], 'SplPriorityQueue::valid' => ['bool'], 'SplQueue::dequeue' => ['mixed'], 'SplQueue::enqueue' => ['void', 'value'=>'mixed'], 'SplQueue::getIteratorMode' => ['int'], 'SplQueue::isEmpty' => ['bool'], 'SplQueue::key' => ['mixed'], 'SplQueue::next' => ['void'], 'SplQueue::offsetExists' => ['bool', 'index'=>'mixed'], 'SplQueue::offsetGet' => ['mixed', 'index'=>'mixed'], 'SplQueue::offsetSet' => ['void', 'index'=>'mixed', 'newval'=>'mixed'], 'SplQueue::offsetUnset' => ['void', 'index'=>'mixed'], 'SplQueue::pop' => ['mixed'], 'SplQueue::prev' => ['void'], 'SplQueue::push' => ['void', 'value'=>'mixed'], 'SplQueue::rewind' => ['void'], 'SplQueue::serialize' => ['string'], 'SplQueue::setIteratorMode' => ['void', 'mode'=>'int'], 'SplQueue::shift' => ['mixed'], 'SplQueue::top' => ['mixed'], 'SplQueue::unserialize' => ['void', 'serialized'=>'string'], 'SplQueue::unshift' => ['bool', 'value'=>'mixed'], 'SplQueue::valid' => ['bool'], 'SplStack::__construct' => ['void'], 'SplStack::add' => ['void', 'index'=>'mixed', 'newval'=>'mixed'], 'SplStack::bottom' => ['mixed'], 'SplStack::count' => ['int'], 'SplStack::current' => ['mixed'], 'SplStack::getIteratorMode' => ['int'], 'SplStack::isEmpty' => ['bool'], 'SplStack::key' => ['mixed'], 'SplStack::next' => ['void'], 'SplStack::offsetExists' => ['bool', 'index'=>'mixed'], 'SplStack::offsetGet' => ['mixed', 'index'=>'mixed'], 'SplStack::offsetSet' => ['void', 'index'=>'mixed', 'newval'=>'mixed'], 'SplStack::offsetUnset' => ['void', 'index'=>'mixed'], 'SplStack::pop' => ['mixed'], 'SplStack::prev' => ['void'], 'SplStack::push' => ['void', 'value'=>'mixed'], 'SplStack::rewind' => ['void'], 'SplStack::serialize' => ['string'], 'SplStack::setIteratorMode' => ['void', 'mode'=>'int'], 'SplStack::shift' => ['mixed'], 'SplStack::top' => ['mixed'], 'SplStack::unserialize' => ['void', 'serialized'=>'string'], 'SplStack::unshift' => ['bool', 'value'=>'mixed'], 'SplStack::valid' => ['bool'], 'SplSubject::attach' => ['void', 'observer'=>'SplObserver'], 'SplSubject::detach' => ['void', 'observer'=>'SplObserver'], 'SplSubject::notify' => ['void'], 'SplTempFileObject::__construct' => ['void', 'max_memory='=>'int'], 'SplTempFileObject::__toString' => ['string'], 'SplTempFileObject::_bad_state_ex' => [''], 'SplTempFileObject::current' => ['array|false|string'], 'SplTempFileObject::eof' => ['bool'], 'SplTempFileObject::fflush' => ['bool'], 'SplTempFileObject::fgetc' => ['false|string'], 'SplTempFileObject::fgetcsv' => ['list|array{0: null}|false|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplTempFileObject::fgets' => ['string'], 'SplTempFileObject::fgetss' => ['string', 'allowable_tags='=>'string'], 'SplTempFileObject::flock' => ['bool', 'operation'=>'int', '&wouldblock='=>'int'], 'SplTempFileObject::fpassthru' => ['int|false'], 'SplTempFileObject::fputcsv' => ['false|int', 'fields'=>'array', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplTempFileObject::fread' => ['false|string', 'length'=>'int'], 'SplTempFileObject::fscanf' => ['bool', 'format'=>'string', '&...w_vars='=>'array|array|array'], 'SplTempFileObject::fseek' => ['int', 'pos'=>'int', 'whence='=>'int'], 'SplTempFileObject::fstat' => ['array|false'], 'SplTempFileObject::ftell' => ['int'], 'SplTempFileObject::ftruncate' => ['bool', 'size'=>'int'], 'SplTempFileObject::fwrite' => ['int', 'string'=>'string', 'length='=>'int'], 'SplTempFileObject::getATime' => ['int'], 'SplTempFileObject::getBasename' => ['string', 'suffix='=>'string'], 'SplTempFileObject::getChildren' => ['null'], 'SplTempFileObject::getCsvControl' => ['array'], 'SplTempFileObject::getCTime' => ['int'], 'SplTempFileObject::getCurrentLine' => ['string'], 'SplTempFileObject::getExtension' => ['string'], 'SplTempFileObject::getFileInfo' => ['SplFileInfo', 'class_name='=>'string'], 'SplTempFileObject::getFilename' => ['string'], 'SplTempFileObject::getFlags' => ['int'], 'SplTempFileObject::getGroup' => ['int'], 'SplTempFileObject::getInode' => ['int'], 'SplTempFileObject::getLinkTarget' => ['string'], 'SplTempFileObject::getMaxLineLen' => ['int'], 'SplTempFileObject::getMTime' => ['int'], 'SplTempFileObject::getOwner' => ['int'], 'SplTempFileObject::getPath' => ['string'], 'SplTempFileObject::getPathInfo' => ['SplFileInfo', 'class_name='=>'string'], 'SplTempFileObject::getPathname' => ['string'], 'SplTempFileObject::getPerms' => ['int'], 'SplTempFileObject::getRealPath' => ['string'], 'SplTempFileObject::getSize' => ['int'], 'SplTempFileObject::getType' => ['string'], 'SplTempFileObject::hasChildren' => ['bool'], 'SplTempFileObject::isDir' => ['bool'], 'SplTempFileObject::isExecutable' => ['bool'], 'SplTempFileObject::isFile' => ['bool'], 'SplTempFileObject::isLink' => ['bool'], 'SplTempFileObject::isReadable' => ['bool'], 'SplTempFileObject::isWritable' => ['bool'], 'SplTempFileObject::key' => ['int'], 'SplTempFileObject::next' => ['void'], 'SplTempFileObject::openFile' => ['SplFileObject', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'SplTempFileObject::rewind' => ['void'], 'SplTempFileObject::seek' => ['void', 'line_pos'=>'int'], 'SplTempFileObject::setCsvControl' => ['void', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplTempFileObject::setFileClass' => ['void', 'class_name='=>'string'], 'SplTempFileObject::setFlags' => ['void', 'flags'=>'int'], 'SplTempFileObject::setInfoClass' => ['void', 'class_name='=>'string'], 'SplTempFileObject::setMaxLineLen' => ['void', 'max_len'=>'int'], 'SplTempFileObject::valid' => ['bool'], 'SplType::__construct' => ['void', 'initial_value='=>'mixed', 'strict='=>'bool'], 'Spoofchecker::__construct' => ['void'], 'Spoofchecker::areConfusable' => ['bool', 's1'=>'string', 's2'=>'string', '&w_error='=>'string'], 'Spoofchecker::isSuspicious' => ['bool', 'text'=>'string', '&w_error='=>'string'], 'Spoofchecker::setAllowedLocales' => ['void', 'locale_list'=>'string'], 'Spoofchecker::setChecks' => ['void', 'checks'=>'long'], 'Spoofchecker::setRestrictionLevel' => ['void', 'restriction_level'=>'int'], 'sprintf' => ['string', 'format'=>'string', '...vars='=>'string|int|float'], 'SQLite3::__construct' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryption_key='=>'?string'], 'SQLite3::busyTimeout' => ['bool', 'msecs'=>'int'], 'SQLite3::changes' => ['int'], 'SQLite3::close' => ['bool'], 'SQLite3::createAggregate' => ['bool', 'name'=>'string', 'step_callback'=>'callable', 'final_callback'=>'callable', 'argument_count='=>'int'], 'SQLite3::createCollation' => ['bool', 'name'=>'string', 'callback'=>'callable'], 'SQLite3::createFunction' => ['bool', 'name'=>'string', 'callback'=>'callable', 'argument_count='=>'int', 'flags='=>'int'], 'SQLite3::enableExceptions' => ['bool', 'enableexceptions='=>'bool'], 'SQLite3::escapeString' => ['string', 'value'=>'string'], 'SQLite3::exec' => ['bool', 'query'=>'string'], 'SQLite3::lastErrorCode' => ['int'], 'SQLite3::lastErrorMsg' => ['string'], 'SQLite3::lastInsertRowID' => ['int'], 'SQLite3::loadExtension' => ['bool', 'shared_library'=>'string'], 'SQLite3::open' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryption_key='=>'?string'], 'SQLite3::openBlob' => ['resource|false', 'table'=>'string', 'column'=>'string', 'rowid'=>'int', 'dbname='=>'string', 'flags='=>'int'], 'SQLite3::prepare' => ['SQLite3Stmt|false', 'query'=>'string'], 'SQLite3::query' => ['SQLite3Result|false', 'query'=>'string'], 'SQLite3::querySingle' => ['array|int|string|bool|float|null|false', 'query'=>'string', 'entire_row='=>'bool'], 'SQLite3::version' => ['array'], 'SQLite3Result::__construct' => ['void'], 'SQLite3Result::columnName' => ['string', 'column_number'=>'int'], 'SQLite3Result::columnType' => ['int', 'column_number'=>'int'], 'SQLite3Result::fetchArray' => ['array|false', 'mode='=>'int'], 'SQLite3Result::finalize' => ['bool'], 'SQLite3Result::numColumns' => ['int'], 'SQLite3Result::reset' => ['bool'], 'SQLite3Stmt::__construct' => ['void', 'dbobject'=>'sqlite3', 'statement'=>'string'], 'SQLite3Stmt::bindParam' => ['bool', 'parameter_name_or_number'=>'string|int', '&rw_parameter'=>'mixed', 'type='=>'int'], 'SQLite3Stmt::bindValue' => ['bool', 'parameter_name_or_number'=>'string|int', 'parameter'=>'mixed', 'type='=>'int'], 'SQLite3Stmt::clear' => ['bool'], 'SQLite3Stmt::close' => ['bool'], 'SQLite3Stmt::execute' => ['false|SQLite3Result'], 'SQLite3Stmt::getSQL' => ['string', 'expanded='=>'bool'], 'SQLite3Stmt::paramCount' => ['int'], 'SQLite3Stmt::readOnly' => ['bool'], 'SQLite3Stmt::reset' => ['bool'], 'sqlite_array_query' => ['array|false', 'dbhandle'=>'resource', 'query'=>'string', 'result_type='=>'int', 'decode_binary='=>'bool'], 'sqlite_busy_timeout' => ['void', 'dbhandle'=>'resource', 'milliseconds'=>'int'], 'sqlite_changes' => ['int', 'dbhandle'=>'resource'], 'sqlite_close' => ['void', 'dbhandle'=>'resource'], 'sqlite_column' => ['mixed', 'result'=>'resource', 'index_or_name'=>'mixed', 'decode_binary='=>'bool'], 'sqlite_create_aggregate' => ['void', 'dbhandle'=>'resource', 'function_name'=>'string', 'step_func'=>'callable', 'finalize_func'=>'callable', 'num_args='=>'int'], 'sqlite_create_function' => ['void', 'dbhandle'=>'resource', 'function_name'=>'string', 'callback'=>'callable', 'num_args='=>'int'], 'sqlite_current' => ['array|false', 'result'=>'resource', 'result_type='=>'int', 'decode_binary='=>'bool'], 'sqlite_error_string' => ['string', 'error_code'=>'int'], 'sqlite_escape_string' => ['string', 'item'=>'string'], 'sqlite_exec' => ['bool', 'dbhandle'=>'resource', 'query'=>'string', 'error_msg='=>'string'], 'sqlite_factory' => ['SQLiteDatabase', 'filename'=>'string', 'mode='=>'int', 'error_message='=>'string'], 'sqlite_fetch_all' => ['array', 'result'=>'resource', 'result_type='=>'int', 'decode_binary='=>'bool'], 'sqlite_fetch_array' => ['array|false', 'result'=>'resource', 'result_type='=>'int', 'decode_binary='=>'bool'], 'sqlite_fetch_column_types' => ['array|false', 'table_name'=>'string', 'dbhandle'=>'resource', 'result_type='=>'int'], 'sqlite_fetch_object' => ['object', 'result'=>'resource', 'class_name='=>'string', 'ctor_params='=>'array', 'decode_binary='=>'bool'], 'sqlite_fetch_single' => ['string', 'result'=>'resource', 'decode_binary='=>'bool'], 'sqlite_fetch_string' => ['string', 'result'=>'resource', 'decode_binary'=>'bool'], 'sqlite_field_name' => ['string', 'result'=>'resource', 'field_index'=>'int'], 'sqlite_has_more' => ['bool', 'result'=>'resource'], 'sqlite_has_prev' => ['bool', 'result'=>'resource'], 'sqlite_key' => ['int', 'result'=>'resource'], 'sqlite_last_error' => ['int', 'dbhandle'=>'resource'], 'sqlite_last_insert_rowid' => ['int', 'dbhandle'=>'resource'], 'sqlite_libencoding' => ['string'], 'sqlite_libversion' => ['string'], 'sqlite_next' => ['bool', 'result'=>'resource'], 'sqlite_num_fields' => ['int', 'result'=>'resource'], 'sqlite_num_rows' => ['int', 'result'=>'resource'], 'sqlite_open' => ['resource|false', 'filename'=>'string', 'mode='=>'int', 'error_message='=>'string'], 'sqlite_popen' => ['resource|false', 'filename'=>'string', 'mode='=>'int', 'error_message='=>'string'], 'sqlite_prev' => ['bool', 'result'=>'resource'], 'sqlite_query' => ['resource|false', 'dbhandle'=>'resource', 'query'=>'resource|string', 'result_type='=>'int', 'error_msg='=>'string'], 'sqlite_rewind' => ['bool', 'result'=>'resource'], 'sqlite_seek' => ['bool', 'result'=>'resource', 'rownum'=>'int'], 'sqlite_single_query' => ['array', 'db'=>'resource', 'query'=>'string', 'first_row_only='=>'bool', 'decode_binary='=>'bool'], 'sqlite_udf_decode_binary' => ['string', 'data'=>'string'], 'sqlite_udf_encode_binary' => ['string', 'data'=>'string'], 'sqlite_unbuffered_query' => ['SQLiteUnbuffered|false', 'dbhandle'=>'resource', 'query'=>'string', 'result_type='=>'int', 'error_msg='=>'string'], 'sqlite_valid' => ['bool', 'result'=>'resource'], 'SQLiteDatabase::__construct' => ['void', 'filename'=>'', 'mode='=>'int|mixed', '&error_message'=>''], 'SQLiteDatabase::arrayQuery' => ['array', 'query'=>'string', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteDatabase::busyTimeout' => ['int', 'milliseconds'=>'int'], 'SQLiteDatabase::changes' => ['int'], 'SQLiteDatabase::createAggregate' => ['', 'function_name'=>'string', 'step_func'=>'callable', 'finalize_func'=>'callable', 'num_args='=>'int'], 'SQLiteDatabase::createFunction' => ['', 'function_name'=>'string', 'callback'=>'callable', 'num_args='=>'int'], 'SQLiteDatabase::exec' => ['bool', 'query'=>'string', 'error_msg='=>'string'], 'SQLiteDatabase::fetchColumnTypes' => ['array', 'table_name'=>'string', 'result_type='=>'int'], 'SQLiteDatabase::lastError' => ['int'], 'SQLiteDatabase::lastInsertRowid' => ['int'], 'SQLiteDatabase::query' => ['SQLiteResult|false', 'query'=>'string', 'result_type='=>'int', 'error_msg='=>'string'], 'SQLiteDatabase::queryExec' => ['bool', 'query'=>'string', '&w_error_msg='=>'string'], 'SQLiteDatabase::singleQuery' => ['array', 'query'=>'string', 'first_row_only='=>'bool', 'decode_binary='=>'bool'], 'SQLiteDatabase::unbufferedQuery' => ['SQLiteUnbuffered|false', 'query'=>'string', 'result_type='=>'int', 'error_msg='=>'string'], 'SQLiteException::__clone' => ['void'], 'SQLiteException::__construct' => ['void', 'message'=>'', 'code'=>'', 'previous'=>''], 'SQLiteException::__toString' => ['string'], 'SQLiteException::__wakeup' => ['void'], 'SQLiteException::getCode' => ['int'], 'SQLiteException::getFile' => ['string'], 'SQLiteException::getLine' => ['int'], 'SQLiteException::getMessage' => ['string'], 'SQLiteException::getPrevious' => ['RuntimeException|Throwable|null'], 'SQLiteException::getTrace' => ['list>'], 'SQLiteException::getTraceAsString' => ['string'], 'SQLiteResult::__construct' => ['void'], 'SQLiteResult::column' => ['mixed', 'index_or_name'=>'', 'decode_binary='=>'bool'], 'SQLiteResult::count' => ['int'], 'SQLiteResult::current' => ['array', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteResult::fetch' => ['array', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteResult::fetchAll' => ['array', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteResult::fetchObject' => ['object', 'class_name='=>'string', 'ctor_params='=>'array', 'decode_binary='=>'bool'], 'SQLiteResult::fetchSingle' => ['string', 'decode_binary='=>'bool'], 'SQLiteResult::fieldName' => ['string', 'field_index'=>'int'], 'SQLiteResult::hasPrev' => ['bool'], 'SQLiteResult::key' => ['mixed|null'], 'SQLiteResult::next' => ['bool'], 'SQLiteResult::numFields' => ['int'], 'SQLiteResult::numRows' => ['int'], 'SQLiteResult::prev' => ['bool'], 'SQLiteResult::rewind' => ['bool'], 'SQLiteResult::seek' => ['bool', 'rownum'=>'int'], 'SQLiteResult::valid' => ['bool'], 'SQLiteUnbuffered::column' => ['void', 'index_or_name'=>'', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::current' => ['array', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fetch' => ['array', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fetchAll' => ['array', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fetchObject' => ['object', 'class_name='=>'string', 'ctor_params='=>'array', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fetchSingle' => ['string', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fieldName' => ['string', 'field_index'=>'int'], 'SQLiteUnbuffered::next' => ['bool'], 'SQLiteUnbuffered::numFields' => ['int'], 'SQLiteUnbuffered::valid' => ['bool'], 'sqlsrv_begin_transaction' => ['bool', 'conn'=>'resource'], 'sqlsrv_cancel' => ['bool', 'stmt'=>'resource'], 'sqlsrv_client_info' => ['array|false', 'conn'=>'resource'], 'sqlsrv_close' => ['bool', 'conn'=>'?resource'], 'sqlsrv_commit' => ['bool', 'conn'=>'resource'], 'sqlsrv_configure' => ['bool', 'setting'=>'string', 'value'=>'mixed'], 'sqlsrv_connect' => ['resource|false', 'serverName'=>'string', 'connectionInfo='=>'array'], 'sqlsrv_errors' => ['?array', 'errorsOrWarnings='=>'int'], 'sqlsrv_execute' => ['bool', 'stmt'=>'resource'], 'sqlsrv_fetch' => ['?bool', 'stmt'=>'resource', 'row='=>'int', 'offset='=>'int'], 'sqlsrv_fetch_array' => ['array|null|false', 'stmt'=>'resource', 'fetchType='=>'int', 'row='=>'int', 'offset='=>'int'], 'sqlsrv_fetch_object' => ['object|null|false', 'stmt'=>'resource', 'className='=>'string', 'ctorParams='=>'array', 'row='=>'int', 'offset='=>'int'], 'sqlsrv_field_metadata' => ['array|false', 'stmt'=>'resource'], 'sqlsrv_free_stmt' => ['bool', 'stmt'=>'resource'], 'sqlsrv_get_config' => ['mixed', 'setting'=>'string'], 'sqlsrv_get_field' => ['mixed', 'stmt'=>'resource', 'fieldIndex'=>'int', 'getAsType='=>'int'], 'sqlsrv_has_rows' => ['bool', 'stmt'=>'resource'], 'sqlsrv_next_result' => ['?bool', 'stmt'=>'resource'], 'sqlsrv_num_fields' => ['int|false', 'stmt'=>'resource'], 'sqlsrv_num_rows' => ['int|false', 'stmt'=>'resource'], 'sqlsrv_prepare' => ['resource|false', 'conn'=>'resource', 'sql'=>'string', 'params='=>'array', 'options='=>'array'], 'sqlsrv_query' => ['resource|false', 'conn'=>'resource', 'sql'=>'string', 'params='=>'array', 'options='=>'array'], 'sqlsrv_rollback' => ['bool', 'conn'=>'resource'], 'sqlsrv_rows_affected' => ['int|false', 'stmt'=>'resource'], 'sqlsrv_send_stream_data' => ['bool', 'stmt'=>'resource'], 'sqlsrv_server_info' => ['array', 'conn'=>'resource'], 'sqrt' => ['float', 'number'=>'float'], 'srand' => ['void', 'seed='=>'int', 'mode='=>'int'], 'sscanf' => ['list|int', 'string'=>'string', 'format'=>'string', '&...w_vars='=>'string|int|float'], 'ssdeep_fuzzy_compare' => ['int', 'signature1'=>'string', 'signature2'=>'string'], 'ssdeep_fuzzy_hash' => ['string', 'to_hash'=>'string'], 'ssdeep_fuzzy_hash_filename' => ['string', 'file_name'=>'string'], 'ssh2_auth_agent' => ['bool', 'session'=>'resource', 'username'=>'string'], 'ssh2_auth_hostbased_file' => ['bool', 'session'=>'resource', 'username'=>'string', 'hostname'=>'string', 'pubkeyfile'=>'string', 'privkeyfile'=>'string', 'passphrase='=>'string', 'local_username='=>'string'], 'ssh2_auth_none' => ['bool|string[]', 'session'=>'resource', 'username'=>'string'], 'ssh2_auth_password' => ['bool', 'session'=>'resource', 'username'=>'string', 'password'=>'string'], 'ssh2_auth_pubkey_file' => ['bool', 'session'=>'resource', 'username'=>'string', 'pubkeyfile'=>'string', 'privkeyfile'=>'string', 'passphrase='=>'string'], 'ssh2_connect' => ['resource|false', 'host'=>'string', 'port='=>'int', 'methods='=>'array', 'callbacks='=>'array'], 'ssh2_disconnect' => ['bool', 'session'=>'resource'], 'ssh2_exec' => ['resource|false', 'session'=>'resource', 'command'=>'string', 'pty='=>'string', 'env='=>'array', 'width='=>'int', 'height='=>'int', 'width_height_type='=>'int'], 'ssh2_fetch_stream' => ['resource|false', 'channel'=>'resource', 'streamid'=>'int'], 'ssh2_fingerprint' => ['string|false', 'session'=>'resource', 'flags='=>'int'], 'ssh2_forward_accept' => ['resource|false', 'session'=>'resource'], 'ssh2_forward_listen' => ['resource|false', 'session'=>'resource', 'port'=>'int', 'host='=>'string', 'max_connections='=>'string'], 'ssh2_methods_negotiated' => ['array|false', 'session'=>'resource'], 'ssh2_poll' => ['int', '&polldes'=>'array', 'timeout='=>'int'], 'ssh2_publickey_add' => ['bool', 'pkey'=>'resource', 'algoname'=>'string', 'blob'=>'string', 'overwrite='=>'bool', 'attributes='=>'array'], 'ssh2_publickey_init' => ['resource|false', 'session'=>'resource'], 'ssh2_publickey_list' => ['array|false', 'pkey'=>'resource'], 'ssh2_publickey_remove' => ['bool', 'pkey'=>'resource', 'algoname'=>'string', 'blob'=>'string'], 'ssh2_scp_recv' => ['bool', 'session'=>'resource', 'remote_file'=>'string', 'local_file'=>'string'], 'ssh2_scp_send' => ['bool', 'session'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'create_mode='=>'int'], 'ssh2_sftp' => ['resource|false', 'session'=>'resource'], 'ssh2_sftp_chmod' => ['bool', 'sftp'=>'resource', 'filename'=>'string', 'mode'=>'int'], 'ssh2_sftp_lstat' => ['array|false', 'sftp'=>'resource', 'path'=>'string'], 'ssh2_sftp_mkdir' => ['bool', 'sftp'=>'resource', 'dirname'=>'string', 'mode='=>'int', 'recursive='=>'bool'], 'ssh2_sftp_readlink' => ['string|false', 'sftp'=>'resource', 'link'=>'string'], 'ssh2_sftp_realpath' => ['string|false', 'sftp'=>'resource', 'filename'=>'string'], 'ssh2_sftp_rename' => ['bool', 'sftp'=>'resource', 'from'=>'string', 'to'=>'string'], 'ssh2_sftp_rmdir' => ['bool', 'sftp'=>'resource', 'dirname'=>'string'], 'ssh2_sftp_stat' => ['array|false', 'sftp'=>'resource', 'path'=>'string'], 'ssh2_sftp_symlink' => ['bool', 'sftp'=>'resource', 'target'=>'string', 'link'=>'string'], 'ssh2_sftp_unlink' => ['bool', 'sftp'=>'resource', 'filename'=>'string'], 'ssh2_shell' => ['resource|false', 'session'=>'resource', 'term_type='=>'string', 'env='=>'array', 'width='=>'int', 'height='=>'int', 'width_height_type='=>'int'], 'ssh2_tunnel' => ['resource|false', 'session'=>'resource', 'host'=>'string', 'port'=>'int'], 'stat' => ['array|false', 'filename'=>'string'], 'stats_absolute_deviation' => ['float', 'a'=>'array'], 'stats_cdf_beta' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_binomial' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_cauchy' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_chisquare' => ['float', 'par1'=>'float', 'par2'=>'float', 'which'=>'int'], 'stats_cdf_exponential' => ['float', 'par1'=>'float', 'par2'=>'float', 'which'=>'int'], 'stats_cdf_f' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_gamma' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_laplace' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_logistic' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_negative_binomial' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_noncentral_chisquare' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_noncentral_f' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'par4'=>'float', 'which'=>'int'], 'stats_cdf_noncentral_t' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_normal' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_poisson' => ['float', 'par1'=>'float', 'par2'=>'float', 'which'=>'int'], 'stats_cdf_t' => ['float', 'par1'=>'float', 'par2'=>'float', 'which'=>'int'], 'stats_cdf_uniform' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_weibull' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_covariance' => ['float', 'a'=>'array', 'b'=>'array'], 'stats_den_uniform' => ['float', 'x'=>'float', 'a'=>'float', 'b'=>'float'], 'stats_dens_beta' => ['float', 'x'=>'float', 'a'=>'float', 'b'=>'float'], 'stats_dens_cauchy' => ['float', 'x'=>'float', 'ave'=>'float', 'stdev'=>'float'], 'stats_dens_chisquare' => ['float', 'x'=>'float', 'dfr'=>'float'], 'stats_dens_exponential' => ['float', 'x'=>'float', 'scale'=>'float'], 'stats_dens_f' => ['float', 'x'=>'float', 'dfr1'=>'float', 'dfr2'=>'float'], 'stats_dens_gamma' => ['float', 'x'=>'float', 'shape'=>'float', 'scale'=>'float'], 'stats_dens_laplace' => ['float', 'x'=>'float', 'ave'=>'float', 'stdev'=>'float'], 'stats_dens_logistic' => ['float', 'x'=>'float', 'ave'=>'float', 'stdev'=>'float'], 'stats_dens_negative_binomial' => ['float', 'x'=>'float', 'n'=>'float', 'pi'=>'float'], 'stats_dens_normal' => ['float', 'x'=>'float', 'ave'=>'float', 'stdev'=>'float'], 'stats_dens_pmf_binomial' => ['float', 'x'=>'float', 'n'=>'float', 'pi'=>'float'], 'stats_dens_pmf_hypergeometric' => ['float', 'n1'=>'float', 'n2'=>'float', 'N1'=>'float', 'N2'=>'float'], 'stats_dens_pmf_negative_binomial' => ['float', 'x'=>'float', 'n'=>'float', 'pi'=>'float'], 'stats_dens_pmf_poisson' => ['float', 'x'=>'float', 'lb'=>'float'], 'stats_dens_t' => ['float', 'x'=>'float', 'dfr'=>'float'], 'stats_dens_uniform' => ['float', 'x'=>'float', 'a'=>'float', 'b'=>'float'], 'stats_dens_weibull' => ['float', 'x'=>'float', 'a'=>'float', 'b'=>'float'], 'stats_harmonic_mean' => ['float', 'a'=>'array'], 'stats_kurtosis' => ['float', 'a'=>'array'], 'stats_rand_gen_beta' => ['float', 'a'=>'float', 'b'=>'float'], 'stats_rand_gen_chisquare' => ['float', 'df'=>'float'], 'stats_rand_gen_exponential' => ['float', 'av'=>'float'], 'stats_rand_gen_f' => ['float', 'dfn'=>'float', 'dfd'=>'float'], 'stats_rand_gen_funiform' => ['float', 'low'=>'float', 'high'=>'float'], 'stats_rand_gen_gamma' => ['float', 'a'=>'float', 'r'=>'float'], 'stats_rand_gen_ibinomial' => ['int', 'n'=>'int', 'pp'=>'float'], 'stats_rand_gen_ibinomial_negative' => ['int', 'n'=>'int', 'p'=>'float'], 'stats_rand_gen_int' => ['int'], 'stats_rand_gen_ipoisson' => ['int', 'mu'=>'float'], 'stats_rand_gen_iuniform' => ['int', 'low'=>'int', 'high'=>'int'], 'stats_rand_gen_noncenral_chisquare' => ['float', 'df'=>'float', 'xnonc'=>'float'], 'stats_rand_gen_noncentral_chisquare' => ['float', 'df'=>'float', 'xnonc'=>'float'], 'stats_rand_gen_noncentral_f' => ['float', 'dfn'=>'float', 'dfd'=>'float', 'xnonc'=>'float'], 'stats_rand_gen_noncentral_t' => ['float', 'df'=>'float', 'xnonc'=>'float'], 'stats_rand_gen_normal' => ['float', 'av'=>'float', 'sd'=>'float'], 'stats_rand_gen_t' => ['float', 'df'=>'float'], 'stats_rand_get_seeds' => ['array'], 'stats_rand_phrase_to_seeds' => ['array', 'phrase'=>'string'], 'stats_rand_ranf' => ['float'], 'stats_rand_setall' => ['void', 'iseed1'=>'int', 'iseed2'=>'int'], 'stats_skew' => ['float', 'a'=>'array'], 'stats_standard_deviation' => ['float', 'a'=>'array', 'sample='=>'bool'], 'stats_stat_binomial_coef' => ['float', 'x'=>'int', 'n'=>'int'], 'stats_stat_correlation' => ['float', 'array1'=>'array', 'array2'=>'array'], 'stats_stat_factorial' => ['float', 'n'=>'int'], 'stats_stat_gennch' => ['float', 'n'=>'int'], 'stats_stat_independent_t' => ['float', 'array1'=>'array', 'array2'=>'array'], 'stats_stat_innerproduct' => ['float', 'array1'=>'array', 'array2'=>'array'], 'stats_stat_noncentral_t' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_stat_paired_t' => ['float', 'array1'=>'array', 'array2'=>'array'], 'stats_stat_percentile' => ['float', 'arr'=>'array', 'perc'=>'float'], 'stats_stat_powersum' => ['float', 'arr'=>'array', 'power'=>'float'], 'stats_variance' => ['float', 'a'=>'array', 'sample='=>'bool'], 'Stomp::__construct' => ['void', 'broker='=>'string', 'username='=>'string', 'password='=>'string', 'headers='=>'array'], 'Stomp::__destruct' => ['bool', 'link'=>''], 'Stomp::abort' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'Stomp::ack' => ['bool', 'msg'=>'', 'headers='=>'array', 'link='=>''], 'Stomp::begin' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'Stomp::commit' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'Stomp::error' => ['string', 'link'=>''], 'Stomp::getReadTimeout' => ['array', 'link'=>''], 'Stomp::getSessionId' => ['string', 'link'=>''], 'Stomp::hasFrame' => ['bool', 'link'=>''], 'Stomp::readFrame' => ['array', 'class_name='=>'string', 'link='=>''], 'Stomp::send' => ['bool', 'destination'=>'string', 'msg'=>'', 'headers='=>'array', 'link='=>''], 'Stomp::setReadTimeout' => ['', 'seconds'=>'int', 'microseconds='=>'int', 'link='=>''], 'Stomp::subscribe' => ['bool', 'destination'=>'string', 'headers='=>'array', 'link='=>''], 'Stomp::unsubscribe' => ['bool', 'destination'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_abort' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_ack' => ['bool', 'msg'=>'', 'headers='=>'array', 'link='=>''], 'stomp_begin' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_close' => ['bool', 'link'=>''], 'stomp_commit' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_connect' => ['resource', 'broker='=>'string', 'username='=>'string', 'password='=>'string', 'headers='=>'array'], 'stomp_connect_error' => ['string'], 'stomp_error' => ['string', 'link'=>''], 'stomp_get_read_timeout' => ['array', 'link'=>''], 'stomp_get_session_id' => ['string', 'link'=>''], 'stomp_has_frame' => ['bool', 'link'=>''], 'stomp_read_frame' => ['array', 'class_name='=>'string', 'link='=>''], 'stomp_send' => ['bool', 'destination'=>'string', 'msg'=>'', 'headers='=>'array', 'link='=>''], 'stomp_set_read_timeout' => ['', 'seconds'=>'int', 'microseconds='=>'int', 'link='=>''], 'stomp_subscribe' => ['bool', 'destination'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_unsubscribe' => ['bool', 'destination'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_version' => ['string'], 'StompException::getDetails' => ['string'], 'StompFrame::__construct' => ['void', 'command='=>'string', 'headers='=>'array', 'body='=>'string'], 'str_contains' => ['bool', 'haystack'=>'string', 'needle'=>'string'], 'str_ends_with' => ['bool', 'haystack'=>'string', 'needle'=>'string'], 'str_getcsv' => ['non-empty-list', 'input'=>'string', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'str_ireplace' => ['string|string[]', 'search'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', '&w_replace_count='=>'int'], 'str_pad' => ['string', 'input'=>'string', 'pad_length'=>'int', 'pad_string='=>'string', 'pad_type='=>'int'], 'str_repeat' => ['string', 'input'=>'string', 'multiplier'=>'int'], 'str_replace' => ['string|string[]', 'search'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', '&w_replace_count='=>'int'], 'str_rot13' => ['string', 'string'=>'string'], 'str_shuffle' => ['string', 'string'=>'string'], 'str_split' => ['list|false', 'str'=>'string', 'split_length='=>'int'], 'str_starts_with' => ['bool', 'haystack'=>'string', 'needle'=>'string'], 'str_word_count' => ['array|int', 'string'=>'string', 'format='=>'int', 'charlist='=>'string'], 'strcasecmp' => ['int', 'string1'=>'string', 'string2'=>'string'], 'strchr' => ['string|false', 'haystack'=>'string', 'needle'=>'mixed', 'before_needle='=>'bool'], 'strcmp' => ['int', 'string1'=>'string', 'string2'=>'string'], 'strcoll' => ['int', 'string1'=>'string', 'string2'=>'string'], 'strcspn' => ['int', 'string'=>'string', 'mask'=>'string', 'start='=>'int', 'length='=>'int'], 'stream_bucket_append' => ['void', 'brigade'=>'resource', 'bucket'=>'object'], 'stream_bucket_make_writeable' => ['object', 'brigade'=>'resource'], 'stream_bucket_new' => ['object|false', 'stream'=>'resource', 'buffer'=>'string'], 'stream_bucket_prepend' => ['void', 'brigade'=>'resource', 'bucket'=>'object'], 'stream_context_create' => ['resource', 'options='=>'array', 'params='=>'array'], 'stream_context_get_default' => ['resource', 'options='=>'array'], 'stream_context_get_options' => ['array', 'context'=>'resource'], 'stream_context_get_params' => ['array', 'context'=>'resource'], 'stream_context_set_default' => ['resource', 'options'=>'array'], 'stream_context_set_option' => ['bool', 'context'=>'', 'wrappername'=>'string', 'optionname'=>'string', 'value'=>''], 'stream_context_set_option\'1' => ['bool', 'context'=>'', 'options'=>'array'], 'stream_context_set_params' => ['bool', 'context'=>'resource', 'options'=>'array'], 'stream_copy_to_stream' => ['int|false', 'source'=>'resource', 'dest'=>'resource', 'maxlen='=>'int', 'pos='=>'int'], 'stream_encoding' => ['bool', 'stream'=>'resource', 'encoding='=>'string'], 'stream_filter_append' => ['resource|false', 'stream'=>'resource', 'filtername'=>'string', 'read_write='=>'int', 'filterparams='=>'mixed'], 'stream_filter_prepend' => ['resource|false', 'stream'=>'resource', 'filtername'=>'string', 'read_write='=>'int', 'filterparams='=>'mixed'], 'stream_filter_register' => ['bool', 'filtername'=>'string', 'classname'=>'string'], 'stream_filter_remove' => ['bool', 'stream_filter'=>'resource'], 'stream_get_contents' => ['string|false', 'source'=>'resource', 'maxlen='=>'int', 'offset='=>'int'], 'stream_get_filters' => ['array'], 'stream_get_line' => ['string|false', 'stream'=>'resource', 'maxlen'=>'int', 'ending='=>'string'], 'stream_get_meta_data' => ['array{timed_out:bool,blocked:bool,eof:bool,unread_bytes:int,stream_type:string,wrapper_type:string,wrapper_data:mixed,mode:string,seekable:bool,uri:string,mediatype:string}', 'fp'=>'resource'], 'stream_get_transports' => ['list'], 'stream_get_wrappers' => ['list'], 'stream_is_local' => ['bool', 'stream'=>'resource|string'], 'stream_isatty' => ['bool', 'stream'=>'resource'], 'stream_notification_callback' => ['callback', 'notification_code'=>'int', 'severity'=>'int', 'message'=>'string', 'message_code'=>'int', 'bytes_transferred'=>'int', 'bytes_max'=>'int'], 'stream_register_wrapper' => ['bool', 'protocol'=>'string', 'classname'=>'string', 'flags='=>'int'], 'stream_resolve_include_path' => ['string|false', 'filename'=>'string'], 'stream_select' => ['int|false', '&rw_read_streams'=>'resource[]', '&rw_write_streams'=>'?resource[]', '&rw_except_streams'=>'?resource[]', 'tv_sec'=>'?int', 'tv_usec='=>'?int'], 'stream_set_blocking' => ['bool', 'socket'=>'resource', 'mode'=>'bool'], 'stream_set_chunk_size' => ['int|false', 'fp'=>'resource', 'chunk_size'=>'int'], 'stream_set_read_buffer' => ['int', 'fp'=>'resource', 'buffer'=>'int'], 'stream_set_timeout' => ['bool', 'stream'=>'resource', 'seconds'=>'int', 'microseconds='=>'int'], 'stream_set_write_buffer' => ['int', 'fp'=>'resource', 'buffer'=>'int'], 'stream_socket_accept' => ['resource|false', 'serverstream'=>'resource', 'timeout='=>'float', '&w_peername='=>'string'], 'stream_socket_client' => ['resource|false', 'remoteaddress'=>'string', '&w_errcode='=>'int', '&w_errstring='=>'string', 'timeout='=>'float', 'flags='=>'int', 'context='=>'resource'], 'stream_socket_enable_crypto' => ['int|bool', 'stream'=>'resource', 'enable'=>'bool', 'cryptokind='=>'int', 'sessionstream='=>'resource'], 'stream_socket_get_name' => ['string', 'stream'=>'resource', 'want_peer'=>'bool'], 'stream_socket_pair' => ['resource[]|false', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int'], 'stream_socket_recvfrom' => ['string', 'stream'=>'resource', 'amount'=>'int', 'flags='=>'int', '&w_remote_addr='=>'string'], 'stream_socket_sendto' => ['int', 'stream'=>'resource', 'data'=>'string', 'flags='=>'int', 'target_addr='=>'string'], 'stream_socket_server' => ['resource|false', 'localaddress'=>'string', '&w_errcode='=>'int', '&w_errstring='=>'string', 'flags='=>'int', 'context='=>'resource'], 'stream_socket_shutdown' => ['bool', 'stream'=>'resource', 'how'=>'int'], 'stream_supports_lock' => ['bool', 'stream'=>'resource'], 'stream_wrapper_register' => ['bool', 'protocol'=>'string', 'classname'=>'string', 'flags='=>'int'], 'stream_wrapper_restore' => ['bool', 'protocol'=>'string'], 'stream_wrapper_unregister' => ['bool', 'protocol'=>'string'], 'streamWrapper::__construct' => ['void'], 'streamWrapper::__destruct' => ['void'], 'streamWrapper::dir_closedir' => ['bool'], 'streamWrapper::dir_opendir' => ['bool', 'path'=>'string', 'options'=>'int'], 'streamWrapper::dir_readdir' => ['string'], 'streamWrapper::dir_rewinddir' => ['bool'], 'streamWrapper::mkdir' => ['bool', 'path'=>'string', 'mode'=>'int', 'options'=>'int'], 'streamWrapper::rename' => ['bool', 'path_from'=>'string', 'path_to'=>'string'], 'streamWrapper::rmdir' => ['bool', 'path'=>'string', 'options'=>'int'], 'streamWrapper::stream_cast' => ['resource', 'cast_as'=>'int'], 'streamWrapper::stream_close' => ['void'], 'streamWrapper::stream_eof' => ['bool'], 'streamWrapper::stream_flush' => ['bool'], 'streamWrapper::stream_lock' => ['bool', 'operation'=>'mode'], 'streamWrapper::stream_metadata' => ['bool', 'path'=>'string', 'option'=>'int', 'value'=>'mixed'], 'streamWrapper::stream_open' => ['bool', 'path'=>'string', 'mode'=>'string', 'options'=>'int', 'opened_path'=>'string'], 'streamWrapper::stream_read' => ['string', 'count'=>'int'], 'streamWrapper::stream_seek' => ['bool', 'offset'=>'int', 'whence'=>'int'], 'streamWrapper::stream_set_option' => ['bool', 'option'=>'int', 'arg1'=>'int', 'arg2'=>'int'], 'streamWrapper::stream_stat' => ['array'], 'streamWrapper::stream_tell' => ['int'], 'streamWrapper::stream_truncate' => ['bool', 'new_size'=>'int'], 'streamWrapper::stream_write' => ['int', 'data'=>'string'], 'streamWrapper::unlink' => ['bool', 'path'=>'string'], 'streamWrapper::url_stat' => ['array', 'path'=>'string', 'flags'=>'int'], 'strftime' => ['string', 'format'=>'string', 'timestamp='=>'int'], 'strip_tags' => ['string', 'string'=>'string', 'allowable_tags='=>'string'], 'stripcslashes' => ['string', 'string'=>'string'], 'stripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'stripslashes' => ['string', 'string'=>'string'], 'stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'mixed', 'before_needle='=>'bool'], 'strlen' => ['int', 'string'=>'string'], 'strnatcasecmp' => ['int', 's1'=>'string', 's2'=>'string'], 'strnatcmp' => ['int', 's1'=>'string', 's2'=>'string'], 'strncasecmp' => ['int', 'string1'=>'string', 'string2'=>'string', 'length'=>'int'], 'strncmp' => ['int', 'string1'=>'string', 'string2'=>'string', 'length'=>'int'], 'strpbrk' => ['string|false', 'haystack'=>'string', 'char_list'=>'string'], 'strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strptime' => ['array|false', 'datestr'=>'string', 'format'=>'string'], 'strrchr' => ['string|false', 'haystack'=>'string', 'needle'=>'mixed'], 'strrev' => ['string', 'string'=>'string'], 'strripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strspn' => ['int', 'string'=>'string', 'mask'=>'string', 'start='=>'int', 'length='=>'int'], 'strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'mixed', 'before_needle='=>'bool'], 'strtok' => ['string|false', 'string'=>'string', 'token'=>'string'], 'strtok\'1' => ['string|false', 'token'=>'string'], 'strtolower' => ['string', 'string'=>'string'], 'strtotime' => ['int|false', 'time'=>'string', 'now='=>'int'], 'strtoupper' => ['string', 'string'=>'string'], 'strtr' => ['string', 'string'=>'string', 'from'=>'string', 'to'=>'string'], 'strtr\'1' => ['string', 'string'=>'string', 'replace_pairs'=>'array'], 'strval' => ['string', 'value'=>'mixed'], 'styleObj::__construct' => ['void', 'label'=>'labelObj', 'style'=>'styleObj'], 'styleObj::convertToString' => ['string'], 'styleObj::free' => ['void'], 'styleObj::getBinding' => ['string', 'stylebinding'=>'mixed'], 'styleObj::getGeomTransform' => ['string'], 'styleObj::ms_newStyleObj' => ['styleObj', 'class'=>'classObj', 'style'=>'styleObj'], 'styleObj::removeBinding' => ['int', 'stylebinding'=>'mixed'], 'styleObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'styleObj::setBinding' => ['int', 'stylebinding'=>'mixed', 'value'=>'string'], 'styleObj::setGeomTransform' => ['int', 'value'=>'string'], 'styleObj::updateFromString' => ['int', 'snippet'=>'string'], 'substr' => ['string|false', 'string'=>'string', 'start'=>'int', 'length='=>'int'], 'substr_compare' => ['int|false', 'main_str'=>'string', 'string'=>'string', 'offset'=>'int', 'length='=>'int', 'case_sensitivity='=>'bool'], 'substr_count' => ['int', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'length='=>'int'], 'substr_replace' => ['string|string[]', 'string'=>'string|string[]', 'repl'=>'mixed', 'start'=>'mixed', 'length='=>'mixed'], 'suhosin_encrypt_cookie' => ['string|false', 'name'=>'string', 'value'=>'string'], 'suhosin_get_raw_cookies' => ['array'], 'SVM::__construct' => ['void'], 'svm::crossvalidate' => ['float', 'problem'=>'array', 'number_of_folds'=>'int'], 'SVM::getOptions' => ['array'], 'SVM::setOptions' => ['bool', 'params'=>'array'], 'svm::train' => ['SVMModel', 'problem'=>'array', 'weights='=>'array'], 'SVMModel::__construct' => ['void', 'filename='=>'string'], 'SVMModel::checkProbabilityModel' => ['bool'], 'SVMModel::getLabels' => ['array'], 'SVMModel::getNrClass' => ['int'], 'SVMModel::getSvmType' => ['int'], 'SVMModel::getSvrProbability' => ['float'], 'SVMModel::load' => ['bool', 'filename'=>'string'], 'SVMModel::predict' => ['float', 'data'=>'array'], 'SVMModel::predict_probability' => ['float', 'data'=>'array'], 'SVMModel::save' => ['bool', 'filename'=>'string'], 'svn_add' => ['bool', 'path'=>'string', 'recursive='=>'bool', 'force='=>'bool'], 'svn_auth_get_parameter' => ['?string', 'key'=>'string'], 'svn_auth_set_parameter' => ['void', 'key'=>'string', 'value'=>'string'], 'svn_blame' => ['array', 'repository_url'=>'string', 'revision_no='=>'int'], 'svn_cat' => ['string', 'repos_url'=>'string', 'revision_no='=>'int'], 'svn_checkout' => ['bool', 'repos'=>'string', 'targetpath'=>'string', 'revision='=>'int', 'flags='=>'int'], 'svn_cleanup' => ['bool', 'workingdir'=>'string'], 'svn_client_version' => ['string'], 'svn_commit' => ['array', 'log'=>'string', 'targets'=>'array', 'dontrecurse='=>'bool'], 'svn_delete' => ['bool', 'path'=>'string', 'force='=>'bool'], 'svn_diff' => ['array', 'path1'=>'string', 'rev1'=>'int', 'path2'=>'string', 'rev2'=>'int'], 'svn_export' => ['bool', 'frompath'=>'string', 'topath'=>'string', 'working_copy='=>'bool', 'revision_no='=>'int'], 'svn_fs_abort_txn' => ['bool', 'txn'=>'resource'], 'svn_fs_apply_text' => ['resource', 'root'=>'resource', 'path'=>'string'], 'svn_fs_begin_txn2' => ['resource', 'repos'=>'resource', 'rev'=>'int'], 'svn_fs_change_node_prop' => ['bool', 'root'=>'resource', 'path'=>'string', 'name'=>'string', 'value'=>'string'], 'svn_fs_check_path' => ['int', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_contents_changed' => ['bool', 'root1'=>'resource', 'path1'=>'string', 'root2'=>'resource', 'path2'=>'string'], 'svn_fs_copy' => ['bool', 'from_root'=>'resource', 'from_path'=>'string', 'to_root'=>'resource', 'to_path'=>'string'], 'svn_fs_delete' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_dir_entries' => ['array', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_file_contents' => ['resource', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_file_length' => ['int', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_is_dir' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_is_file' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_make_dir' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_make_file' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_node_created_rev' => ['int', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_node_prop' => ['string', 'fsroot'=>'resource', 'path'=>'string', 'propname'=>'string'], 'svn_fs_props_changed' => ['bool', 'root1'=>'resource', 'path1'=>'string', 'root2'=>'resource', 'path2'=>'string'], 'svn_fs_revision_prop' => ['string', 'fs'=>'resource', 'revnum'=>'int', 'propname'=>'string'], 'svn_fs_revision_root' => ['resource', 'fs'=>'resource', 'revnum'=>'int'], 'svn_fs_txn_root' => ['resource', 'txn'=>'resource'], 'svn_fs_youngest_rev' => ['int', 'fs'=>'resource'], 'svn_import' => ['bool', 'path'=>'string', 'url'=>'string', 'nonrecursive'=>'bool'], 'svn_log' => ['array', 'repos_url'=>'string', 'start_revision='=>'int', 'end_revision='=>'int', 'limit='=>'int', 'flags='=>'int'], 'svn_ls' => ['array', 'repos_url'=>'string', 'revision_no='=>'int', 'recurse='=>'bool', 'peg='=>'bool'], 'svn_mkdir' => ['bool', 'path'=>'string', 'log_message='=>'string'], 'svn_move' => ['mixed', 'src_path'=>'string', 'dst_path'=>'string', 'force='=>'bool'], 'svn_propget' => ['mixed', 'path'=>'string', 'property_name'=>'string', 'recurse='=>'bool', 'revision'=>'int'], 'svn_proplist' => ['mixed', 'path'=>'string', 'recurse='=>'bool', 'revision'=>'int'], 'svn_repos_create' => ['resource', 'path'=>'string', 'config='=>'array', 'fsconfig='=>'array'], 'svn_repos_fs' => ['resource', 'repos'=>'resource'], 'svn_repos_fs_begin_txn_for_commit' => ['resource', 'repos'=>'resource', 'rev'=>'int', 'author'=>'string', 'log_msg'=>'string'], 'svn_repos_fs_commit_txn' => ['int', 'txn'=>'resource'], 'svn_repos_hotcopy' => ['bool', 'repospath'=>'string', 'destpath'=>'string', 'cleanlogs'=>'bool'], 'svn_repos_open' => ['resource', 'path'=>'string'], 'svn_repos_recover' => ['bool', 'path'=>'string'], 'svn_revert' => ['bool', 'path'=>'string', 'recursive='=>'bool'], 'svn_status' => ['array', 'path'=>'string', 'flags='=>'int'], 'svn_update' => ['int|false', 'path'=>'string', 'revno='=>'int', 'recurse='=>'bool'], 'swf_actiongeturl' => ['', 'url'=>'string', 'target'=>'string'], 'swf_actiongotoframe' => ['', 'framenumber'=>'int'], 'swf_actiongotolabel' => ['', 'label'=>'string'], 'swf_actionnextframe' => [''], 'swf_actionplay' => [''], 'swf_actionprevframe' => [''], 'swf_actionsettarget' => ['', 'target'=>'string'], 'swf_actionstop' => [''], 'swf_actiontogglequality' => [''], 'swf_actionwaitforframe' => ['', 'framenumber'=>'int', 'skipcount'=>'int'], 'swf_addbuttonrecord' => ['', 'states'=>'int', 'shapeid'=>'int', 'depth'=>'int'], 'swf_addcolor' => ['', 'r'=>'float', 'g'=>'float', 'b'=>'float', 'a'=>'float'], 'swf_closefile' => ['', 'return_file='=>'int'], 'swf_definebitmap' => ['', 'objid'=>'int', 'image_name'=>'string'], 'swf_definefont' => ['', 'fontid'=>'int', 'fontname'=>'string'], 'swf_defineline' => ['', 'objid'=>'int', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'width'=>'float'], 'swf_definepoly' => ['', 'objid'=>'int', 'coords'=>'array', 'npoints'=>'int', 'width'=>'float'], 'swf_definerect' => ['', 'objid'=>'int', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'width'=>'float'], 'swf_definetext' => ['', 'objid'=>'int', 'string'=>'string', 'docenter'=>'int'], 'swf_endbutton' => [''], 'swf_enddoaction' => [''], 'swf_endshape' => [''], 'swf_endsymbol' => [''], 'swf_fontsize' => ['', 'size'=>'float'], 'swf_fontslant' => ['', 'slant'=>'float'], 'swf_fonttracking' => ['', 'tracking'=>'float'], 'swf_getbitmapinfo' => ['array', 'bitmapid'=>'int'], 'swf_getfontinfo' => ['array'], 'swf_getframe' => ['int'], 'swf_labelframe' => ['', 'name'=>'string'], 'swf_lookat' => ['', 'view_x'=>'float', 'view_y'=>'float', 'view_z'=>'float', 'reference_x'=>'float', 'reference_y'=>'float', 'reference_z'=>'float', 'twist'=>'float'], 'swf_modifyobject' => ['', 'depth'=>'int', 'how'=>'int'], 'swf_mulcolor' => ['', 'r'=>'float', 'g'=>'float', 'b'=>'float', 'a'=>'float'], 'swf_nextid' => ['int'], 'swf_oncondition' => ['', 'transition'=>'int'], 'swf_openfile' => ['', 'filename'=>'string', 'width'=>'float', 'height'=>'float', 'framerate'=>'float', 'r'=>'float', 'g'=>'float', 'b'=>'float'], 'swf_ortho' => ['', 'xmin'=>'float', 'xmax'=>'float', 'ymin'=>'float', 'ymax'=>'float', 'zmin'=>'float', 'zmax'=>'float'], 'swf_ortho2' => ['', 'xmin'=>'float', 'xmax'=>'float', 'ymin'=>'float', 'ymax'=>'float'], 'swf_perspective' => ['', 'fovy'=>'float', 'aspect'=>'float', 'near'=>'float', 'far'=>'float'], 'swf_placeobject' => ['', 'objid'=>'int', 'depth'=>'int'], 'swf_polarview' => ['', 'dist'=>'float', 'azimuth'=>'float', 'incidence'=>'float', 'twist'=>'float'], 'swf_popmatrix' => [''], 'swf_posround' => ['', 'round'=>'int'], 'swf_pushmatrix' => [''], 'swf_removeobject' => ['', 'depth'=>'int'], 'swf_rotate' => ['', 'angle'=>'float', 'axis'=>'string'], 'swf_scale' => ['', 'x'=>'float', 'y'=>'float', 'z'=>'float'], 'swf_setfont' => ['', 'fontid'=>'int'], 'swf_setframe' => ['', 'framenumber'=>'int'], 'swf_shapearc' => ['', 'x'=>'float', 'y'=>'float', 'r'=>'float', 'ang1'=>'float', 'ang2'=>'float'], 'swf_shapecurveto' => ['', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float'], 'swf_shapecurveto3' => ['', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'swf_shapefillbitmapclip' => ['', 'bitmapid'=>'int'], 'swf_shapefillbitmaptile' => ['', 'bitmapid'=>'int'], 'swf_shapefilloff' => [''], 'swf_shapefillsolid' => ['', 'r'=>'float', 'g'=>'float', 'b'=>'float', 'a'=>'float'], 'swf_shapelinesolid' => ['', 'r'=>'float', 'g'=>'float', 'b'=>'float', 'a'=>'float', 'width'=>'float'], 'swf_shapelineto' => ['', 'x'=>'float', 'y'=>'float'], 'swf_shapemoveto' => ['', 'x'=>'float', 'y'=>'float'], 'swf_showframe' => [''], 'swf_startbutton' => ['', 'objid'=>'int', 'type'=>'int'], 'swf_startdoaction' => [''], 'swf_startshape' => ['', 'objid'=>'int'], 'swf_startsymbol' => ['', 'objid'=>'int'], 'swf_textwidth' => ['float', 'string'=>'string'], 'swf_translate' => ['', 'x'=>'float', 'y'=>'float', 'z'=>'float'], 'swf_viewport' => ['', 'xmin'=>'float', 'xmax'=>'float', 'ymin'=>'float', 'ymax'=>'float'], 'SWFAction::__construct' => ['void', 'script'=>'string'], 'SWFBitmap::__construct' => ['void', 'file'=>'', 'alphafile='=>''], 'SWFBitmap::getHeight' => ['float'], 'SWFBitmap::getWidth' => ['float'], 'SWFButton::__construct' => ['void'], 'SWFButton::addAction' => ['void', 'action'=>'swfaction', 'flags'=>'int'], 'SWFButton::addASound' => ['SWFSoundInstance', 'sound'=>'swfsound', 'flags'=>'int'], 'SWFButton::addShape' => ['void', 'shape'=>'swfshape', 'flags'=>'int'], 'SWFButton::setAction' => ['void', 'action'=>'swfaction'], 'SWFButton::setDown' => ['void', 'shape'=>'swfshape'], 'SWFButton::setHit' => ['void', 'shape'=>'swfshape'], 'SWFButton::setMenu' => ['void', 'flag'=>'int'], 'SWFButton::setOver' => ['void', 'shape'=>'swfshape'], 'SWFButton::setUp' => ['void', 'shape'=>'swfshape'], 'SWFDisplayItem::addAction' => ['void', 'action'=>'swfaction', 'flags'=>'int'], 'SWFDisplayItem::addColor' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFDisplayItem::endMask' => ['void'], 'SWFDisplayItem::getRot' => ['float'], 'SWFDisplayItem::getX' => ['float'], 'SWFDisplayItem::getXScale' => ['float'], 'SWFDisplayItem::getXSkew' => ['float'], 'SWFDisplayItem::getY' => ['float'], 'SWFDisplayItem::getYScale' => ['float'], 'SWFDisplayItem::getYSkew' => ['float'], 'SWFDisplayItem::move' => ['void', 'dx'=>'float', 'dy'=>'float'], 'SWFDisplayItem::moveTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFDisplayItem::multColor' => ['void', 'red'=>'float', 'green'=>'float', 'blue'=>'float', 'a='=>'float'], 'SWFDisplayItem::remove' => ['void'], 'SWFDisplayItem::rotate' => ['void', 'angle'=>'float'], 'SWFDisplayItem::rotateTo' => ['void', 'angle'=>'float'], 'SWFDisplayItem::scale' => ['void', 'dx'=>'float', 'dy'=>'float'], 'SWFDisplayItem::scaleTo' => ['void', 'x'=>'float', 'y='=>'float'], 'SWFDisplayItem::setDepth' => ['void', 'depth'=>'int'], 'SWFDisplayItem::setMaskLevel' => ['void', 'level'=>'int'], 'SWFDisplayItem::setMatrix' => ['void', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'x'=>'float', 'y'=>'float'], 'SWFDisplayItem::setName' => ['void', 'name'=>'string'], 'SWFDisplayItem::setRatio' => ['void', 'ratio'=>'float'], 'SWFDisplayItem::skewX' => ['void', 'ddegrees'=>'float'], 'SWFDisplayItem::skewXTo' => ['void', 'degrees'=>'float'], 'SWFDisplayItem::skewY' => ['void', 'ddegrees'=>'float'], 'SWFDisplayItem::skewYTo' => ['void', 'degrees'=>'float'], 'SWFFill::moveTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFFill::rotateTo' => ['void', 'angle'=>'float'], 'SWFFill::scaleTo' => ['void', 'x'=>'float', 'y='=>'float'], 'SWFFill::skewXTo' => ['void', 'x'=>'float'], 'SWFFill::skewYTo' => ['void', 'y'=>'float'], 'SWFFont::__construct' => ['void', 'filename'=>'string'], 'SWFFont::getAscent' => ['float'], 'SWFFont::getDescent' => ['float'], 'SWFFont::getLeading' => ['float'], 'SWFFont::getShape' => ['string', 'code'=>'int'], 'SWFFont::getUTF8Width' => ['float', 'string'=>'string'], 'SWFFont::getWidth' => ['float', 'string'=>'string'], 'SWFFontChar::addChars' => ['void', 'char'=>'string'], 'SWFFontChar::addUTF8Chars' => ['void', 'char'=>'string'], 'SWFGradient::__construct' => ['void'], 'SWFGradient::addEntry' => ['void', 'ratio'=>'float', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha='=>'int'], 'SWFMorph::__construct' => ['void'], 'SWFMorph::getShape1' => ['SWFShape'], 'SWFMorph::getShape2' => ['SWFShape'], 'SWFMovie::__construct' => ['void', 'version='=>'int'], 'SWFMovie::add' => ['mixed', 'instance'=>'object'], 'SWFMovie::addExport' => ['void', 'char'=>'swfcharacter', 'name'=>'string'], 'SWFMovie::addFont' => ['mixed', 'font'=>'swffont'], 'SWFMovie::importChar' => ['SWFSprite', 'libswf'=>'string', 'name'=>'string'], 'SWFMovie::importFont' => ['SWFFontChar', 'libswf'=>'string', 'name'=>'string'], 'SWFMovie::labelFrame' => ['void', 'label'=>'string'], 'SWFMovie::namedAnchor' => [''], 'SWFMovie::nextFrame' => ['void'], 'SWFMovie::output' => ['int', 'compression='=>'int'], 'SWFMovie::protect' => [''], 'SWFMovie::remove' => ['void', 'instance'=>'object'], 'SWFMovie::save' => ['int', 'filename'=>'string', 'compression='=>'int'], 'SWFMovie::saveToFile' => ['int', 'x'=>'resource', 'compression='=>'int'], 'SWFMovie::setbackground' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'SWFMovie::setDimension' => ['void', 'width'=>'float', 'height'=>'float'], 'SWFMovie::setFrames' => ['void', 'number'=>'int'], 'SWFMovie::setRate' => ['void', 'rate'=>'float'], 'SWFMovie::startSound' => ['SWFSoundInstance', 'sound'=>'swfsound'], 'SWFMovie::stopSound' => ['void', 'sound'=>'swfsound'], 'SWFMovie::streamMP3' => ['int', 'mp3file'=>'mixed', 'skip='=>'float'], 'SWFMovie::writeExports' => ['void'], 'SWFPrebuiltClip::__construct' => ['void', 'file'=>''], 'SWFShape::__construct' => ['void'], 'SWFShape::addFill' => ['SWFFill', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha='=>'int', 'bitmap='=>'swfbitmap', 'flags='=>'int', 'gradient='=>'swfgradient'], 'SWFShape::addFill\'1' => ['SWFFill', 'bitmap'=>'SWFBitmap', 'flags='=>'int'], 'SWFShape::addFill\'2' => ['SWFFill', 'gradient'=>'SWFGradient', 'flags='=>'int'], 'SWFShape::drawArc' => ['void', 'r'=>'float', 'startangle'=>'float', 'endangle'=>'float'], 'SWFShape::drawCircle' => ['void', 'r'=>'float'], 'SWFShape::drawCubic' => ['int', 'bx'=>'float', 'by'=>'float', 'cx'=>'float', 'cy'=>'float', 'dx'=>'float', 'dy'=>'float'], 'SWFShape::drawCubicTo' => ['int', 'bx'=>'float', 'by'=>'float', 'cx'=>'float', 'cy'=>'float', 'dx'=>'float', 'dy'=>'float'], 'SWFShape::drawCurve' => ['int', 'controldx'=>'float', 'controldy'=>'float', 'anchordx'=>'float', 'anchordy'=>'float', 'targetdx='=>'float', 'targetdy='=>'float'], 'SWFShape::drawCurveTo' => ['int', 'controlx'=>'float', 'controly'=>'float', 'anchorx'=>'float', 'anchory'=>'float', 'targetx='=>'float', 'targety='=>'float'], 'SWFShape::drawGlyph' => ['void', 'font'=>'swffont', 'character'=>'string', 'size='=>'int'], 'SWFShape::drawLine' => ['void', 'dx'=>'float', 'dy'=>'float'], 'SWFShape::drawLineTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFShape::movePen' => ['void', 'dx'=>'float', 'dy'=>'float'], 'SWFShape::movePenTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFShape::setLeftFill' => ['', 'fill'=>'swfgradient', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFShape::setLine' => ['', 'shape'=>'swfshape', 'width'=>'int', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFShape::setRightFill' => ['', 'fill'=>'swfgradient', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFSound' => ['SWFSound', 'filename'=>'string', 'flags='=>'int'], 'SWFSound::__construct' => ['void', 'filename'=>'string', 'flags='=>'int'], 'SWFSoundInstance::loopCount' => ['void', 'point'=>'int'], 'SWFSoundInstance::loopInPoint' => ['void', 'point'=>'int'], 'SWFSoundInstance::loopOutPoint' => ['void', 'point'=>'int'], 'SWFSoundInstance::noMultiple' => ['void'], 'SWFSprite::__construct' => ['void'], 'SWFSprite::add' => ['void', 'object'=>'object'], 'SWFSprite::labelFrame' => ['void', 'label'=>'string'], 'SWFSprite::nextFrame' => ['void'], 'SWFSprite::remove' => ['void', 'object'=>'object'], 'SWFSprite::setFrames' => ['void', 'number'=>'int'], 'SWFSprite::startSound' => ['SWFSoundInstance', 'sount'=>'swfsound'], 'SWFSprite::stopSound' => ['void', 'sount'=>'swfsound'], 'SWFText::__construct' => ['void'], 'SWFText::addString' => ['void', 'string'=>'string'], 'SWFText::addUTF8String' => ['void', 'text'=>'string'], 'SWFText::getAscent' => ['float'], 'SWFText::getDescent' => ['float'], 'SWFText::getLeading' => ['float'], 'SWFText::getUTF8Width' => ['float', 'string'=>'string'], 'SWFText::getWidth' => ['float', 'string'=>'string'], 'SWFText::moveTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFText::setColor' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFText::setFont' => ['void', 'font'=>'swffont'], 'SWFText::setHeight' => ['void', 'height'=>'float'], 'SWFText::setSpacing' => ['void', 'spacing'=>'float'], 'SWFTextField::__construct' => ['void', 'flags='=>'int'], 'SWFTextField::addChars' => ['void', 'chars'=>'string'], 'SWFTextField::addString' => ['void', 'string'=>'string'], 'SWFTextField::align' => ['void', 'alignement'=>'int'], 'SWFTextField::setBounds' => ['void', 'width'=>'float', 'height'=>'float'], 'SWFTextField::setColor' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFTextField::setFont' => ['void', 'font'=>'swffont'], 'SWFTextField::setHeight' => ['void', 'height'=>'float'], 'SWFTextField::setIndentation' => ['void', 'width'=>'float'], 'SWFTextField::setLeftMargin' => ['void', 'width'=>'float'], 'SWFTextField::setLineSpacing' => ['void', 'height'=>'float'], 'SWFTextField::setMargins' => ['void', 'left'=>'float', 'right'=>'float'], 'SWFTextField::setName' => ['void', 'name'=>'string'], 'SWFTextField::setPadding' => ['void', 'padding'=>'float'], 'SWFTextField::setRightMargin' => ['void', 'width'=>'float'], 'SWFVideoStream::__construct' => ['void', 'file='=>'string'], 'SWFVideoStream::getNumFrames' => ['int'], 'SWFVideoStream::setDimension' => ['void', 'x'=>'int', 'y'=>'int'], 'Swish::__construct' => ['void', 'index_names'=>'string'], 'Swish::getMetaList' => ['array', 'index_name'=>'string'], 'Swish::getPropertyList' => ['array', 'index_name'=>'string'], 'Swish::prepare' => ['object', 'query='=>'string'], 'Swish::query' => ['object', 'query'=>'string'], 'SwishResult::getMetaList' => ['array'], 'SwishResult::stem' => ['array', 'word'=>'string'], 'SwishResults::getParsedWords' => ['array', 'index_name'=>'string'], 'SwishResults::getRemovedStopwords' => ['array', 'index_name'=>'string'], 'SwishResults::nextResult' => ['object'], 'SwishResults::seekResult' => ['int', 'position'=>'int'], 'SwishSearch::execute' => ['object', 'query='=>'string'], 'SwishSearch::resetLimit' => [''], 'SwishSearch::setLimit' => ['', 'property'=>'string', 'low'=>'string', 'high'=>'string'], 'SwishSearch::setPhraseDelimiter' => ['', 'delimiter'=>'string'], 'SwishSearch::setSort' => ['', 'sort'=>'string'], 'SwishSearch::setStructure' => ['', 'structure'=>'int'], 'swoole\async::dnsLookup' => ['void', 'hostname'=>'string', 'callback'=>'callable'], 'swoole\async::read' => ['bool', 'filename'=>'string', 'callback'=>'callable', 'chunk_size='=>'integer', 'offset='=>'integer'], 'swoole\async::readFile' => ['void', 'filename'=>'string', 'callback'=>'callable'], 'swoole\async::set' => ['void', 'settings'=>'array'], 'swoole\async::write' => ['void', 'filename'=>'string', 'content'=>'string', 'offset='=>'integer', 'callback='=>'callable'], 'swoole\async::writeFile' => ['void', 'filename'=>'string', 'content'=>'string', 'callback='=>'callable', 'flags='=>'string'], 'swoole\atomic::add' => ['integer', 'add_value='=>'integer'], 'swoole\atomic::cmpset' => ['integer', 'cmp_value'=>'integer', 'new_value'=>'integer'], 'swoole\atomic::get' => ['integer'], 'swoole\atomic::set' => ['integer', 'value'=>'integer'], 'swoole\atomic::sub' => ['integer', 'sub_value='=>'integer'], 'swoole\buffer::__destruct' => ['void'], 'swoole\buffer::__toString' => ['string'], 'swoole\buffer::append' => ['integer', 'data'=>'string'], 'swoole\buffer::clear' => ['void'], 'swoole\buffer::expand' => ['integer', 'size'=>'integer'], 'swoole\buffer::read' => ['string', 'offset'=>'integer', 'length'=>'integer'], 'swoole\buffer::recycle' => ['void'], 'swoole\buffer::substr' => ['string', 'offset'=>'integer', 'length='=>'integer', 'remove='=>'bool'], 'swoole\buffer::write' => ['void', 'offset'=>'integer', 'data'=>'string'], 'swoole\channel::__destruct' => ['void'], 'swoole\channel::pop' => ['mixed'], 'swoole\channel::push' => ['bool', 'data'=>'string'], 'swoole\channel::stats' => ['array'], 'swoole\client::__destruct' => ['void'], 'swoole\client::close' => ['bool', 'force='=>'bool'], 'swoole\client::connect' => ['bool', 'host'=>'string', 'port='=>'integer', 'timeout='=>'integer', 'flag='=>'integer'], 'swoole\client::getpeername' => ['array'], 'swoole\client::getsockname' => ['array'], 'swoole\client::isConnected' => ['bool'], 'swoole\client::on' => ['void', 'event'=>'string', 'callback'=>'callable'], 'swoole\client::pause' => ['void'], 'swoole\client::pipe' => ['void', 'socket'=>'string'], 'swoole\client::recv' => ['void', 'size='=>'string', 'flag='=>'string'], 'swoole\client::resume' => ['void'], 'swoole\client::send' => ['integer', 'data'=>'string', 'flag='=>'string'], 'swoole\client::sendfile' => ['bool', 'filename'=>'string', 'offset='=>'int'], 'swoole\client::sendto' => ['bool', 'ip'=>'string', 'port'=>'integer', 'data'=>'string'], 'swoole\client::set' => ['void', 'settings'=>'array'], 'swoole\client::sleep' => ['void'], 'swoole\client::wakeup' => ['void'], 'swoole\connection\iterator::count' => ['int'], 'swoole\connection\iterator::current' => ['Connection'], 'swoole\connection\iterator::key' => ['int'], 'swoole\connection\iterator::next' => ['Connection'], 'swoole\connection\iterator::offsetExists' => ['bool', 'index'=>'int'], 'swoole\connection\iterator::offsetGet' => ['Connection', 'index'=>'string'], 'swoole\connection\iterator::offsetSet' => ['void', 'offset'=>'int', 'connection'=>'mixed'], 'swoole\connection\iterator::offsetUnset' => ['void', 'offset'=>'int'], 'swoole\connection\iterator::rewind' => ['void'], 'swoole\connection\iterator::valid' => ['bool'], 'swoole\coroutine::call_user_func' => ['mixed', 'callback'=>'callable', 'parameter='=>'mixed', '...args='=>'mixed'], 'swoole\coroutine::call_user_func_array' => ['mixed', 'callback'=>'callable', 'param_array'=>'array'], 'swoole\coroutine::cli_wait' => ['ReturnType'], 'swoole\coroutine::create' => ['ReturnType'], 'swoole\coroutine::getuid' => ['ReturnType'], 'swoole\coroutine::resume' => ['ReturnType'], 'swoole\coroutine::suspend' => ['ReturnType'], 'swoole\coroutine\client::__destruct' => ['ReturnType'], 'swoole\coroutine\client::close' => ['ReturnType'], 'swoole\coroutine\client::connect' => ['ReturnType'], 'swoole\coroutine\client::getpeername' => ['ReturnType'], 'swoole\coroutine\client::getsockname' => ['ReturnType'], 'swoole\coroutine\client::isConnected' => ['ReturnType'], 'swoole\coroutine\client::recv' => ['ReturnType'], 'swoole\coroutine\client::send' => ['ReturnType'], 'swoole\coroutine\client::sendfile' => ['ReturnType'], 'swoole\coroutine\client::sendto' => ['ReturnType'], 'swoole\coroutine\client::set' => ['ReturnType'], 'swoole\coroutine\http\client::__destruct' => ['ReturnType'], 'swoole\coroutine\http\client::addFile' => ['ReturnType'], 'swoole\coroutine\http\client::close' => ['ReturnType'], 'swoole\coroutine\http\client::execute' => ['ReturnType'], 'swoole\coroutine\http\client::get' => ['ReturnType'], 'swoole\coroutine\http\client::getDefer' => ['ReturnType'], 'swoole\coroutine\http\client::isConnected' => ['ReturnType'], 'swoole\coroutine\http\client::post' => ['ReturnType'], 'swoole\coroutine\http\client::recv' => ['ReturnType'], 'swoole\coroutine\http\client::set' => ['ReturnType'], 'swoole\coroutine\http\client::setCookies' => ['ReturnType'], 'swoole\coroutine\http\client::setData' => ['ReturnType'], 'swoole\coroutine\http\client::setDefer' => ['ReturnType'], 'swoole\coroutine\http\client::setHeaders' => ['ReturnType'], 'swoole\coroutine\http\client::setMethod' => ['ReturnType'], 'swoole\coroutine\mysql::__destruct' => ['ReturnType'], 'swoole\coroutine\mysql::close' => ['ReturnType'], 'swoole\coroutine\mysql::connect' => ['ReturnType'], 'swoole\coroutine\mysql::getDefer' => ['ReturnType'], 'swoole\coroutine\mysql::query' => ['ReturnType'], 'swoole\coroutine\mysql::recv' => ['ReturnType'], 'swoole\coroutine\mysql::setDefer' => ['ReturnType'], 'swoole\event::add' => ['bool', 'fd'=>'int', 'read_callback'=>'callable', 'write_callback='=>'callable', 'events='=>'string'], 'swoole\event::defer' => ['void', 'callback'=>'mixed'], 'swoole\event::del' => ['bool', 'fd'=>'string'], 'swoole\event::exit' => ['void'], 'swoole\event::set' => ['bool', 'fd'=>'int', 'read_callback='=>'string', 'write_callback='=>'string', 'events='=>'string'], 'swoole\event::wait' => ['void'], 'swoole\event::write' => ['void', 'fd'=>'string', 'data'=>'string'], 'swoole\http\client::__destruct' => ['void'], 'swoole\http\client::addFile' => ['void', 'path'=>'string', 'name'=>'string', 'type='=>'string', 'filename='=>'string', 'offset='=>'string'], 'swoole\http\client::close' => ['void'], 'swoole\http\client::download' => ['void', 'path'=>'string', 'file'=>'string', 'callback'=>'callable', 'offset='=>'integer'], 'swoole\http\client::execute' => ['void', 'path'=>'string', 'callback'=>'string'], 'swoole\http\client::get' => ['void', 'path'=>'string', 'callback'=>'callable'], 'swoole\http\client::isConnected' => ['bool'], 'swoole\http\client::on' => ['void', 'event_name'=>'string', 'callback'=>'callable'], 'swoole\http\client::post' => ['void', 'path'=>'string', 'data'=>'string', 'callback'=>'callable'], 'swoole\http\client::push' => ['void', 'data'=>'string', 'opcode='=>'string', 'finish='=>'string'], 'swoole\http\client::set' => ['void', 'settings'=>'array'], 'swoole\http\client::setCookies' => ['void', 'cookies'=>'array'], 'swoole\http\client::setData' => ['ReturnType', 'data'=>'string'], 'swoole\http\client::setHeaders' => ['void', 'headers'=>'array'], 'swoole\http\client::setMethod' => ['void', 'method'=>'string'], 'swoole\http\client::upgrade' => ['void', 'path'=>'string', 'callback'=>'string'], 'swoole\http\request::__destruct' => ['void'], 'swoole\http\request::rawcontent' => ['string'], 'swoole\http\response::__destruct' => ['void'], 'swoole\http\response::cookie' => ['string', 'name'=>'string', 'value='=>'string', 'expires='=>'string', 'path='=>'string', 'domain='=>'string', 'secure='=>'string', 'httponly='=>'string'], 'swoole\http\response::end' => ['void', 'content='=>'string'], 'swoole\http\response::gzip' => ['ReturnType', 'compress_level='=>'string'], 'swoole\http\response::header' => ['void', 'key'=>'string', 'value'=>'string', 'ucwords='=>'string'], 'swoole\http\response::initHeader' => ['ReturnType'], 'swoole\http\response::rawcookie' => ['ReturnType', 'name'=>'string', 'value='=>'string', 'expires='=>'string', 'path='=>'string', 'domain='=>'string', 'secure='=>'string', 'httponly='=>'string'], 'swoole\http\response::sendfile' => ['ReturnType', 'filename'=>'string', 'offset='=>'int'], 'swoole\http\response::status' => ['ReturnType', 'http_code'=>'string'], 'swoole\http\response::write' => ['void', 'content'=>'string'], 'swoole\http\server::on' => ['void', 'event_name'=>'string', 'callback'=>'callable'], 'swoole\http\server::start' => ['void'], 'swoole\lock::__destruct' => ['void'], 'swoole\lock::lock' => ['void'], 'swoole\lock::lock_read' => ['void'], 'swoole\lock::trylock' => ['void'], 'swoole\lock::trylock_read' => ['void'], 'swoole\lock::unlock' => ['void'], 'swoole\mmap::open' => ['ReturnType', 'filename'=>'string', 'size='=>'string', 'offset='=>'string'], 'swoole\mysql::__destruct' => ['void'], 'swoole\mysql::close' => ['void'], 'swoole\mysql::connect' => ['void', 'server_config'=>'array', 'callback'=>'callable'], 'swoole\mysql::getBuffer' => ['ReturnType'], 'swoole\mysql::on' => ['void', 'event_name'=>'string', 'callback'=>'callable'], 'swoole\mysql::query' => ['ReturnType', 'sql'=>'string', 'callback'=>'callable'], 'swoole\process::__destruct' => ['void'], 'swoole\process::alarm' => ['void', 'interval_usec'=>'integer'], 'swoole\process::close' => ['void'], 'swoole\process::daemon' => ['void', 'nochdir='=>'bool', 'noclose='=>'bool'], 'swoole\process::exec' => ['ReturnType', 'exec_file'=>'string', 'args'=>'string'], 'swoole\process::exit' => ['void', 'exit_code='=>'string'], 'swoole\process::freeQueue' => ['void'], 'swoole\process::kill' => ['void', 'pid'=>'integer', 'signal_no='=>'string'], 'swoole\process::name' => ['void', 'process_name'=>'string'], 'swoole\process::pop' => ['mixed', 'maxsize='=>'integer'], 'swoole\process::push' => ['bool', 'data'=>'string'], 'swoole\process::read' => ['string', 'maxsize='=>'integer'], 'swoole\process::signal' => ['void', 'signal_no'=>'string', 'callback'=>'callable'], 'swoole\process::start' => ['void'], 'swoole\process::statQueue' => ['array'], 'swoole\process::useQueue' => ['bool', 'key'=>'integer', 'mode='=>'integer'], 'swoole\process::wait' => ['array', 'blocking='=>'bool'], 'swoole\process::write' => ['integer', 'data'=>'string'], 'swoole\redis\server::format' => ['ReturnType', 'type'=>'string', 'value='=>'string'], 'swoole\redis\server::setHandler' => ['ReturnType', 'command'=>'string', 'callback'=>'string', 'number_of_string_param='=>'string', 'type_of_array_param='=>'string'], 'swoole\redis\server::start' => ['ReturnType'], 'swoole\serialize::pack' => ['ReturnType', 'data'=>'string', 'is_fast='=>'int'], 'swoole\serialize::unpack' => ['ReturnType', 'data'=>'string', 'args='=>'string'], 'swoole\server::addlistener' => ['void', 'host'=>'string', 'port'=>'integer', 'socket_type'=>'string'], 'swoole\server::addProcess' => ['bool', 'process'=>'swoole_process'], 'swoole\server::after' => ['ReturnType', 'after_time_ms'=>'integer', 'callback'=>'callable', 'param='=>'string'], 'swoole\server::bind' => ['bool', 'fd'=>'integer', 'uid'=>'integer'], 'swoole\server::close' => ['bool', 'fd'=>'integer', 'reset='=>'bool'], 'swoole\server::confirm' => ['bool', 'fd'=>'integer'], 'swoole\server::connection_info' => ['array', 'fd'=>'integer', 'reactor_id='=>'integer'], 'swoole\server::connection_list' => ['array', 'start_fd'=>'integer', 'pagesize='=>'integer'], 'swoole\server::defer' => ['void', 'callback'=>'callable'], 'swoole\server::exist' => ['bool', 'fd'=>'integer'], 'swoole\server::finish' => ['void', 'data'=>'string'], 'swoole\server::getClientInfo' => ['ReturnType', 'fd'=>'integer', 'reactor_id='=>'integer'], 'swoole\server::getClientList' => ['array', 'start_fd'=>'integer', 'pagesize='=>'integer'], 'swoole\server::getLastError' => ['integer'], 'swoole\server::heartbeat' => ['mixed', 'if_close_connection'=>'bool'], 'swoole\server::listen' => ['bool', 'host'=>'string', 'port'=>'integer', 'socket_type'=>'string'], 'swoole\server::on' => ['void', 'event_name'=>'string', 'callback'=>'callable'], 'swoole\server::pause' => ['void', 'fd'=>'integer'], 'swoole\server::protect' => ['void', 'fd'=>'integer', 'is_protected='=>'bool'], 'swoole\server::reload' => ['bool'], 'swoole\server::resume' => ['void', 'fd'=>'integer'], 'swoole\server::send' => ['bool', 'fd'=>'integer', 'data'=>'string', 'reactor_id='=>'integer'], 'swoole\server::sendfile' => ['bool', 'fd'=>'integer', 'filename'=>'string', 'offset='=>'integer'], 'swoole\server::sendMessage' => ['bool', 'worker_id'=>'integer', 'data'=>'string'], 'swoole\server::sendto' => ['bool', 'ip'=>'string', 'port'=>'integer', 'data'=>'string', 'server_socket='=>'string'], 'swoole\server::sendwait' => ['bool', 'fd'=>'integer', 'data'=>'string'], 'swoole\server::set' => ['ReturnType', 'settings'=>'array'], 'swoole\server::shutdown' => ['void'], 'swoole\server::start' => ['void'], 'swoole\server::stats' => ['array'], 'swoole\server::stop' => ['bool', 'worker_id='=>'integer'], 'swoole\server::task' => ['mixed', 'data'=>'string', 'dst_worker_id='=>'integer', 'callback='=>'callable'], 'swoole\server::taskwait' => ['void', 'data'=>'string', 'timeout='=>'float', 'worker_id='=>'integer'], 'swoole\server::taskWaitMulti' => ['void', 'tasks'=>'array', 'timeout_ms='=>'double'], 'swoole\server::tick' => ['void', 'interval_ms'=>'integer', 'callback'=>'callable'], 'swoole\server\port::__destruct' => ['void'], 'swoole\server\port::on' => ['ReturnType', 'event_name'=>'string', 'callback'=>'callable'], 'swoole\server\port::set' => ['void', 'settings'=>'array'], 'swoole\table::column' => ['ReturnType', 'name'=>'string', 'type'=>'string', 'size='=>'integer'], 'swoole\table::count' => ['integer'], 'swoole\table::create' => ['void'], 'swoole\table::current' => ['array'], 'swoole\table::decr' => ['ReturnType', 'key'=>'string', 'column'=>'string', 'decrby='=>'integer'], 'swoole\table::del' => ['void', 'key'=>'string'], 'swoole\table::destroy' => ['void'], 'swoole\table::exist' => ['bool', 'key'=>'string'], 'swoole\table::get' => ['integer', 'row_key'=>'string', 'column_key'=>'string'], 'swoole\table::incr' => ['void', 'key'=>'string', 'column'=>'string', 'incrby='=>'integer'], 'swoole\table::key' => ['string'], 'swoole\table::next' => ['ReturnType'], 'swoole\table::rewind' => ['void'], 'swoole\table::set' => ['VOID', 'key'=>'string', 'value'=>'array'], 'swoole\table::valid' => ['bool'], 'swoole\timer::after' => ['void', 'after_time_ms'=>'int', 'callback'=>'callable'], 'swoole\timer::clear' => ['void', 'timer_id'=>'integer'], 'swoole\timer::exists' => ['bool', 'timer_id'=>'integer'], 'swoole\timer::tick' => ['void', 'interval_ms'=>'integer', 'callback'=>'callable', 'param='=>'string'], 'swoole\websocket\server::exist' => ['bool', 'fd'=>'integer'], 'swoole\websocket\server::on' => ['ReturnType', 'event_name'=>'string', 'callback'=>'callable'], 'swoole\websocket\server::pack' => ['binary', 'data'=>'string', 'opcode='=>'string', 'finish='=>'string', 'mask='=>'string'], 'swoole\websocket\server::push' => ['void', 'fd'=>'string', 'data'=>'string', 'opcode='=>'string', 'finish='=>'string'], 'swoole\websocket\server::unpack' => ['string', 'data'=>'binary'], 'swoole_async_dns_lookup' => ['bool', 'hostname'=>'string', 'callback'=>'callable'], 'swoole_async_read' => ['bool', 'filename'=>'string', 'callback'=>'callable', 'chunk_size='=>'int', 'offset='=>'int'], 'swoole_async_readfile' => ['bool', 'filename'=>'string', 'callback'=>'string'], 'swoole_async_set' => ['void', 'settings'=>'array'], 'swoole_async_write' => ['bool', 'filename'=>'string', 'content'=>'string', 'offset='=>'int', 'callback='=>'callable'], 'swoole_async_writefile' => ['bool', 'filename'=>'string', 'content'=>'string', 'callback='=>'callable', 'flags='=>'int'], 'swoole_client_select' => ['int', 'read_array'=>'array', 'write_array'=>'array', 'error_array'=>'array', 'timeout='=>'float'], 'swoole_cpu_num' => ['int'], 'swoole_errno' => ['int'], 'swoole_event_add' => ['int', 'fd'=>'int', 'read_callback='=>'callable', 'write_callback='=>'callable', 'events='=>'int'], 'swoole_event_defer' => ['bool', 'callback'=>'callable'], 'swoole_event_del' => ['bool', 'fd'=>'int'], 'swoole_event_exit' => ['void'], 'swoole_event_set' => ['bool', 'fd'=>'int', 'read_callback='=>'callable', 'write_callback='=>'callable', 'events='=>'int'], 'swoole_event_wait' => ['void'], 'swoole_event_write' => ['bool', 'fd'=>'int', 'data'=>'string'], 'swoole_get_local_ip' => ['array'], 'swoole_last_error' => ['int'], 'swoole_load_module' => ['mixed', 'filename'=>'string'], 'swoole_select' => ['int', 'read_array'=>'array', 'write_array'=>'array', 'error_array'=>'array', 'timeout='=>'float'], 'swoole_set_process_name' => ['void', 'process_name'=>'string', 'size='=>'int'], 'swoole_strerror' => ['string', 'errno'=>'int', 'error_type='=>'int'], 'swoole_timer_after' => ['int', 'ms'=>'int', 'callback'=>'callable', 'param='=>'mixed'], 'swoole_timer_exists' => ['bool', 'timer_id'=>'int'], 'swoole_timer_tick' => ['int', 'ms'=>'int', 'callback'=>'callable', 'param='=>'mixed'], 'swoole_version' => ['string'], 'symbolObj::__construct' => ['void', 'map'=>'mapObj', 'symbolname'=>'string'], 'symbolObj::free' => ['void'], 'symbolObj::getPatternArray' => ['array'], 'symbolObj::getPointsArray' => ['array'], 'symbolObj::ms_newSymbolObj' => ['int', 'map'=>'mapObj', 'symbolname'=>'string'], 'symbolObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'symbolObj::setImagePath' => ['int', 'filename'=>'string'], 'symbolObj::setPattern' => ['int', 'int'=>'array'], 'symbolObj::setPoints' => ['int', 'double'=>'array'], 'symlink' => ['bool', 'target'=>'string', 'link'=>'string'], 'SyncEvent::__construct' => ['void', 'name='=>'string', 'manual='=>'bool'], 'SyncEvent::fire' => ['bool'], 'SyncEvent::reset' => ['bool'], 'SyncEvent::wait' => ['bool', 'wait='=>'int'], 'SyncMutex::__construct' => ['void', 'name='=>'string'], 'SyncMutex::lock' => ['bool', 'wait='=>'int'], 'SyncMutex::unlock' => ['bool', 'all='=>'bool'], 'SyncReaderWriter::__construct' => ['void', 'name='=>'string', 'autounlock='=>'bool'], 'SyncReaderWriter::readlock' => ['bool', 'wait='=>'int'], 'SyncReaderWriter::readunlock' => ['bool'], 'SyncReaderWriter::writelock' => ['bool', 'wait='=>'int'], 'SyncReaderWriter::writeunlock' => ['bool'], 'SyncSemaphore::__construct' => ['void', 'name='=>'string', 'initialval='=>'int', 'autounlock='=>'bool'], 'SyncSemaphore::lock' => ['bool', 'wait='=>'int'], 'SyncSemaphore::unlock' => ['bool', '&w_prevcount='=>'int'], 'SyncSharedMemory::__construct' => ['void', 'name'=>'string', 'size'=>'int'], 'SyncSharedMemory::first' => ['bool'], 'SyncSharedMemory::read' => ['string', 'start='=>'int', 'length='=>'int'], 'SyncSharedMemory::size' => ['int'], 'SyncSharedMemory::write' => ['int', 'string='=>'string', 'start='=>'int'], 'sys_get_temp_dir' => ['string'], 'sys_getloadavg' => ['array'], 'syslog' => ['bool', 'priority'=>'int', 'message'=>'string'], 'system' => ['string|false', 'command'=>'string', '&w_return_value='=>'int'], 'taint' => ['bool', '&rw_string'=>'string', '&...w_other_strings='=>'string'], 'tan' => ['float', 'number'=>'float'], 'tanh' => ['float', 'number'=>'float'], 'tcpwrap_check' => ['bool', 'daemon'=>'string', 'address'=>'string', 'user='=>'string', 'nodns='=>'bool'], 'tempnam' => ['string|false', 'dir'=>'string', 'prefix'=>'string'], 'textdomain' => ['string', 'domain'=>'string'], 'Thread::__construct' => ['void'], 'Thread::addRef' => ['void'], 'Thread::chunk' => ['array', 'size'=>'int', 'preserve'=>'bool'], 'Thread::count' => ['int'], 'Thread::delRef' => ['void'], 'Thread::detach' => ['void'], 'Thread::extend' => ['bool', 'class'=>'string'], 'Thread::getCreatorId' => ['int'], 'Thread::getCurrentThread' => ['Thread'], 'Thread::getCurrentThreadId' => ['int'], 'Thread::getRefCount' => ['int'], 'Thread::getTerminationInfo' => ['array'], 'Thread::getThreadId' => ['int'], 'Thread::globally' => ['mixed'], 'Thread::isGarbage' => ['bool'], 'Thread::isJoined' => ['bool'], 'Thread::isRunning' => ['bool'], 'Thread::isStarted' => ['bool'], 'Thread::isTerminated' => ['bool'], 'Thread::isWaiting' => ['bool'], 'Thread::join' => ['bool'], 'Thread::kill' => ['void'], 'Thread::lock' => ['bool'], '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::pop' => ['bool'], 'Thread::run' => ['void'], 'Thread::setGarbage' => ['void'], 'Thread::shift' => ['bool'], 'Thread::start' => ['bool', 'options='=>'int'], 'Thread::synchronized' => ['mixed', 'block'=>'Closure', '_='=>'mixed'], 'Thread::unlock' => ['bool'], 'Thread::wait' => ['bool', 'timeout='=>'int'], 'Threaded::__construct' => ['void'], 'Threaded::addRef' => ['void'], 'Threaded::chunk' => ['array', 'size'=>'int', 'preserve'=>'bool'], 'Threaded::count' => ['int'], 'Threaded::delRef' => ['void'], 'Threaded::extend' => ['bool', 'class'=>'string'], 'Threaded::from' => ['Threaded', 'run'=>'Closure', 'construct='=>'Closure', 'args='=>'array'], 'Threaded::getRefCount' => ['int'], 'Threaded::getTerminationInfo' => ['array'], 'Threaded::isGarbage' => ['bool'], 'Threaded::isRunning' => ['bool'], 'Threaded::isTerminated' => ['bool'], 'Threaded::isWaiting' => ['bool'], 'Threaded::lock' => ['bool'], '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::pop' => ['bool'], 'Threaded::run' => ['void'], 'Threaded::setGarbage' => ['void'], 'Threaded::shift' => ['mixed'], 'Threaded::synchronized' => ['mixed', 'block'=>'Closure', '...args='=>'mixed'], 'Threaded::unlock' => ['bool'], 'Threaded::wait' => ['bool', 'timeout='=>'int'], 'Throwable::__toString' => ['string'], 'Throwable::getCode' => ['int|string'], 'Throwable::getFile' => ['string'], 'Throwable::getLine' => ['int'], 'Throwable::getMessage' => ['string'], 'Throwable::getPrevious' => ['?Throwable'], 'Throwable::getTrace' => ['list>'], 'Throwable::getTraceAsString' => ['string'], 'tidy::__construct' => ['void', 'filename='=>'string', 'config='=>'', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy::body' => ['tidyNode'], 'tidy::cleanRepair' => ['bool'], 'tidy::diagnose' => ['bool'], 'tidy::getConfig' => ['array'], 'tidy::getHtmlVer' => ['int'], 'tidy::getOpt' => ['mixed', 'option'=>'string'], 'tidy::getOptDoc' => ['string', 'optname'=>'string'], 'tidy::getRelease' => ['string'], 'tidy::getStatus' => ['int'], 'tidy::head' => ['tidyNode'], 'tidy::html' => ['tidyNode'], 'tidy::htmlver' => ['int'], 'tidy::isXhtml' => ['bool'], 'tidy::isXml' => ['bool'], 'tidy::parseFile' => ['bool', 'filename'=>'string', 'config='=>'', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy::parseString' => ['bool', 'input'=>'string', 'config='=>'', 'encoding='=>'string'], 'tidy::repairFile' => ['string', 'filename'=>'string', 'config='=>'', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy::repairString' => ['string', 'data'=>'string', 'config='=>'', 'encoding='=>'string'], 'tidy::root' => ['tidyNode'], 'tidy_access_count' => ['int', 'object'=>'tidy'], 'tidy_clean_repair' => ['bool', 'object'=>'tidy'], 'tidy_config_count' => ['int', 'object'=>'tidy'], 'tidy_diagnose' => ['bool', 'object'=>'tidy'], 'tidy_error_count' => ['int', 'object'=>'tidy'], 'tidy_get_body' => ['tidyNode', 'object'=>'tidy'], 'tidy_get_config' => ['array', 'object'=>'tidy'], 'tidy_get_error_buffer' => ['string', 'object'=>'tidy'], 'tidy_get_head' => ['tidyNode', 'object'=>'tidy'], 'tidy_get_html' => ['tidyNode', 'object'=>'tidy'], 'tidy_get_html_ver' => ['int', 'object'=>'tidy'], 'tidy_get_opt_doc' => ['string', 'object'=>'tidy', 'optname'=>'string'], 'tidy_get_output' => ['string', 'object'=>'tidy'], 'tidy_get_release' => ['string'], 'tidy_get_root' => ['tidyNode', 'object'=>'tidy'], 'tidy_get_status' => ['int', 'object'=>'tidy'], 'tidy_getopt' => ['mixed', 'option'=>'string', 'object'=>'tidy'], 'tidy_is_xhtml' => ['bool', 'object'=>'tidy'], 'tidy_is_xml' => ['bool', 'object'=>'tidy'], 'tidy_load_config' => ['void', 'filename'=>'string', 'encoding'=>'string'], 'tidy_parse_file' => ['tidy', 'file'=>'string', 'config_options='=>'', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy_parse_string' => ['tidy', 'input'=>'string', 'config_options='=>'', 'encoding='=>'string'], 'tidy_repair_file' => ['string', 'filename'=>'string', 'config_file='=>'', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy_repair_string' => ['string', 'data'=>'string', 'config_file='=>'', 'encoding='=>'string'], 'tidy_reset_config' => ['bool'], 'tidy_save_config' => ['bool', 'filename'=>'string'], 'tidy_set_encoding' => ['bool', 'encoding'=>'string'], 'tidy_setopt' => ['bool', 'option'=>'string', 'value'=>'mixed'], 'tidy_warning_count' => ['int', 'object'=>'tidy'], 'tidyNode::__construct' => ['void'], 'tidyNode::getParent' => ['tidyNode'], 'tidyNode::hasChildren' => ['bool'], 'tidyNode::hasSiblings' => ['bool'], 'tidyNode::isAsp' => ['bool'], 'tidyNode::isComment' => ['bool'], 'tidyNode::isHtml' => ['bool'], 'tidyNode::isJste' => ['bool'], 'tidyNode::isPhp' => ['bool'], 'tidyNode::isText' => ['bool'], 'time' => ['int'], 'time_nanosleep' => ['array{0:int,1:int}|bool', 'seconds'=>'int', 'nanoseconds'=>'int'], 'time_sleep_until' => ['bool', 'timestamp'=>'float'], 'timezone_abbreviations_list' => ['array|false'], 'timezone_identifiers_list' => ['list|false', 'what='=>'int', 'country='=>'?string'], 'timezone_location_get' => ['array|false', 'object'=>'DateTimeZone'], 'timezone_name_from_abbr' => ['string|false', 'abbr'=>'string', 'gmtoffset='=>'int', 'isdst='=>'int'], 'timezone_name_get' => ['string', 'object'=>'DateTimeZone'], 'timezone_offset_get' => ['int|false', 'object'=>'DateTimeZone', 'datetime'=>'DateTimeInterface'], 'timezone_open' => ['DateTimeZone|false', 'timezone'=>'string'], 'timezone_transitions_get' => ['array|false', 'object'=>'DateTimeZone', 'timestamp_begin='=>'int', 'timestamp_end='=>'int'], 'timezone_version_get' => ['string'], 'tmpfile' => ['resource|false'], 'token_get_all' => ['list', 'source'=>'string', 'flags='=>'int'], 'token_name' => ['string', 'type'=>'int'], 'TokyoTyrant::__construct' => ['void', 'host='=>'string', 'port='=>'int', 'options='=>'array'], 'TokyoTyrant::add' => ['int|float', 'key'=>'string', 'increment'=>'float', 'type='=>'int'], 'TokyoTyrant::connect' => ['TokyoTyrant', 'host'=>'string', 'port='=>'int', 'options='=>'array'], 'TokyoTyrant::connectUri' => ['TokyoTyrant', 'uri'=>'string'], 'TokyoTyrant::copy' => ['TokyoTyrant', 'path'=>'string'], 'TokyoTyrant::ext' => ['string', 'name'=>'string', 'options'=>'int', 'key'=>'string', 'value'=>'string'], 'TokyoTyrant::fwmKeys' => ['array', 'prefix'=>'string', 'max_recs'=>'int'], 'TokyoTyrant::get' => ['array', 'keys'=>'mixed'], 'TokyoTyrant::getIterator' => ['TokyoTyrantIterator'], 'TokyoTyrant::num' => ['int'], 'TokyoTyrant::out' => ['string', 'keys'=>'mixed'], 'TokyoTyrant::put' => ['TokyoTyrant', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrant::putCat' => ['TokyoTyrant', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrant::putKeep' => ['TokyoTyrant', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrant::putNr' => ['TokyoTyrant', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrant::putShl' => ['mixed', 'key'=>'string', 'value'=>'string', 'width'=>'int'], 'TokyoTyrant::restore' => ['mixed', 'log_dir'=>'string', 'timestamp'=>'int', 'check_consistency='=>'bool'], 'TokyoTyrant::setMaster' => ['mixed', 'host'=>'string', 'port'=>'int', 'timestamp'=>'int', 'check_consistency='=>'bool'], 'TokyoTyrant::size' => ['int', 'key'=>'string'], 'TokyoTyrant::stat' => ['array'], 'TokyoTyrant::sync' => ['mixed'], 'TokyoTyrant::tune' => ['TokyoTyrant', 'timeout'=>'float', 'options='=>'int'], 'TokyoTyrant::vanish' => ['mixed'], 'TokyoTyrantIterator::__construct' => ['void', 'object'=>'mixed'], 'TokyoTyrantIterator::current' => ['mixed'], 'TokyoTyrantIterator::key' => ['mixed'], 'TokyoTyrantIterator::next' => ['mixed'], 'TokyoTyrantIterator::rewind' => ['void'], 'TokyoTyrantIterator::valid' => ['bool'], 'TokyoTyrantQuery::__construct' => ['void', 'table'=>'TokyoTyrantTable'], 'TokyoTyrantQuery::addCond' => ['mixed', 'name'=>'string', 'op'=>'int', 'expr'=>'string'], 'TokyoTyrantQuery::count' => ['int'], 'TokyoTyrantQuery::current' => ['array'], 'TokyoTyrantQuery::hint' => ['string'], 'TokyoTyrantQuery::key' => ['string'], 'TokyoTyrantQuery::metaSearch' => ['array', 'queries'=>'array', 'type'=>'int'], 'TokyoTyrantQuery::next' => ['array'], 'TokyoTyrantQuery::out' => ['TokyoTyrantQuery'], 'TokyoTyrantQuery::rewind' => ['bool'], 'TokyoTyrantQuery::search' => ['array'], 'TokyoTyrantQuery::setLimit' => ['mixed', 'max='=>'int', 'skip='=>'int'], 'TokyoTyrantQuery::setOrder' => ['mixed', 'name'=>'string', 'type'=>'int'], 'TokyoTyrantQuery::valid' => ['bool'], 'TokyoTyrantTable::add' => ['void', 'key'=>'string', 'increment'=>'mixed', 'type='=>'string'], 'TokyoTyrantTable::genUid' => ['int'], 'TokyoTyrantTable::get' => ['array', 'keys'=>'mixed'], 'TokyoTyrantTable::getIterator' => ['TokyoTyrantIterator'], 'TokyoTyrantTable::getQuery' => ['TokyoTyrantQuery'], 'TokyoTyrantTable::out' => ['void', 'keys'=>'mixed'], 'TokyoTyrantTable::put' => ['int', 'key'=>'string', 'columns'=>'array'], 'TokyoTyrantTable::putCat' => ['void', 'key'=>'string', 'columns'=>'array'], 'TokyoTyrantTable::putKeep' => ['void', 'key'=>'string', 'columns'=>'array'], 'TokyoTyrantTable::putNr' => ['void', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrantTable::putShl' => ['void', 'key'=>'string', 'value'=>'string', 'width'=>'int'], 'TokyoTyrantTable::setIndex' => ['mixed', 'column'=>'string', 'type'=>'int'], 'touch' => ['bool', 'filename'=>'string', 'time='=>'int', 'atime='=>'int'], 'trader_acos' => ['array', 'real'=>'array'], 'trader_ad' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'volume'=>'array'], 'trader_add' => ['array', 'real0'=>'array', 'real1'=>'array'], 'trader_adosc' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'volume'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int'], 'trader_adx' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_adxr' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_apo' => ['array', 'real'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int', 'mAType='=>'int'], 'trader_aroon' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_aroonosc' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_asin' => ['array', 'real'=>'array'], 'trader_atan' => ['array', 'real'=>'array'], 'trader_atr' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_avgprice' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_bbands' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'nbDevUp='=>'float', 'nbDevDn='=>'float', 'mAType='=>'int'], 'trader_beta' => ['array', 'real0'=>'array', 'real1'=>'array', 'timePeriod='=>'int'], 'trader_bop' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cci' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_cdl2crows' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3blackcrows' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3inside' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3linestrike' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3outside' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3starsinsouth' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3whitesoldiers' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlabandonedbaby' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdladvanceblock' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlbelthold' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlbreakaway' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlclosingmarubozu' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlconcealbabyswall' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlcounterattack' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdldarkcloudcover' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdldoji' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdldojistar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdldragonflydoji' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlengulfing' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdleveningdojistar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdleveningstar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlgapsidesidewhite' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlgravestonedoji' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhammer' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhangingman' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlharami' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlharamicross' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhighwave' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhikkake' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhikkakemod' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhomingpigeon' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlidentical3crows' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlinneck' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlinvertedhammer' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlkicking' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlkickingbylength' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlladderbottom' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdllongleggeddoji' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdllongline' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlmarubozu' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlmatchinglow' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlmathold' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlmorningdojistar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlmorningstar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlonneck' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlpiercing' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlrickshawman' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlrisefall3methods' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlseparatinglines' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlshootingstar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlshortline' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlspinningtop' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlstalledpattern' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlsticksandwich' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdltakuri' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdltasukigap' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlthrusting' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdltristar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlunique3river' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlupsidegap2crows' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlxsidegap3methods' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_ceil' => ['array', 'real'=>'array'], 'trader_cmo' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_correl' => ['array', 'real0'=>'array', 'real1'=>'array', 'timePeriod='=>'int'], 'trader_cos' => ['array', 'real'=>'array'], 'trader_cosh' => ['array', 'real'=>'array'], 'trader_dema' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_div' => ['array', 'real0'=>'array', 'real1'=>'array'], 'trader_dx' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_ema' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_errno' => ['int'], 'trader_exp' => ['array', 'real'=>'array'], 'trader_floor' => ['array', 'real'=>'array'], 'trader_get_compat' => ['int'], 'trader_get_unstable_period' => ['int', 'functionId'=>'int'], 'trader_ht_dcperiod' => ['array', 'real'=>'array'], 'trader_ht_dcphase' => ['array', 'real'=>'array'], 'trader_ht_phasor' => ['array', 'real'=>'array'], 'trader_ht_sine' => ['array', 'real'=>'array'], 'trader_ht_trendline' => ['array', 'real'=>'array'], 'trader_ht_trendmode' => ['array', 'real'=>'array'], 'trader_kama' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg_angle' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg_intercept' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg_slope' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_ln' => ['array', 'real'=>'array'], 'trader_log10' => ['array', 'real'=>'array'], 'trader_ma' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'mAType='=>'int'], 'trader_macd' => ['array', 'real'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int', 'signalPeriod='=>'int'], 'trader_macdext' => ['array', 'real'=>'array', 'fastPeriod='=>'int', 'fastMAType='=>'int', 'slowPeriod='=>'int', 'slowMAType='=>'int', 'signalPeriod='=>'int', 'signalMAType='=>'int'], 'trader_macdfix' => ['array', 'real'=>'array', 'signalPeriod='=>'int'], 'trader_mama' => ['array', 'real'=>'array', 'fastLimit='=>'float', 'slowLimit='=>'float'], 'trader_mavp' => ['array', 'real'=>'array', 'periods'=>'array', 'minPeriod='=>'int', 'maxPeriod='=>'int', 'mAType='=>'int'], 'trader_max' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_maxindex' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_medprice' => ['array', 'high'=>'array', 'low'=>'array'], 'trader_mfi' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'volume'=>'array', 'timePeriod='=>'int'], 'trader_midpoint' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_midprice' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_min' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minindex' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minmax' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minmaxindex' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minus_di' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_minus_dm' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_mom' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_mult' => ['array', 'real0'=>'array', 'real1'=>'array'], 'trader_natr' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_obv' => ['array', 'real'=>'array', 'volume'=>'array'], 'trader_plus_di' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_plus_dm' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_ppo' => ['array', 'real'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int', 'mAType='=>'int'], 'trader_roc' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rocp' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rocr' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rocr100' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rsi' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_sar' => ['array', 'high'=>'array', 'low'=>'array', 'acceleration='=>'float', 'maximum='=>'float'], 'trader_sarext' => ['array', 'high'=>'array', 'low'=>'array', 'startValue='=>'float', 'offsetOnReverse='=>'float', 'accelerationInitLong='=>'float', 'accelerationLong='=>'float', 'accelerationMaxLong='=>'float', 'accelerationInitShort='=>'float', 'accelerationShort='=>'float', 'accelerationMaxShort='=>'float'], 'trader_set_compat' => ['void', 'compatId'=>'int'], 'trader_set_unstable_period' => ['void', 'functionId'=>'int', 'timePeriod'=>'int'], 'trader_sin' => ['array', 'real'=>'array'], 'trader_sinh' => ['array', 'real'=>'array'], 'trader_sma' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_sqrt' => ['array', 'real'=>'array'], 'trader_stddev' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'nbDev='=>'float'], 'trader_stoch' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'fastK_Period='=>'int', 'slowK_Period='=>'int', 'slowK_MAType='=>'int', 'slowD_Period='=>'int', 'slowD_MAType='=>'int'], 'trader_stochf' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'fastK_Period='=>'int', 'fastD_Period='=>'int', 'fastD_MAType='=>'int'], 'trader_stochrsi' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'fastK_Period='=>'int', 'fastD_Period='=>'int', 'fastD_MAType='=>'int'], 'trader_sub' => ['array', 'real0'=>'array', 'real1'=>'array'], 'trader_sum' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_t3' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'vFactor='=>'float'], 'trader_tan' => ['array', 'real'=>'array'], 'trader_tanh' => ['array', 'real'=>'array'], 'trader_tema' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_trange' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_trima' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_trix' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_tsf' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_typprice' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_ultosc' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod1='=>'int', 'timePeriod2='=>'int', 'timePeriod3='=>'int'], 'trader_var' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'nbDev='=>'float'], 'trader_wclprice' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_willr' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_wma' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trait_exists' => ['?bool', 'traitname'=>'string', 'autoload='=>'bool'], 'Transliterator::create' => ['?Transliterator', 'id'=>'string', 'direction='=>'int'], 'Transliterator::createFromRules' => ['?Transliterator', 'rules'=>'string', 'direction='=>'int'], 'Transliterator::createInverse' => ['Transliterator'], 'Transliterator::getErrorCode' => ['int'], 'Transliterator::getErrorMessage' => ['string'], 'Transliterator::listIDs' => ['array'], 'Transliterator::transliterate' => ['string|false', 'subject'=>'string', 'start='=>'int', 'end='=>'int'], 'transliterator_create' => ['?Transliterator', 'id'=>'string', 'direction='=>'int'], 'transliterator_create_from_rules' => ['?Transliterator', 'rules'=>'string', 'direction='=>'int'], 'transliterator_create_inverse' => ['Transliterator', 'object'=>'Transliterator'], 'transliterator_get_error_code' => ['int', 'object'=>'Transliterator'], 'transliterator_get_error_message' => ['string', 'object'=>'Transliterator'], 'transliterator_list_ids' => ['array'], 'transliterator_transliterate' => ['string|false', 'object'=>'Transliterator|string', 'subject'=>'string', 'start='=>'int', 'end='=>'int'], 'trigger_error' => ['bool', 'message'=>'string', 'error_type='=>'256|512|1024|16384'], 'trim' => ['string', 'string'=>'string', 'character_mask='=>'string'], 'TypeError::__clone' => ['void'], 'TypeError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?TypeError'], 'TypeError::__toString' => ['string'], 'TypeError::getCode' => ['int'], 'TypeError::getFile' => ['string'], 'TypeError::getLine' => ['int'], 'TypeError::getMessage' => ['string'], 'TypeError::getPrevious' => ['Throwable|TypeError|null'], 'TypeError::getTrace' => ['list>'], 'TypeError::getTraceAsString' => ['string'], 'uasort' => ['bool', '&rw_array'=>'array', 'cmp_function'=>'callable(mixed,mixed):int'], 'ucfirst' => ['string', 'string'=>'string'], 'UConverter::__construct' => ['void', 'destination_encoding='=>'string', 'source_encoding='=>'string'], 'UConverter::convert' => ['string', 'string'=>'string', 'reverse='=>'bool'], 'UConverter::fromUCallback' => ['mixed', 'reason'=>'int', 'source'=>'string', 'codePoint'=>'string', '&w_error'=>'int'], 'UConverter::getAliases' => ['array', 'name'=>'string'], 'UConverter::getAvailable' => ['array'], 'UConverter::getDestinationEncoding' => ['string'], 'UConverter::getDestinationType' => ['int'], 'UConverter::getErrorCode' => ['int'], 'UConverter::getErrorMessage' => ['string'], 'UConverter::getSourceEncoding' => ['string'], 'UConverter::getSourceType' => ['int'], 'UConverter::getStandards' => ['array'], 'UConverter::getSubstChars' => ['string'], 'UConverter::reasonText' => ['string', 'reason='=>'int'], 'UConverter::setDestinationEncoding' => ['bool', 'encoding'=>'string'], 'UConverter::setSourceEncoding' => ['bool', 'encoding'=>'string'], 'UConverter::setSubstChars' => ['bool', 'chars'=>'string'], 'UConverter::toUCallback' => ['mixed', 'reason'=>'int', 'source'=>'string', 'codeUnits'=>'string', '&w_error'=>'int'], 'UConverter::transcode' => ['string', 'string'=>'string', 'toEncoding'=>'string', 'fromEncoding'=>'string', 'options='=>'?array'], 'ucwords' => ['string', 'string'=>'string', 'delimiters='=>'string'], 'udm_add_search_limit' => ['bool', 'agent'=>'resource', 'var'=>'int', 'value'=>'string'], 'udm_alloc_agent' => ['resource', 'dbaddr'=>'string', 'dbmode='=>'string'], 'udm_alloc_agent_array' => ['resource', 'databases'=>'array'], 'udm_api_version' => ['int'], 'udm_cat_list' => ['array', 'agent'=>'resource', 'category'=>'string'], 'udm_cat_path' => ['array', 'agent'=>'resource', 'category'=>'string'], 'udm_check_charset' => ['bool', 'agent'=>'resource', 'charset'=>'string'], 'udm_check_stored' => ['int', 'agent'=>'', 'link'=>'int', 'doc_id'=>'string'], 'udm_clear_search_limits' => ['bool', 'agent'=>'resource'], 'udm_close_stored' => ['int', 'agent'=>'', 'link'=>'int'], 'udm_crc32' => ['int', 'agent'=>'resource', 'string'=>'string'], 'udm_errno' => ['int', 'agent'=>'resource'], 'udm_error' => ['string', 'agent'=>'resource'], 'udm_find' => ['resource', 'agent'=>'resource', 'query'=>'string'], 'udm_free_agent' => ['int', 'agent'=>'resource'], 'udm_free_ispell_data' => ['bool', 'agent'=>'int'], 'udm_free_res' => ['bool', 'res'=>'resource'], 'udm_get_doc_count' => ['int', 'agent'=>'resource'], 'udm_get_res_field' => ['string', 'res'=>'resource', 'row'=>'int', 'field'=>'int'], 'udm_get_res_param' => ['string', 'res'=>'resource', 'param'=>'int'], 'udm_hash32' => ['int', 'agent'=>'resource', 'string'=>'string'], 'udm_load_ispell_data' => ['bool', 'agent'=>'resource', 'var'=>'int', 'val1'=>'string', 'val2'=>'string', 'flag'=>'int'], 'udm_open_stored' => ['int', 'agent'=>'', 'storedaddr'=>'string'], 'udm_set_agent_param' => ['bool', 'agent'=>'resource', 'var'=>'int', 'val'=>'string'], 'ui\area::onDraw' => ['', 'pen'=>'UI\Draw\Pen', 'areaSize'=>'UI\Size', 'clipPoint'=>'UI\Point', 'clipSize'=>'UI\Size'], 'ui\area::onKey' => ['', 'key'=>'string', 'ext'=>'int', 'flags'=>'int'], 'ui\area::onMouse' => ['', 'areaPoint'=>'UI\Point', 'areaSize'=>'UI\Size', 'flags'=>'int'], 'ui\area::redraw' => [''], 'ui\area::scrollTo' => ['', 'point'=>'UI\Point', 'size'=>'UI\Size'], 'ui\area::setSize' => ['', 'size'=>'UI\Size'], 'ui\control::destroy' => [''], 'ui\control::disable' => [''], 'ui\control::enable' => [''], 'ui\control::getParent' => ['UI\Control'], 'ui\control::getTopLevel' => ['int'], 'ui\control::hide' => [''], 'ui\control::isEnabled' => ['bool'], 'ui\control::isVisible' => ['bool'], 'ui\control::setParent' => ['', 'parent'=>'UI\Control'], 'ui\control::show' => [''], 'ui\controls\box::append' => ['int', 'control'=>'Control', 'stretchy='=>'bool'], 'ui\controls\box::delete' => ['bool', 'index'=>'int'], 'ui\controls\box::getOrientation' => ['int'], 'ui\controls\box::isPadded' => ['bool'], 'ui\controls\box::setPadded' => ['', 'padded'=>'bool'], 'ui\controls\button::getText' => ['string'], 'ui\controls\button::onClick' => [''], 'ui\controls\button::setText' => ['', 'text'=>'string'], 'ui\controls\check::getText' => ['string'], 'ui\controls\check::isChecked' => ['bool'], 'ui\controls\check::onToggle' => [''], 'ui\controls\check::setChecked' => ['', 'checked'=>'bool'], 'ui\controls\check::setText' => ['', 'text'=>'string'], 'ui\controls\colorbutton::getColor' => ['UI\Color'], 'ui\controls\colorbutton::onChange' => [''], 'ui\controls\combo::append' => ['', 'text'=>'string'], 'ui\controls\combo::getSelected' => ['int'], 'ui\controls\combo::onSelected' => [''], 'ui\controls\combo::setSelected' => ['', 'index'=>'int'], 'ui\controls\editablecombo::append' => ['', 'text'=>'string'], 'ui\controls\editablecombo::getText' => ['string'], 'ui\controls\editablecombo::onChange' => [''], 'ui\controls\editablecombo::setText' => ['', 'text'=>'string'], 'ui\controls\entry::getText' => ['string'], 'ui\controls\entry::isReadOnly' => ['bool'], 'ui\controls\entry::onChange' => [''], 'ui\controls\entry::setReadOnly' => ['', 'readOnly'=>'bool'], 'ui\controls\entry::setText' => ['', 'text'=>'string'], 'ui\controls\form::append' => ['int', 'label'=>'string', 'control'=>'UI\Control', 'stretchy='=>'bool'], 'ui\controls\form::delete' => ['bool', 'index'=>'int'], 'ui\controls\form::isPadded' => ['bool'], 'ui\controls\form::setPadded' => ['', 'padded'=>'bool'], 'ui\controls\grid::append' => ['', 'control'=>'UI\Control', 'left'=>'int', 'top'=>'int', 'xspan'=>'int', 'yspan'=>'int', 'hexpand'=>'bool', 'halign'=>'int', 'vexpand'=>'bool', 'valign'=>'int'], 'ui\controls\grid::isPadded' => ['bool'], 'ui\controls\grid::setPadded' => ['', 'padding'=>'bool'], 'ui\controls\group::append' => ['', 'control'=>'UI\Control'], 'ui\controls\group::getTitle' => ['string'], 'ui\controls\group::hasMargin' => ['bool'], 'ui\controls\group::setMargin' => ['', 'margin'=>'bool'], 'ui\controls\group::setTitle' => ['', 'title'=>'string'], 'ui\controls\label::getText' => ['string'], 'ui\controls\label::setText' => ['', 'text'=>'string'], 'ui\controls\multilineentry::append' => ['', 'text'=>'string'], 'ui\controls\multilineentry::getText' => ['string'], 'ui\controls\multilineentry::isReadOnly' => ['bool'], 'ui\controls\multilineentry::onChange' => [''], 'ui\controls\multilineentry::setReadOnly' => ['', 'readOnly'=>'bool'], 'ui\controls\multilineentry::setText' => ['', 'text'=>'string'], 'ui\controls\progress::getValue' => ['int'], 'ui\controls\progress::setValue' => ['', 'value'=>'int'], 'ui\controls\radio::append' => ['', 'text'=>'string'], 'ui\controls\radio::getSelected' => ['int'], 'ui\controls\radio::onSelected' => [''], 'ui\controls\radio::setSelected' => ['', 'index'=>'int'], 'ui\controls\slider::getValue' => ['int'], 'ui\controls\slider::onChange' => [''], 'ui\controls\slider::setValue' => ['', 'value'=>'int'], 'ui\controls\spin::getValue' => ['int'], 'ui\controls\spin::onChange' => [''], 'ui\controls\spin::setValue' => ['', 'value'=>'int'], 'ui\controls\tab::append' => ['int', 'name'=>'string', 'control'=>'UI\Control'], 'ui\controls\tab::delete' => ['bool', 'index'=>'int'], 'ui\controls\tab::hasMargin' => ['bool', 'page'=>'int'], 'ui\controls\tab::insertAt' => ['', 'name'=>'string', 'page'=>'int', 'control'=>'UI\Control'], 'ui\controls\tab::pages' => ['int'], 'ui\controls\tab::setMargin' => ['', 'page'=>'int', 'margin'=>'bool'], 'ui\draw\brush::getColor' => ['UI\Draw\Color'], 'ui\draw\brush\gradient::delStop' => ['int', 'index'=>'int'], 'ui\draw\color::getChannel' => ['float', 'channel'=>'int'], 'ui\draw\color::setChannel' => ['void', 'channel'=>'int', 'value'=>'float'], 'ui\draw\matrix::invert' => [''], 'ui\draw\matrix::isInvertible' => ['bool'], 'ui\draw\matrix::multiply' => ['UI\Draw\Matrix', 'matrix'=>'UI\Draw\Matrix'], 'ui\draw\matrix::rotate' => ['', 'point'=>'UI\Point', 'amount'=>'float'], 'ui\draw\matrix::scale' => ['', 'center'=>'UI\Point', 'point'=>'UI\Point'], 'ui\draw\matrix::skew' => ['', 'point'=>'UI\Point', 'amount'=>'UI\Point'], 'ui\draw\matrix::translate' => ['', 'point'=>'UI\Point'], 'ui\draw\path::addRectangle' => ['', 'point'=>'UI\Point', 'size'=>'UI\Size'], 'ui\draw\path::arcTo' => ['', 'point'=>'UI\Point', 'radius'=>'float', 'angle'=>'float', 'sweep'=>'float', 'negative'=>'float'], 'ui\draw\path::bezierTo' => ['', 'point'=>'UI\Point', 'radius'=>'float', 'angle'=>'float', 'sweep'=>'float', 'negative'=>'float'], 'ui\draw\path::closeFigure' => [''], 'ui\draw\path::end' => [''], 'ui\draw\path::lineTo' => ['', 'point'=>'UI\Point', 'radius'=>'float', 'angle'=>'float', 'sweep'=>'float', 'negative'=>'float'], 'ui\draw\path::newFigure' => ['', 'point'=>'UI\Point'], 'ui\draw\path::newFigureWithArc' => ['', 'point'=>'UI\Point', 'radius'=>'float', 'angle'=>'float', 'sweep'=>'float', 'negative'=>'float'], 'ui\draw\pen::clip' => ['', 'path'=>'UI\Draw\Path'], 'ui\draw\pen::restore' => [''], 'ui\draw\pen::save' => [''], 'ui\draw\pen::transform' => ['', 'matrix'=>'UI\Draw\Matrix'], 'ui\draw\pen::write' => ['', 'point'=>'UI\Point', 'layout'=>'UI\Draw\Text\Layout'], 'ui\draw\stroke::getCap' => ['int'], 'ui\draw\stroke::getJoin' => ['int'], 'ui\draw\stroke::getMiterLimit' => ['float'], 'ui\draw\stroke::getThickness' => ['float'], 'ui\draw\stroke::setCap' => ['', 'cap'=>'int'], 'ui\draw\stroke::setJoin' => ['', 'join'=>'int'], 'ui\draw\stroke::setMiterLimit' => ['', 'limit'=>'float'], 'ui\draw\stroke::setThickness' => ['', 'thickness'=>'float'], 'ui\draw\text\font::getAscent' => ['float'], 'ui\draw\text\font::getDescent' => ['float'], 'ui\draw\text\font::getLeading' => ['float'], 'ui\draw\text\font::getUnderlinePosition' => ['float'], 'ui\draw\text\font::getUnderlineThickness' => ['float'], 'ui\draw\text\font\descriptor::getFamily' => ['string'], 'ui\draw\text\font\descriptor::getItalic' => ['int'], 'ui\draw\text\font\descriptor::getSize' => ['float'], 'ui\draw\text\font\descriptor::getStretch' => ['int'], 'ui\draw\text\font\descriptor::getWeight' => ['int'], 'ui\draw\text\font\fontfamilies' => ['array'], 'ui\draw\text\layout::setWidth' => ['', 'width'=>'float'], 'ui\executor::kill' => ['void'], 'ui\executor::onExecute' => ['void'], 'ui\menu::append' => ['UI\MenuItem', 'name'=>'string', 'type='=>'string'], 'ui\menu::appendAbout' => ['UI\MenuItem', 'type='=>'string'], 'ui\menu::appendCheck' => ['UI\MenuItem', 'name'=>'string', 'type='=>'string'], 'ui\menu::appendPreferences' => ['UI\MenuItem', 'type='=>'string'], 'ui\menu::appendQuit' => ['UI\MenuItem', 'type='=>'string'], 'ui\menu::appendSeparator' => [''], 'ui\menuitem::disable' => [''], 'ui\menuitem::enable' => [''], 'ui\menuitem::isChecked' => ['bool'], 'ui\menuitem::onClick' => [''], 'ui\menuitem::setChecked' => ['', 'checked'=>'bool'], 'ui\point::getX' => ['float'], 'ui\point::getY' => ['float'], 'ui\point::setX' => ['', 'point'=>'float'], 'ui\point::setY' => ['', 'point'=>'float'], 'ui\quit' => ['void'], 'ui\run' => ['void', 'flags='=>'int'], 'ui\size::getHeight' => ['float'], 'ui\size::getWidth' => ['float'], 'ui\size::setHeight' => ['', 'size'=>'float'], 'ui\size::setWidth' => ['', 'size'=>'float'], 'ui\window::add' => ['', 'control'=>'UI\Control'], 'ui\window::error' => ['', 'title'=>'string', 'msg'=>'string'], 'ui\window::getSize' => ['UI\Size'], 'ui\window::getTitle' => ['string'], 'ui\window::hasBorders' => ['bool'], 'ui\window::hasMargin' => ['bool'], 'ui\window::isFullScreen' => ['bool'], 'ui\window::msg' => ['', 'title'=>'string', 'msg'=>'string'], 'ui\window::onClosing' => ['int'], 'ui\window::open' => ['string'], 'ui\window::save' => ['string'], 'ui\window::setBorders' => ['', 'borders'=>'bool'], 'ui\window::setFullScreen' => ['', 'full'=>'bool'], 'ui\window::setMargin' => ['', 'margin'=>'bool'], 'ui\window::setSize' => ['', 'size'=>'UI\Size'], 'ui\window::setTitle' => ['', 'title'=>'string'], 'uksort' => ['bool', '&rw_array'=>'array', 'cmp_function'=>'callable(mixed,mixed):int'], 'umask' => ['int', 'mask='=>'int'], 'UnderflowException::__clone' => ['void'], 'UnderflowException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?UnderflowException'], 'UnderflowException::__toString' => ['string'], 'UnderflowException::getCode' => ['int'], 'UnderflowException::getFile' => ['string'], 'UnderflowException::getLine' => ['int'], 'UnderflowException::getMessage' => ['string'], 'UnderflowException::getPrevious' => ['Throwable|UnderflowException|null'], 'UnderflowException::getTrace' => ['list>'], 'UnderflowException::getTraceAsString' => ['string'], 'UnexpectedValueException::__clone' => ['void'], 'UnexpectedValueException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable|?UnexpectedValueException'], 'UnexpectedValueException::__toString' => ['string'], 'UnexpectedValueException::getCode' => ['int'], 'UnexpectedValueException::getFile' => ['string'], 'UnexpectedValueException::getLine' => ['int'], 'UnexpectedValueException::getMessage' => ['string'], 'UnexpectedValueException::getPrevious' => ['Throwable|UnexpectedValueException|null'], 'UnexpectedValueException::getTrace' => ['list>'], 'UnexpectedValueException::getTraceAsString' => ['string'], 'uniqid' => ['string', 'prefix='=>'string', 'more_entropy='=>'bool'], 'unixtojd' => ['int', 'timestamp='=>'int'], 'unlink' => ['bool', 'filename'=>'string', 'context='=>'resource'], 'unpack' => ['array|false', 'format'=>'string', 'data'=>'string', 'offset='=>'int'], 'unregister_tick_function' => ['void', 'function_name'=>'callable'], 'unserialize' => ['mixed', 'value'=>'string', 'options='=>'array{allowed_classes?:string[]|bool}'], 'unset' => ['void', 'var='=>'mixed', '...args='=>'mixed'], 'untaint' => ['bool', '&rw_string'=>'string', '&...rw_strings='=>'string'], 'uopz_allow_exit' => ['void', 'allow'=>'bool'], 'uopz_backup' => ['void', 'class'=>'string', 'function'=>'string'], 'uopz_backup\'1' => ['void', 'function'=>'string'], 'uopz_compose' => ['void', 'name'=>'string', 'classes'=>'array', 'methods='=>'array', 'properties='=>'array', 'flags='=>'int'], 'uopz_copy' => ['Closure', 'class'=>'string', 'function'=>'string'], 'uopz_copy\'1' => ['Closure', 'function'=>'string'], 'uopz_delete' => ['void', 'class'=>'string', 'function'=>'string'], 'uopz_delete\'1' => ['void', 'function'=>'string'], 'uopz_extend' => ['bool', 'class'=>'string', 'parent'=>'string'], 'uopz_flags' => ['int', 'class'=>'string', 'function'=>'string', 'flags'=>'int'], 'uopz_flags\'1' => ['int', 'function'=>'string', 'flags'=>'int'], 'uopz_function' => ['void', 'class'=>'string', 'function'=>'string', 'handler'=>'Closure', 'modifiers='=>'int'], 'uopz_function\'1' => ['void', 'function'=>'string', 'handler'=>'Closure', 'modifiers='=>'int'], 'uopz_get_exit_status' => ['?int'], 'uopz_get_hook' => ['?Closure', 'class'=>'string', 'function'=>'string'], 'uopz_get_hook\'1' => ['?Closure', 'function'=>'string'], 'uopz_get_mock' => ['string|object|null', 'class'=>'string'], 'uopz_get_property' => ['mixed', 'class'=>'object|string', 'property'=>'string'], 'uopz_get_return' => ['mixed', 'class='=>'string', 'function='=>'string'], 'uopz_get_static' => ['?array', 'class'=>'string', 'function'=>'string'], 'uopz_implement' => ['bool', 'class'=>'string', 'interface'=>'string'], 'uopz_overload' => ['void', 'opcode'=>'int', 'callable'=>'Callable'], 'uopz_redefine' => ['bool', 'class'=>'string', 'constant'=>'string', 'value'=>'mixed'], 'uopz_redefine\'1' => ['bool', 'constant'=>'string', 'value'=>'mixed'], 'uopz_rename' => ['void', 'class'=>'string', 'function'=>'string', 'rename'=>'string'], 'uopz_rename\'1' => ['void', 'function'=>'string', 'rename'=>'string'], 'uopz_restore' => ['void', 'class'=>'string', 'function'=>'string'], 'uopz_restore\'1' => ['void', 'function'=>'string'], 'uopz_set_hook' => ['bool', 'class'=>'string', 'function'=>'string', 'hook'=>'Closure'], 'uopz_set_hook\'1' => ['bool', 'function'=>'string', 'hook'=>'Closure'], 'uopz_set_mock' => ['void', 'class'=>'string', 'mock'=>'object|string'], 'uopz_set_property' => ['void', 'class'=>'object|string', 'property'=>'string', 'value'=>'mixed'], 'uopz_set_return' => ['bool', 'class'=>'string', 'function'=>'string', 'value'=>'mixed', 'execute='=>'bool'], 'uopz_set_return\'1' => ['bool', 'function'=>'string', 'value'=>'mixed', 'execute='=>'bool'], 'uopz_set_static' => ['void', 'class'=>'string', 'function'=>'string', 'static'=>'array'], 'uopz_undefine' => ['bool', 'class'=>'string', 'constant'=>'string'], 'uopz_undefine\'1' => ['bool', 'constant'=>'string'], 'uopz_unset_hook' => ['bool', 'class'=>'string', 'function'=>'string'], 'uopz_unset_hook\'1' => ['bool', 'function'=>'string'], 'uopz_unset_mock' => ['void', 'class'=>'string'], 'uopz_unset_return' => ['bool', 'class='=>'string', 'function='=>'string'], 'uopz_unset_return\'1' => ['bool', 'function'=>'string'], 'urldecode' => ['string', 'string'=>'string'], 'urlencode' => ['string', 'string'=>'string'], 'use_soap_error_handler' => ['bool', 'handler='=>'bool'], 'user_error' => ['void', 'message'=>'string', 'error_type='=>'int'], 'usleep' => ['void', 'microseconds'=>'int'], 'usort' => ['bool', '&rw_array'=>'array', 'cmp_function'=>'callable(mixed,mixed):int'], 'utf8_decode' => ['string', 'data'=>'string'], 'utf8_encode' => ['string', 'data'=>'string'], 'V8Js::__construct' => ['void', 'object_name='=>'string', 'variables='=>'array', 'extensions='=>'array', 'report_uncaught_exceptions='=>'bool', 'snapshot_blob='=>'string'], 'V8Js::clearPendingException' => [''], 'V8Js::compileString' => ['resource', 'script'=>'', 'identifier='=>'string'], 'V8Js::createSnapshot' => ['false|string', 'embed_source'=>'string'], 'V8Js::executeScript' => ['', 'script'=>'resource', 'flags='=>'int', 'time_limit='=>'int', 'memory_limit='=>'int'], 'V8Js::executeString' => ['mixed', 'script'=>'string', 'identifier='=>'string', 'flags='=>'int'], 'V8Js::getExtensions' => ['string[]'], 'V8Js::getPendingException' => ['?V8JsException'], 'V8Js::registerExtension' => ['bool', 'extension_name'=>'string', 'script'=>'string', 'dependencies='=>'array', 'auto_enable='=>'bool'], 'V8Js::setAverageObjectSize' => ['', 'average_object_size'=>'int'], 'V8Js::setMemoryLimit' => ['', 'limit'=>'int'], 'V8Js::setModuleLoader' => ['', 'loader'=>'callable'], 'V8Js::setModuleNormaliser' => ['', 'normaliser'=>'callable'], 'V8Js::setTimeLimit' => ['', 'limit'=>'int'], 'V8JsException::getJsFileName' => ['string'], 'V8JsException::getJsLineNumber' => ['int'], 'V8JsException::getJsSourceLine' => ['int'], 'V8JsException::getJsTrace' => ['string'], 'V8JsScriptException::__clone' => ['void'], 'V8JsScriptException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'V8JsScriptException::__toString' => ['string'], 'V8JsScriptException::__wakeup' => ['void'], 'V8JsScriptException::getCode' => ['int'], 'V8JsScriptException::getFile' => ['string'], 'V8JsScriptException::getJsEndColumn' => ['int'], 'V8JsScriptException::getJsFileName' => ['string'], 'V8JsScriptException::getJsLineNumber' => ['int'], 'V8JsScriptException::getJsSourceLine' => ['string'], 'V8JsScriptException::getJsStartColumn' => ['int'], 'V8JsScriptException::getJsTrace' => ['string'], 'V8JsScriptException::getLine' => ['int'], 'V8JsScriptException::getMessage' => ['string'], 'V8JsScriptException::getPrevious' => ['Exception|Throwable'], 'V8JsScriptException::getTrace' => ['list>'], 'V8JsScriptException::getTraceAsString' => ['string'], 'var_dump' => ['void', 'value'=>'mixed', '...args='=>'mixed'], 'var_export' => ['?string', 'value'=>'mixed', 'return='=>'bool'], 'VARIANT::__construct' => ['void', 'value='=>'mixed', 'type='=>'int', 'codepage='=>'int'], 'variant_abs' => ['mixed', 'left'=>'mixed'], 'variant_add' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_and' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_cast' => ['VARIANT', 'variant'=>'VARIANT', 'type'=>'int'], 'variant_cat' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_cmp' => ['int', 'left'=>'mixed', 'right'=>'mixed', 'lcid='=>'int', 'flags='=>'int'], 'variant_date_from_timestamp' => ['VARIANT', 'timestamp'=>'int'], 'variant_date_to_timestamp' => ['int', 'variant'=>'VARIANT'], 'variant_div' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_eqv' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_fix' => ['mixed', 'left'=>'mixed'], 'variant_get_type' => ['int', 'variant'=>'VARIANT'], 'variant_idiv' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_imp' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_int' => ['mixed', 'left'=>'mixed'], 'variant_mod' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_mul' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_neg' => ['mixed', 'left'=>'mixed'], 'variant_not' => ['mixed', 'left'=>'mixed'], 'variant_or' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_pow' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_round' => ['mixed', 'left'=>'mixed', 'decimals'=>'int'], 'variant_set' => ['void', 'variant'=>'object', 'value'=>'mixed'], 'variant_set_type' => ['void', 'variant'=>'object', 'type'=>'int'], 'variant_sub' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_xor' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'VarnishAdmin::__construct' => ['void', 'args='=>'array'], 'VarnishAdmin::auth' => ['bool'], 'VarnishAdmin::ban' => ['int', 'vcl_regex'=>'string'], 'VarnishAdmin::banUrl' => ['int', 'vcl_regex'=>'string'], 'VarnishAdmin::clearPanic' => ['int'], 'VarnishAdmin::connect' => ['bool'], 'VarnishAdmin::disconnect' => ['bool'], 'VarnishAdmin::getPanic' => ['string'], 'VarnishAdmin::getParams' => ['array'], 'VarnishAdmin::isRunning' => ['bool'], 'VarnishAdmin::setCompat' => ['void', 'compat'=>'int'], 'VarnishAdmin::setHost' => ['void', 'host'=>'string'], 'VarnishAdmin::setIdent' => ['void', 'ident'=>'string'], 'VarnishAdmin::setParam' => ['int', 'name'=>'string', 'value'=>'string|int'], 'VarnishAdmin::setPort' => ['void', 'port'=>'int'], 'VarnishAdmin::setSecret' => ['void', 'secret'=>'string'], 'VarnishAdmin::setTimeout' => ['void', 'timeout'=>'int'], 'VarnishAdmin::start' => ['int'], 'VarnishAdmin::stop' => ['int'], 'VarnishLog::__construct' => ['void', 'args='=>'array'], 'VarnishLog::getLine' => ['array'], 'VarnishLog::getTagName' => ['string', 'index'=>'int'], 'VarnishStat::__construct' => ['void', 'args='=>'array'], 'VarnishStat::getSnapshot' => ['array'], 'version_compare' => ['bool', 'ver1'=>'string', 'ver2'=>'string', 'oper'=>'\'<\'|\'lt\'|\'<=\'|\'le\'|\'>\'|\'gt\'|\'>=\'|\'ge\'|\'==\'|\'=\'|\'eq\'|\'!=\'|\'<>\'|\'ne\''], 'version_compare\'1' => ['int', 'ver1'=>'string', 'ver2'=>'string'], 'vfprintf' => ['int', 'stream'=>'resource', 'format'=>'string', 'args'=>'array'], 'virtual' => ['bool', 'uri'=>'string'], 'vpopmail_add_alias_domain' => ['bool', 'domain'=>'string', 'aliasdomain'=>'string'], 'vpopmail_add_alias_domain_ex' => ['bool', 'olddomain'=>'string', 'newdomain'=>'string'], 'vpopmail_add_domain' => ['bool', 'domain'=>'string', 'dir'=>'string', 'uid'=>'int', 'gid'=>'int'], 'vpopmail_add_domain_ex' => ['bool', 'domain'=>'string', 'passwd'=>'string', 'quota='=>'string', 'bounce='=>'string', 'apop='=>'bool'], 'vpopmail_add_user' => ['bool', 'user'=>'string', 'domain'=>'string', 'password'=>'string', 'gecos='=>'string', 'apop='=>'bool'], 'vpopmail_alias_add' => ['bool', 'user'=>'string', 'domain'=>'string', 'alias'=>'string'], 'vpopmail_alias_del' => ['bool', 'user'=>'string', 'domain'=>'string'], 'vpopmail_alias_del_domain' => ['bool', 'domain'=>'string'], 'vpopmail_alias_get' => ['array', 'alias'=>'string', 'domain'=>'string'], 'vpopmail_alias_get_all' => ['array', 'domain'=>'string'], 'vpopmail_auth_user' => ['bool', 'user'=>'string', 'domain'=>'string', 'password'=>'string', 'apop='=>'string'], 'vpopmail_del_domain' => ['bool', 'domain'=>'string'], 'vpopmail_del_domain_ex' => ['bool', 'domain'=>'string'], 'vpopmail_del_user' => ['bool', 'user'=>'string', 'domain'=>'string'], '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', 'args'=>'array'], 'vsprintf' => ['string', 'format'=>'string', 'args'=>'array'], 'Vtiful\Kernel\Excel::__construct' => ['void', 'config'=>'array'], 'Vtiful\Kernel\Excel::addSheet' => ['', 'sheetName'=>'string'], 'Vtiful\Kernel\Excel::autoFilter' => ['', 'scope'=>'string'], 'Vtiful\Kernel\Excel::constMemory' => ['', 'fileName'=>'string', 'sheetName='=>'string'], 'Vtiful\Kernel\Excel::data' => ['', 'data'=>'array'], 'Vtiful\Kernel\Excel::fileName' => ['', 'fileName'=>'string', 'sheetName='=>'string'], 'Vtiful\Kernel\Excel::getHandle' => [''], 'Vtiful\Kernel\Excel::header' => ['', 'headerData'=>'array'], 'Vtiful\Kernel\Excel::insertFormula' => ['', 'row'=>'int', 'column'=>'int', 'formula'=>'string'], 'Vtiful\Kernel\Excel::insertImage' => ['', 'row'=>'int', 'column'=>'int', 'localImagePath'=>'string'], 'Vtiful\Kernel\Excel::insertText' => ['', 'row'=>'int', 'column'=>'int', 'data'=>'string', 'format='=>'string'], 'Vtiful\Kernel\Excel::mergeCells' => ['', 'scope'=>'string', 'data'=>'string'], 'Vtiful\Kernel\Excel::output' => [''], 'Vtiful\Kernel\Excel::setColumn' => ['', 'range'=>'string', 'width'=>'float', 'format='=>'resource'], 'Vtiful\Kernel\Excel::setRow' => ['', 'range'=>'string', 'height'=>'float', 'format='=>'resource'], 'Vtiful\Kernel\Format::align' => ['', 'handle'=>'resource', 'style'=>'int'], 'Vtiful\Kernel\Format::bold' => ['', 'handle'=>'resource'], 'Vtiful\Kernel\Format::italic' => ['', 'handle'=>'resource'], 'Vtiful\Kernel\Format::underline' => ['', 'handle'=>'resource', 'style'=>'int'], '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='=>''], 'w32api_register_function' => ['bool', 'library'=>'string', 'function_name'=>'string', 'return_type'=>'string'], 'w32api_set_call_method' => ['', 'method'=>'int'], 'wddx_add_vars' => ['bool', 'packet_id'=>'resource', 'var_names'=>'mixed', '...vars='=>'mixed'], 'wddx_deserialize' => ['mixed', 'packet'=>'string'], 'wddx_packet_end' => ['string', 'packet_id'=>'resource'], 'wddx_packet_start' => ['resource|false', 'comment='=>'string'], 'wddx_serialize_value' => ['string|false', 'value'=>'mixed', 'comment='=>'string'], 'wddx_serialize_vars' => ['string|false', 'var_name'=>'mixed', '...vars='=>'mixed'], 'WeakMap::__construct' => ['void'], 'WeakMap::count' => ['int'], 'WeakMap::current' => ['mixed'], 'WeakMap::key' => ['object'], 'WeakMap::next' => ['void'], 'WeakMap::offsetExists' => ['bool', 'object'=>'object'], 'WeakMap::offsetGet' => ['mixed', 'object'=>'object'], 'WeakMap::offsetSet' => ['void', 'object'=>'object', 'value'=>'mixed'], 'WeakMap::offsetUnset' => ['void', 'object'=>'object'], 'WeakMap::rewind' => ['void'], 'WeakMap::valid' => ['bool'], 'Weakref::acquire' => ['bool'], 'Weakref::get' => ['object'], 'Weakref::release' => ['bool'], 'Weakref::valid' => ['bool'], 'webObj::convertToString' => ['string'], 'webObj::free' => ['void'], 'webObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'webObj::updateFromString' => ['int', 'snippet'=>'string'], 'win32_continue_service' => ['int|false', 'servicename'=>'string', 'machine='=>'string'], 'win32_create_service' => ['int|false', 'details'=>'array', 'machine='=>'string'], 'win32_delete_service' => ['int|false', 'servicename'=>'string', 'machine='=>'string'], 'win32_get_last_control_message' => ['int'], 'win32_pause_service' => ['int|false', 'servicename'=>'string', 'machine='=>'string'], 'win32_ps_list_procs' => ['array'], 'win32_ps_stat_mem' => ['array'], 'win32_ps_stat_proc' => ['array', 'pid='=>'int'], 'win32_query_service_status' => ['array|false|int', 'servicename'=>'string', 'machine='=>'string'], 'win32_send_custom_control' => ['int', 'servicename'=>'string', 'control'=>'int', 'machine='=>'string'], 'win32_set_service_exit_code' => ['int', 'exitCode='=>'int'], 'win32_set_service_exit_mode' => ['bool', 'gracefulMode='=>'bool'], 'win32_set_service_status' => ['bool|int', 'status'=>'int', 'checkpoint='=>'int'], 'win32_start_service' => ['int|false', 'servicename'=>'string', 'machine='=>'string'], 'win32_start_service_ctrl_dispatcher' => ['bool|int', 'name'=>'string'], 'win32_stop_service' => ['int|false', 'servicename'=>'string', 'machine='=>'string'], 'wincache_fcache_fileinfo' => ['array|false', 'summaryonly='=>'bool'], 'wincache_fcache_meminfo' => ['array|false'], 'wincache_lock' => ['bool', 'key'=>'string', 'isglobal='=>'bool'], 'wincache_ocache_fileinfo' => ['array|false', 'summaryonly='=>'bool'], 'wincache_ocache_meminfo' => ['array|false'], 'wincache_refresh_if_changed' => ['bool', 'files='=>'array'], 'wincache_rplist_fileinfo' => ['array|false', 'summaryonly='=>'bool'], 'wincache_rplist_meminfo' => ['array|false'], 'wincache_scache_info' => ['array|false', 'summaryonly='=>'bool'], 'wincache_scache_meminfo' => ['array|false'], 'wincache_ucache_add' => ['bool', 'key'=>'string', 'value'=>'mixed', 'ttl='=>'int'], 'wincache_ucache_add\'1' => ['bool', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'wincache_ucache_cas' => ['bool', 'key'=>'string', 'old_value'=>'int', 'new_value'=>'int'], 'wincache_ucache_clear' => ['bool'], 'wincache_ucache_dec' => ['int|false', 'key'=>'string', 'dec_by='=>'int', 'success='=>'bool'], 'wincache_ucache_delete' => ['bool', 'key'=>'mixed'], 'wincache_ucache_exists' => ['bool', 'key'=>'string'], 'wincache_ucache_get' => ['mixed', 'key'=>'mixed', '&w_success='=>'bool'], 'wincache_ucache_inc' => ['int|false', 'key'=>'string', 'inc_by='=>'int', 'success='=>'bool'], 'wincache_ucache_info' => ['array|false', 'summaryonly='=>'bool', 'key='=>'string'], 'wincache_ucache_meminfo' => ['array|false'], 'wincache_ucache_set' => ['bool', 'key'=>'', 'value'=>'', 'ttl='=>'int'], 'wincache_ucache_set\'1' => ['bool', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'wincache_unlock' => ['bool', 'key'=>'string'], 'wkhtmltox\image\converter::convert' => ['?string'], 'wkhtmltox\image\converter::getVersion' => ['string'], 'wkhtmltox\pdf\converter::add' => ['void', 'object'=>'wkhtmltox\PDF\Object'], 'wkhtmltox\pdf\converter::convert' => ['?string'], 'wkhtmltox\pdf\converter::getVersion' => ['string'], 'wordwrap' => ['string', 'string'=>'string', 'width='=>'int', 'break='=>'string', 'cut='=>'bool'], 'Worker::__construct' => ['void'], 'Worker::addRef' => ['void'], 'Worker::chunk' => ['array', 'size'=>'int', 'preserve'=>'bool'], 'Worker::collect' => ['int', 'collector='=>'Callable'], 'Worker::count' => ['int'], 'Worker::delRef' => ['void'], 'Worker::detach' => ['void'], 'Worker::extend' => ['bool', 'class'=>'string'], 'Worker::getCreatorId' => ['int'], 'Worker::getCurrentThread' => ['Thread'], 'Worker::getCurrentThreadId' => ['int'], 'Worker::getRefCount' => ['int'], 'Worker::getStacked' => ['int'], 'Worker::getTerminationInfo' => ['array'], 'Worker::getThreadId' => ['int'], 'Worker::globally' => ['mixed'], 'Worker::isGarbage' => ['bool'], 'Worker::isJoined' => ['bool'], 'Worker::isRunning' => ['bool'], 'Worker::isShutdown' => ['bool'], 'Worker::isStarted' => ['bool'], 'Worker::isTerminated' => ['bool'], 'Worker::isWaiting' => ['bool'], 'Worker::isWorking' => ['bool'], 'Worker::join' => ['bool'], 'Worker::kill' => ['bool'], 'Worker::lock' => ['bool'], '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::pop' => ['bool'], 'Worker::run' => ['void'], 'Worker::setGarbage' => ['void'], 'Worker::shift' => ['bool'], 'Worker::shutdown' => ['bool'], 'Worker::stack' => ['int', '&rw_work'=>'Threaded'], 'Worker::start' => ['bool', 'options='=>'int'], 'Worker::synchronized' => ['mixed', 'block'=>'Closure', '_='=>'mixed'], 'Worker::unlock' => ['bool'], 'Worker::unstack' => ['int', '&rw_work='=>'Threaded'], 'Worker::wait' => ['bool', 'timeout='=>'int'], 'xattr_get' => ['string', 'filename'=>'string', 'name'=>'string', 'flags='=>'int'], 'xattr_list' => ['array', 'filename'=>'string', 'flags='=>'int'], 'xattr_remove' => ['bool', 'filename'=>'string', 'name'=>'string', 'flags='=>'int'], 'xattr_set' => ['bool', 'filename'=>'string', 'name'=>'string', 'value'=>'string', 'flags='=>'int'], 'xattr_supported' => ['bool', 'filename'=>'string', 'flags='=>'int'], 'xcache_asm' => ['string', 'filename'=>'string'], 'xcache_clear_cache' => ['void', 'type'=>'int', 'id='=>'int'], 'xcache_coredump' => ['string', 'op_type'=>'int'], 'xcache_count' => ['int', 'type'=>'int'], 'xcache_coverager_decode' => ['array', 'data'=>'string'], 'xcache_coverager_get' => ['array', 'clean='=>'bool'], 'xcache_coverager_start' => ['void', 'clean='=>'bool'], 'xcache_coverager_stop' => ['void', 'clean='=>'bool'], 'xcache_dasm_file' => ['string', 'filename'=>'string'], 'xcache_dasm_string' => ['string', 'code'=>'string'], 'xcache_dec' => ['int', 'name'=>'string', 'value='=>'int|mixed', 'ttl='=>'int'], 'xcache_decode' => ['bool', 'filename'=>'string'], 'xcache_encode' => ['string', 'filename'=>'string'], 'xcache_get' => ['mixed', 'name'=>'string'], 'xcache_get_data_type' => ['string', 'type'=>'int'], 'xcache_get_op_spec' => ['string', 'op_type'=>'int'], 'xcache_get_op_type' => ['string', 'op_type'=>'int'], 'xcache_get_opcode' => ['string', 'opcode'=>'int'], 'xcache_get_opcode_spec' => ['string', 'opcode'=>'int'], 'xcache_inc' => ['int', 'name'=>'string', 'value='=>'int|mixed', 'ttl='=>'int'], 'xcache_info' => ['array', 'type'=>'int', 'id'=>'int'], 'xcache_is_autoglobal' => ['string', 'name'=>'string'], 'xcache_isset' => ['bool', 'name'=>'string'], 'xcache_list' => ['array', 'type'=>'int', 'id'=>'int'], 'xcache_set' => ['bool', 'name'=>'string', 'value'=>'mixed', 'ttl='=>'int'], 'xcache_unset' => ['bool', 'name'=>'string'], 'xcache_unset_by_prefix' => ['bool', 'prefix'=>'string'], 'Xcom::__construct' => ['void', 'fabric_url='=>'string', 'fabric_token='=>'string', 'capability_token='=>'string'], 'Xcom::decode' => ['object', 'avro_msg'=>'string', 'json_schema'=>'string'], 'Xcom::encode' => ['string', 'data'=>'stdClass', 'avro_schema'=>'string'], 'Xcom::getDebugOutput' => ['string'], 'Xcom::getLastResponse' => ['string'], 'Xcom::getLastResponseInfo' => ['array'], 'Xcom::getOnboardingURL' => ['string', 'capability_name'=>'string', 'agreement_url'=>'string'], 'Xcom::send' => ['int', 'topic'=>'string', 'data'=>'mixed', 'json_schema='=>'string', 'http_headers='=>'array'], 'Xcom::sendAsync' => ['int', 'topic'=>'string', 'data'=>'mixed', 'json_schema='=>'string', 'http_headers='=>'array'], 'xdebug_break' => ['bool'], 'xdebug_call_class' => ['string', 'depth='=>'int'], 'xdebug_call_file' => ['string', 'depth='=>'int'], 'xdebug_call_function' => ['string', 'depth='=>'int'], 'xdebug_call_line' => ['int', 'depth='=>'int'], 'xdebug_clear_aggr_profiling_data' => ['bool'], 'xdebug_code_coverage_started' => ['bool'], 'xdebug_debug_zval' => ['void', '...varName'=>'string'], 'xdebug_debug_zval_stdout' => ['void', '...varName'=>'string'], 'xdebug_disable' => ['void'], 'xdebug_dump_aggr_profiling_data' => ['bool'], 'xdebug_dump_superglobals' => ['void'], 'xdebug_enable' => ['void'], 'xdebug_get_code_coverage' => ['array'], 'xdebug_get_collected_errors' => ['string', 'clean='=>'bool'], 'xdebug_get_declared_vars' => ['array'], 'xdebug_get_formatted_function_stack' => [''], 'xdebug_get_function_count' => ['int'], 'xdebug_get_function_stack' => ['array', 'message='=>'string', 'options='=>'int'], 'xdebug_get_headers' => ['array'], 'xdebug_get_monitored_functions' => ['array'], 'xdebug_get_profiler_filename' => ['string'], 'xdebug_get_stack_depth' => ['int'], 'xdebug_get_tracefile_name' => ['string'], 'xdebug_is_debugger_active' => ['bool'], 'xdebug_is_enabled' => ['bool'], 'xdebug_memory_usage' => ['int'], 'xdebug_peak_memory_usage' => ['int'], 'xdebug_print_function_stack' => ['array', 'message='=>'string', 'options='=>'int'], 'xdebug_set_filter' => ['void', 'group'=>'int', 'list_type'=>'int', 'configuration'=>'array'], 'xdebug_start_code_coverage' => ['void', 'options='=>'int'], 'xdebug_start_error_collection' => ['void'], 'xdebug_start_function_monitor' => ['void', 'list_of_functions_to_monitor'=>'string[]'], 'xdebug_start_trace' => ['void', 'trace_file'=>'', 'options='=>'int|mixed'], 'xdebug_stop_code_coverage' => ['void', 'cleanup='=>'bool'], 'xdebug_stop_error_collection' => ['void'], 'xdebug_stop_function_monitor' => ['void'], 'xdebug_stop_trace' => ['void'], 'xdebug_time_index' => ['float'], 'xdebug_var_dump' => ['void', '...var'=>''], 'xdiff_file_bdiff' => ['bool', 'old_file'=>'string', 'new_file'=>'string', 'dest'=>'string'], 'xdiff_file_bdiff_size' => ['int', 'file'=>'string'], 'xdiff_file_bpatch' => ['bool', 'file'=>'string', 'patch'=>'string', 'dest'=>'string'], 'xdiff_file_diff' => ['bool', 'old_file'=>'string', 'new_file'=>'string', 'dest'=>'string', 'context='=>'int', 'minimal='=>'bool'], 'xdiff_file_diff_binary' => ['bool', 'old_file'=>'string', 'new_file'=>'string', 'dest'=>'string'], 'xdiff_file_merge3' => ['mixed', 'old_file'=>'string', 'new_file1'=>'string', 'new_file2'=>'string', 'dest'=>'string'], 'xdiff_file_patch' => ['mixed', 'file'=>'string', 'patch'=>'string', 'dest'=>'string', 'flags='=>'int'], 'xdiff_file_patch_binary' => ['bool', 'file'=>'string', 'patch'=>'string', 'dest'=>'string'], 'xdiff_file_rabdiff' => ['bool', 'old_file'=>'string', 'new_file'=>'string', 'dest'=>'string'], 'xdiff_string_bdiff' => ['string', 'old_data'=>'string', 'new_data'=>'string'], 'xdiff_string_bdiff_size' => ['int', 'patch'=>'string'], 'xdiff_string_bpatch' => ['string', 'string'=>'string', 'patch'=>'string'], 'xdiff_string_diff' => ['string', 'old_data'=>'string', 'new_data'=>'string', 'context='=>'int', 'minimal='=>'bool'], 'xdiff_string_diff_binary' => ['string', 'old_data'=>'string', 'new_data'=>'string'], 'xdiff_string_merge3' => ['mixed', 'old_data'=>'string', 'new_data1'=>'string', 'new_data2'=>'string', 'error='=>'string'], 'xdiff_string_patch' => ['string', 'string'=>'string', 'patch'=>'string', 'flags='=>'int', '&w_error='=>'string'], 'xdiff_string_patch_binary' => ['string', 'string'=>'string', 'patch'=>'string'], 'xdiff_string_rabdiff' => ['string', 'old_data'=>'string', 'new_data'=>'string'], 'xhprof_disable' => ['array'], 'xhprof_enable' => ['void', 'flags='=>'int', 'options='=>'array'], 'xhprof_sample_disable' => ['array'], 'xhprof_sample_enable' => ['void'], 'xml_error_string' => ['string', 'code'=>'int'], 'xml_get_current_byte_index' => ['int|false', 'parser'=>'resource'], 'xml_get_current_column_number' => ['int|false', 'parser'=>'resource'], 'xml_get_current_line_number' => ['int|false', 'parser'=>'resource'], 'xml_get_error_code' => ['int|false', 'parser'=>'resource'], 'xml_parse' => ['int', 'parser'=>'resource', 'data'=>'string', 'isfinal='=>'bool'], 'xml_parse_into_struct' => ['int', 'parser'=>'resource', 'data'=>'string', '&w_values'=>'array', '&w_index='=>'array'], 'xml_parser_create' => ['resource', 'encoding='=>'string'], 'xml_parser_create_ns' => ['resource', 'encoding='=>'string', 'sep='=>'string'], 'xml_parser_free' => ['bool', 'parser'=>'resource'], 'xml_parser_get_option' => ['mixed|false', 'parser'=>'resource', 'option'=>'int'], 'xml_parser_set_option' => ['bool', 'parser'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'xml_set_character_data_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_default_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_element_handler' => ['bool', 'parser'=>'resource', 'shdl'=>'callable', 'ehdl'=>'callable'], 'xml_set_end_namespace_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_external_entity_ref_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_notation_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_object' => ['bool', 'parser'=>'resource', 'object'=>'object'], 'xml_set_processing_instruction_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_start_namespace_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_unparsed_entity_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'XMLDiff\Base::__construct' => ['void', 'nsname'=>'string'], 'XMLDiff\Base::diff' => ['mixed', 'from'=>'mixed', 'to'=>'mixed'], 'XMLDiff\Base::merge' => ['mixed', 'src'=>'mixed', 'diff'=>'mixed'], 'XMLDiff\DOM::diff' => ['DOMDocument', 'from'=>'DOMDocument', 'to'=>'DOMDocument'], 'XMLDiff\DOM::merge' => ['DOMDocument', 'src'=>'DOMDocument', 'diff'=>'DOMDocument'], 'XMLDiff\File::diff' => ['string', 'from'=>'string', 'to'=>'string'], 'XMLDiff\File::merge' => ['string', 'src'=>'string', 'diff'=>'string'], 'XMLDiff\Memory::diff' => ['string', 'from'=>'string', 'to'=>'string'], 'XMLDiff\Memory::merge' => ['string', 'src'=>'string', 'diff'=>'string'], 'XMLReader::close' => ['bool'], 'XMLReader::expand' => ['DOMNode|false', 'basenode='=>'DOMNode'], 'XMLReader::getAttribute' => ['?string', 'name'=>'string'], 'XMLReader::getAttributeNo' => ['?string', 'index'=>'int'], 'XMLReader::getAttributeNs' => ['?string', 'name'=>'string', 'namespaceuri'=>'string'], 'XMLReader::getParserProperty' => ['bool', 'property'=>'int'], 'XMLReader::isValid' => ['bool'], 'XMLReader::lookupNamespace' => ['?string', 'prefix'=>'string'], 'XMLReader::moveToAttribute' => ['bool', 'name'=>'string'], 'XMLReader::moveToAttributeNo' => ['bool', 'index'=>'int'], 'XMLReader::moveToAttributeNs' => ['bool', 'localname'=>'string', 'namespaceuri'=>'string'], 'XMLReader::moveToElement' => ['bool'], 'XMLReader::moveToFirstAttribute' => ['bool'], 'XMLReader::moveToNextAttribute' => ['bool'], 'XMLReader::next' => ['bool', 'localname='=>'string'], 'XMLReader::open' => ['bool', 'uri'=>'string', 'encoding='=>'?string', 'options='=>'int'], 'XMLReader::read' => ['bool'], 'XMLReader::readInnerXML' => ['string'], 'XMLReader::readOuterXML' => ['string'], 'XMLReader::readString' => ['string'], 'XMLReader::setParserProperty' => ['bool', 'property'=>'int', 'value'=>'bool'], 'XMLReader::setRelaxNGSchema' => ['bool', 'filename'=>'string'], 'XMLReader::setRelaxNGSchemaSource' => ['bool', 'source'=>'string'], 'XMLReader::setSchema' => ['bool', 'filename'=>'string'], 'XMLReader::XML' => ['bool', 'source'=>'string', 'encoding='=>'?string', 'options='=>'int'], 'xmlrpc_decode' => ['mixed', 'xml'=>'string', 'encoding='=>'string'], 'xmlrpc_decode_request' => ['?array', 'xml'=>'string', '&w_method'=>'string', 'encoding='=>'string'], 'xmlrpc_encode' => ['string', 'value'=>'mixed'], 'xmlrpc_encode_request' => ['string', 'method'=>'string', 'params'=>'mixed', 'output_options='=>'array'], 'xmlrpc_get_type' => ['string', 'value'=>'mixed'], 'xmlrpc_is_fault' => ['bool', 'arg'=>'array'], 'xmlrpc_parse_method_descriptions' => ['array', 'xml'=>'string'], 'xmlrpc_server_add_introspection_data' => ['int', 'server'=>'resource', 'desc'=>'array'], 'xmlrpc_server_call_method' => ['string', 'server'=>'resource', 'xml'=>'string', 'user_data'=>'mixed', 'output_options='=>'array'], 'xmlrpc_server_create' => ['resource'], 'xmlrpc_server_destroy' => ['int', 'server'=>'resource'], 'xmlrpc_server_register_introspection_callback' => ['bool', 'server'=>'resource', 'function'=>'string'], 'xmlrpc_server_register_method' => ['bool', 'server'=>'resource', 'method_name'=>'string', 'function'=>'string'], 'xmlrpc_set_type' => ['bool', '&rw_value'=>'string|DateTime', 'type'=>'string'], 'XMLWriter::endAttribute' => ['bool'], 'XMLWriter::endCData' => ['bool'], 'XMLWriter::endComment' => ['bool'], 'XMLWriter::endDocument' => ['bool'], 'XMLWriter::endDTD' => ['bool', 'xmlwriter='=>''], 'XMLWriter::endDTDAttlist' => ['bool'], 'XMLWriter::endDTDElement' => ['bool'], 'XMLWriter::endDTDEntity' => ['bool'], 'XMLWriter::endElement' => ['bool'], 'XMLWriter::endPI' => ['bool'], 'XMLWriter::flush' => ['', 'empty='=>'bool', 'xmlwriter='=>''], 'XMLWriter::fullEndElement' => ['bool'], 'XMLWriter::openMemory' => ['bool'], 'XMLWriter::openURI' => ['bool', 'uri'=>'string'], 'XMLWriter::outputMemory' => ['string', 'flush='=>'bool', 'xmlwriter='=>''], 'XMLWriter::setIndent' => ['bool', 'indent'=>'bool'], 'XMLWriter::setIndentString' => ['bool', 'indentstring'=>'string'], 'XMLWriter::startAttribute' => ['bool', 'name'=>'string'], 'XMLWriter::startAttributeNS' => ['bool', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'XMLWriter::startCData' => ['bool'], 'XMLWriter::startComment' => ['bool'], 'XMLWriter::startDocument' => ['bool', 'version='=>'string', 'encoding='=>'string', 'standalone='=>'string'], 'XMLWriter::startDTD' => ['bool', 'qualifiedname'=>'string', 'publicid='=>'string', 'systemid='=>'string'], 'XMLWriter::startDTDAttlist' => ['bool', 'name'=>'string'], 'XMLWriter::startDTDElement' => ['bool', 'qualifiedname'=>'string'], 'XMLWriter::startDTDEntity' => ['bool', 'name'=>'string', 'isparam'=>'bool'], 'XMLWriter::startElement' => ['bool', 'name'=>'string'], 'XMLWriter::startElementNS' => ['bool', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'XMLWriter::startPI' => ['bool', 'target'=>'string'], 'XMLWriter::text' => ['bool', 'content'=>'string'], 'XMLWriter::writeAttribute' => ['bool', 'name'=>'string', 'value'=>'string'], 'XMLWriter::writeAttributeNS' => ['bool', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'XMLWriter::writeCData' => ['bool', 'content'=>'string'], 'XMLWriter::writeComment' => ['bool', 'content'=>'string'], 'XMLWriter::writeDTD' => ['bool', 'name'=>'string', 'publicid='=>'string', 'systemid='=>'string', 'subset='=>'string'], 'XMLWriter::writeDTDAttlist' => ['bool', 'name'=>'string', 'content'=>'string'], 'XMLWriter::writeDTDElement' => ['bool', 'name'=>'string', 'content'=>'string'], 'XMLWriter::writeDTDEntity' => ['bool', 'name'=>'string', 'content'=>'string', 'pe'=>'bool', 'publicid'=>'string', 'sysid'=>'string', 'ndataid'=>'string'], 'XMLWriter::writeElement' => ['bool', 'name'=>'string', 'content='=>'?string'], 'XMLWriter::writeElementNS' => ['bool', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content='=>'?string'], 'XMLWriter::writePI' => ['bool', 'target'=>'string', 'content'=>'string'], 'XMLWriter::writeRaw' => ['bool', 'content'=>'string'], 'xmlwriter_end_attribute' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_cdata' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_comment' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_document' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_attlist' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_entity' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_pi' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_flush' => ['mixed', 'xmlwriter'=>'resource', 'empty='=>'bool'], 'xmlwriter_full_end_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_open_memory' => ['resource'], 'xmlwriter_open_uri' => ['resource', 'source'=>'string'], 'xmlwriter_output_memory' => ['string', 'xmlwriter'=>'resource', 'flush='=>'bool'], 'xmlwriter_set_indent' => ['bool', 'xmlwriter'=>'resource', 'indent'=>'bool'], 'xmlwriter_set_indent_string' => ['bool', 'xmlwriter'=>'resource', 'indentstring'=>'string'], 'xmlwriter_start_attribute' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_attribute_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'xmlwriter_start_cdata' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_start_comment' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_start_document' => ['bool', 'xmlwriter'=>'resource', 'version='=>'string', 'encoding='=>'string', 'standalone='=>'string'], 'xmlwriter_start_dtd' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string'], 'xmlwriter_start_dtd_attlist' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_dtd_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_dtd_entity' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'isparam'=>'bool'], 'xmlwriter_start_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_element_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'xmlwriter_start_pi' => ['bool', 'xmlwriter'=>'resource', 'target'=>'string'], 'xmlwriter_text' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_attribute' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_attribute_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_cdata' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_comment' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_dtd' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string', 'subset='=>'string'], 'xmlwriter_write_dtd_attlist' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_entity' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string', 'pe'=>'bool', 'publicid'=>'string', 'sysid'=>'string', 'ndataid'=>'string'], 'xmlwriter_write_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_element_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_pi' => ['bool', 'xmlwriter'=>'resource', 'target'=>'string', 'content'=>'string'], 'xmlwriter_write_raw' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xpath_new_context' => ['XPathContext', 'dom_document'=>'DOMDocument'], 'xpath_register_ns' => ['bool', 'xpath_context'=>'xpathcontext', 'prefix'=>'string', 'uri'=>'string'], 'xpath_register_ns_auto' => ['bool', 'xpath_context'=>'xpathcontext', 'context_node='=>'object'], 'xptr_new_context' => ['XPathContext'], 'xsl_xsltprocessor_get_parameter' => ['string', 'namespace'=>'string', 'name'=>'string'], 'xsl_xsltprocessor_get_security_prefs' => ['int'], 'xsl_xsltprocessor_has_exslt_support' => ['bool'], 'xsl_xsltprocessor_register_php_functions' => ['', 'restrict'=>''], 'xsl_xsltprocessor_remove_parameter' => ['bool', 'namespace'=>'string', 'name'=>'string'], 'xsl_xsltprocessor_set_parameter' => ['bool', 'namespace'=>'string', 'name'=>'', 'value'=>'string'], 'xsl_xsltprocessor_set_profiling' => ['bool', 'filename'=>'string'], 'xsl_xsltprocessor_set_security_prefs' => ['int', 'securityprefs'=>'int'], 'xsl_xsltprocessor_transform_to_uri' => ['int', 'doc'=>'DOMDocument', 'uri'=>'string'], 'xsl_xsltprocessor_transform_to_xml' => ['string', 'doc'=>'DOMDocument'], 'xslt_backend_info' => ['string'], 'xslt_backend_name' => ['string'], 'xslt_backend_version' => ['string'], 'xslt_create' => ['resource'], 'xslt_errno' => ['int', 'xh'=>''], 'xslt_error' => ['string', 'xh'=>''], 'xslt_free' => ['', 'xh'=>''], 'xslt_getopt' => ['int', 'processor'=>''], 'xslt_process' => ['', 'xh'=>'', 'xmlcontainer'=>'string', 'xslcontainer'=>'string', 'resultcontainer='=>'string', 'arguments='=>'array', 'parameters='=>'array'], 'xslt_set_base' => ['', 'xh'=>'', 'uri'=>'string'], 'xslt_set_encoding' => ['', 'xh'=>'', 'encoding'=>'string'], 'xslt_set_error_handler' => ['', 'xh'=>'', 'handler'=>''], 'xslt_set_log' => ['', 'xh'=>'', 'log='=>''], 'xslt_set_object' => ['bool', 'processor'=>'', 'object'=>'object'], 'xslt_set_sax_handler' => ['', 'xh'=>'', 'handlers'=>'array'], 'xslt_set_sax_handlers' => ['', 'processor'=>'', 'handlers'=>'array'], 'xslt_set_scheme_handler' => ['', 'xh'=>'', 'handlers'=>'array'], 'xslt_set_scheme_handlers' => ['', 'xh'=>'', 'handlers'=>'array'], 'xslt_setopt' => ['', 'processor'=>'', 'newmask'=>'int'], 'XSLTProcessor::getParameter' => ['string|false', 'namespaceuri'=>'string', 'localname'=>'string'], 'XsltProcessor::getSecurityPrefs' => ['int'], 'XSLTProcessor::hasExsltSupport' => ['bool'], 'XSLTProcessor::importStylesheet' => ['bool', 'stylesheet'=>'object'], 'XSLTProcessor::registerPHPFunctions' => ['void', 'restrict='=>'mixed'], 'XSLTProcessor::removeParameter' => ['bool', 'namespaceuri'=>'string', 'localname'=>'string'], 'XSLTProcessor::setParameter' => ['bool', 'namespace'=>'string', 'name'=>'string', 'value'=>'string'], 'XSLTProcessor::setParameter\'1' => ['bool', 'namespace'=>'string', 'options'=>'array'], 'XSLTProcessor::setProfiling' => ['bool', 'filename'=>'string'], 'XsltProcessor::setSecurityPrefs' => ['int', 'securityPrefs'=>'int'], 'XSLTProcessor::transformToDoc' => ['DOMDocument|false', 'doc'=>'DOMNode'], 'XSLTProcessor::transformToURI' => ['int', 'doc'=>'DOMDocument', 'uri'=>'string'], 'XSLTProcessor::transformToXML' => ['string|false', 'doc'=>'DOMDocument'], 'yac::__construct' => ['void', 'prefix='=>'string'], 'yac::__get' => ['mixed', 'key'=>'string'], 'yac::__set' => ['mixed', 'key'=>'string', 'value'=>'mixed'], 'yac::delete' => ['bool', 'keys'=>'string|array', 'ttl='=>'int'], 'yac::dump' => ['mixed', 'num'=>'int'], 'yac::flush' => ['bool'], 'yac::get' => ['mixed', 'key'=>'string|array', 'cas='=>'int'], 'yac::info' => ['array'], 'Yaconf::get' => ['mixed', 'name'=>'string', 'default_value='=>'mixed'], 'Yaconf::has' => ['bool', 'name'=>'string'], 'Yaf\Action_Abstract::__clone' => ['void'], 'Yaf\Action_Abstract::__construct' => ['void', 'request'=>'Yaf\Request_Abstract', 'response'=>'Yaf\Response_Abstract', 'view'=>'Yaf\View_Interface', 'invokeArgs='=>'?array'], 'Yaf\Action_Abstract::display' => ['bool', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf\Action_Abstract::execute' => ['mixed'], 'Yaf\Action_Abstract::forward' => ['bool', 'module'=>'string', 'controller='=>'string', 'action='=>'string', 'parameters='=>'?array'], 'Yaf\Action_Abstract::getController' => ['Yaf\Controller_Abstract'], 'Yaf\Action_Abstract::getInvokeArg' => ['mixed|null', 'name'=>'string'], 'Yaf\Action_Abstract::getInvokeArgs' => ['array'], 'Yaf\Action_Abstract::getModuleName' => ['string'], 'Yaf\Action_Abstract::getRequest' => ['Yaf\Request_Abstract'], 'Yaf\Action_Abstract::getResponse' => ['Yaf\Response_Abstract'], 'Yaf\Action_Abstract::getView' => ['Yaf\View_Interface'], 'Yaf\Action_Abstract::getViewpath' => ['string'], 'Yaf\Action_Abstract::init' => [''], 'Yaf\Action_Abstract::initView' => ['Yaf\Response_Abstract', 'options='=>'?array'], 'Yaf\Action_Abstract::redirect' => ['bool', 'url'=>'string'], 'Yaf\Action_Abstract::render' => ['string', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf\Action_Abstract::setViewpath' => ['bool', 'view_directory'=>'string'], 'Yaf\Application::__clone' => ['void'], 'Yaf\Application::__construct' => ['void', 'config'=>'array|string', 'envrion='=>'string'], 'Yaf\Application::__destruct' => ['void'], 'Yaf\Application::__sleep' => ['string[]'], 'Yaf\Application::__wakeup' => ['void'], 'Yaf\Application::app' => ['?Yaf\Application'], 'Yaf\Application::bootstrap' => ['Yaf\Application', 'bootstrap='=>'?Yaf\Bootstrap_Abstract'], 'Yaf\Application::clearLastError' => ['void'], 'Yaf\Application::environ' => ['string'], 'Yaf\Application::execute' => ['void', 'entry'=>'callable', '_='=>'string'], 'Yaf\Application::getAppDirectory' => ['string'], 'Yaf\Application::getConfig' => ['Yaf\Config_Abstract'], 'Yaf\Application::getDispatcher' => ['Yaf\Dispatcher'], 'Yaf\Application::getLastErrorMsg' => ['string'], 'Yaf\Application::getLastErrorNo' => ['int'], 'Yaf\Application::getModules' => ['array'], 'Yaf\Application::run' => ['void'], 'Yaf\Application::setAppDirectory' => ['Yaf\Application', 'directory'=>'string'], 'Yaf\Config\Ini::__construct' => ['void', 'config_file'=>'string', 'section='=>'string'], 'Yaf\Config\Ini::__get' => ['', 'name='=>'mixed'], 'Yaf\Config\Ini::__isset' => ['', 'name'=>'string'], 'Yaf\Config\Ini::__set' => ['void', 'name'=>'', 'value'=>''], 'Yaf\Config\Ini::count' => ['int'], 'Yaf\Config\Ini::current' => ['mixed'], '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::readonly' => ['bool'], 'Yaf\Config\Ini::rewind' => ['void'], 'Yaf\Config\Ini::set' => ['Yaf\Config_Abstract', 'name'=>'string', 'value'=>'mixed'], 'Yaf\Config\Ini::toArray' => ['array'], 'Yaf\Config\Ini::valid' => ['bool'], 'Yaf\Config\Simple::__construct' => ['void', 'array'=>'array', 'readonly='=>'string'], 'Yaf\Config\Simple::__get' => ['', 'name='=>'mixed'], 'Yaf\Config\Simple::__isset' => ['', 'name'=>'string'], 'Yaf\Config\Simple::__set' => ['void', 'name'=>'', 'value'=>''], 'Yaf\Config\Simple::count' => ['int'], 'Yaf\Config\Simple::current' => ['mixed'], '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::readonly' => ['bool'], 'Yaf\Config\Simple::rewind' => ['void'], 'Yaf\Config\Simple::set' => ['Yaf\Config_Abstract', 'name'=>'string', 'value'=>'mixed'], 'Yaf\Config\Simple::toArray' => ['array'], 'Yaf\Config\Simple::valid' => ['bool'], 'Yaf\Config_Abstract::__construct' => ['void'], 'Yaf\Config_Abstract::get' => ['mixed', 'name='=>'string'], 'Yaf\Config_Abstract::readonly' => ['bool'], 'Yaf\Config_Abstract::set' => ['Yaf\Config_Abstract', 'name'=>'string', 'value'=>'mixed'], 'Yaf\Config_Abstract::toArray' => ['array'], 'Yaf\Controller_Abstract::__clone' => ['void'], 'Yaf\Controller_Abstract::__construct' => ['void', 'request'=>'Yaf\Request_Abstract', 'response'=>'Yaf\Response_Abstract', 'view'=>'Yaf\View_Interface', 'invokeArgs='=>'?array'], 'Yaf\Controller_Abstract::display' => ['bool', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf\Controller_Abstract::forward' => ['bool', 'module'=>'string', 'controller='=>'string', 'action='=>'string', 'parameters='=>'?array'], 'Yaf\Controller_Abstract::getInvokeArg' => ['mixed|null', 'name'=>'string'], 'Yaf\Controller_Abstract::getInvokeArgs' => ['array'], 'Yaf\Controller_Abstract::getModuleName' => ['string'], 'Yaf\Controller_Abstract::getRequest' => ['Yaf\Request_Abstract'], 'Yaf\Controller_Abstract::getResponse' => ['Yaf\Response_Abstract'], 'Yaf\Controller_Abstract::getView' => ['Yaf\View_Interface'], 'Yaf\Controller_Abstract::getViewpath' => ['string'], 'Yaf\Controller_Abstract::init' => [''], 'Yaf\Controller_Abstract::initView' => ['Yaf\Response_Abstract', 'options='=>'?array'], 'Yaf\Controller_Abstract::redirect' => ['bool', 'url'=>'string'], 'Yaf\Controller_Abstract::render' => ['string', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf\Controller_Abstract::setViewpath' => ['bool', 'view_directory'=>'string'], 'Yaf\Dispatcher::__clone' => ['void'], 'Yaf\Dispatcher::__construct' => ['void'], 'Yaf\Dispatcher::__sleep' => ['list'], 'Yaf\Dispatcher::__wakeup' => ['void'], 'Yaf\Dispatcher::autoRender' => ['Yaf\Dispatcher', 'flag='=>'bool'], 'Yaf\Dispatcher::catchException' => ['Yaf\Dispatcher', 'flag='=>'bool'], 'Yaf\Dispatcher::disableView' => ['bool'], 'Yaf\Dispatcher::dispatch' => ['Yaf\Response_Abstract', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Dispatcher::enableView' => ['Yaf\Dispatcher'], 'Yaf\Dispatcher::flushInstantly' => ['Yaf\Dispatcher', 'flag='=>'bool'], 'Yaf\Dispatcher::getApplication' => ['Yaf\Application'], 'Yaf\Dispatcher::getInstance' => ['Yaf\Dispatcher'], 'Yaf\Dispatcher::getRequest' => ['Yaf\Request_Abstract'], 'Yaf\Dispatcher::getRouter' => ['Yaf\Router'], 'Yaf\Dispatcher::initView' => ['Yaf\View_Interface', 'templates_dir'=>'string', 'options='=>'?array'], 'Yaf\Dispatcher::registerPlugin' => ['Yaf\Dispatcher', 'plugin'=>'Yaf\Plugin_Abstract'], 'Yaf\Dispatcher::returnResponse' => ['Yaf\Dispatcher', 'flag'=>'bool'], 'Yaf\Dispatcher::setDefaultAction' => ['Yaf\Dispatcher', 'action'=>'string'], 'Yaf\Dispatcher::setDefaultController' => ['Yaf\Dispatcher', 'controller'=>'string'], 'Yaf\Dispatcher::setDefaultModule' => ['Yaf\Dispatcher', 'module'=>'string'], 'Yaf\Dispatcher::setErrorHandler' => ['Yaf\Dispatcher', 'callback'=>'callable', 'error_types'=>'int'], 'Yaf\Dispatcher::setRequest' => ['Yaf\Dispatcher', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Dispatcher::setView' => ['Yaf\Dispatcher', 'view'=>'Yaf\View_Interface'], 'Yaf\Dispatcher::throwException' => ['Yaf\Dispatcher', 'flag='=>'bool'], 'Yaf\Loader::__clone' => ['void'], 'Yaf\Loader::__construct' => ['void'], 'Yaf\Loader::__sleep' => ['list'], 'Yaf\Loader::__wakeup' => ['void'], 'Yaf\Loader::autoload' => ['bool', 'class_name'=>'string'], 'Yaf\Loader::clearLocalNamespace' => [''], 'Yaf\Loader::getInstance' => ['Yaf\Loader', 'local_library_path='=>'string', 'global_library_path='=>'string'], 'Yaf\Loader::getLibraryPath' => ['string', 'is_global='=>'bool'], 'Yaf\Loader::getLocalNamespace' => ['string'], 'Yaf\Loader::import' => ['bool', 'file'=>'string'], 'Yaf\Loader::isLocalName' => ['bool', 'class_name'=>'string'], 'Yaf\Loader::registerLocalNamespace' => ['bool', 'name_prefix'=>'string|string[]'], 'Yaf\Loader::setLibraryPath' => ['Yaf\Loader', 'directory'=>'string', 'global='=>'bool'], 'Yaf\Plugin_Abstract::dispatchLoopShutdown' => ['bool', 'request'=>'Yaf\Request_Abstract', 'response'=>'Yaf\Response_Abstract'], 'Yaf\Plugin_Abstract::dispatchLoopStartup' => ['bool', 'request'=>'Yaf\Request_Abstract', 'response'=>'Yaf\Response_Abstract'], 'Yaf\Plugin_Abstract::postDispatch' => ['bool', 'request'=>'Yaf\Request_Abstract', 'response'=>'Yaf\Response_Abstract'], 'Yaf\Plugin_Abstract::preDispatch' => ['bool', 'request'=>'Yaf\Request_Abstract', 'response'=>'Yaf\Response_Abstract'], 'Yaf\Plugin_Abstract::preResponse' => ['bool', 'request'=>'Yaf\Request_Abstract', 'response'=>'Yaf\Response_Abstract'], 'Yaf\Plugin_Abstract::routerShutdown' => ['bool', 'request'=>'Yaf\Request_Abstract', 'response'=>'Yaf\Response_Abstract'], 'Yaf\Plugin_Abstract::routerStartup' => ['bool', 'request'=>'Yaf\Request_Abstract', 'response'=>'Yaf\Response_Abstract'], 'Yaf\Registry::__clone' => ['void'], 'Yaf\Registry::__construct' => ['void'], 'Yaf\Registry::del' => ['bool|void', 'name'=>'string'], 'Yaf\Registry::get' => ['mixed', 'name'=>'string'], 'Yaf\Registry::has' => ['bool', 'name'=>'string'], 'Yaf\Registry::set' => ['bool', 'name'=>'string', 'value'=>'mixed'], 'Yaf\Request\Http::__clone' => ['void'], 'Yaf\Request\Http::__construct' => ['void', 'request_uri'=>'string', 'base_uri'=>'string'], 'Yaf\Request\Http::get' => ['mixed', 'name'=>'string', 'default='=>'string'], 'Yaf\Request\Http::getActionName' => ['string'], 'Yaf\Request\Http::getBaseUri' => ['string'], 'Yaf\Request\Http::getControllerName' => ['string'], 'Yaf\Request\Http::getCookie' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request\Http::getEnv' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request\Http::getException' => ['Yaf\Exception'], 'Yaf\Request\Http::getFiles' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request\Http::getLanguage' => ['string'], 'Yaf\Request\Http::getMethod' => ['string'], 'Yaf\Request\Http::getModuleName' => ['string'], 'Yaf\Request\Http::getParam' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'Yaf\Request\Http::getParams' => ['array'], 'Yaf\Request\Http::getPost' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request\Http::getQuery' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request\Http::getRequest' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request\Http::getRequestUri' => ['string'], 'Yaf\Request\Http::getServer' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request\Http::isCli' => ['bool'], 'Yaf\Request\Http::isDispatched' => ['bool'], 'Yaf\Request\Http::isGet' => ['bool'], 'Yaf\Request\Http::isHead' => ['bool'], 'Yaf\Request\Http::isOptions' => ['bool'], 'Yaf\Request\Http::isPost' => ['bool'], 'Yaf\Request\Http::isPut' => ['bool'], 'Yaf\Request\Http::isRouted' => ['bool'], 'Yaf\Request\Http::isXmlHttpRequest' => ['bool'], 'Yaf\Request\Http::setActionName' => ['Yaf\Request_Abstract|bool', 'action'=>'string'], 'Yaf\Request\Http::setBaseUri' => ['bool', 'uri'=>'string'], 'Yaf\Request\Http::setControllerName' => ['Yaf\Request_Abstract|bool', 'controller'=>'string'], 'Yaf\Request\Http::setDispatched' => ['bool'], 'Yaf\Request\Http::setModuleName' => ['Yaf\Request_Abstract|bool', 'module'=>'string'], 'Yaf\Request\Http::setParam' => ['Yaf\Request_Abstract|bool', 'name'=>'array|string', 'value='=>'string'], 'Yaf\Request\Http::setRequestUri' => ['', 'uri'=>'string'], 'Yaf\Request\Http::setRouted' => ['Yaf\Request_Abstract|bool'], 'Yaf\Request\Simple::__clone' => ['void'], 'Yaf\Request\Simple::__construct' => ['void', 'method'=>'string', 'controller'=>'string', 'action'=>'string', 'params='=>'string'], 'Yaf\Request\Simple::get' => ['mixed', 'name'=>'string', 'default='=>'string'], 'Yaf\Request\Simple::getActionName' => ['string'], 'Yaf\Request\Simple::getBaseUri' => ['string'], 'Yaf\Request\Simple::getControllerName' => ['string'], 'Yaf\Request\Simple::getCookie' => ['mixed', 'name='=>'string', 'default='=>'string'], 'Yaf\Request\Simple::getEnv' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request\Simple::getException' => ['Yaf\Exception'], 'Yaf\Request\Simple::getFiles' => ['array', 'name='=>'mixed', 'default='=>'null'], 'Yaf\Request\Simple::getLanguage' => ['string'], 'Yaf\Request\Simple::getMethod' => ['string'], 'Yaf\Request\Simple::getModuleName' => ['string'], 'Yaf\Request\Simple::getParam' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'Yaf\Request\Simple::getParams' => ['array'], 'Yaf\Request\Simple::getPost' => ['mixed', 'name='=>'string', 'default='=>'string'], 'Yaf\Request\Simple::getQuery' => ['mixed', 'name='=>'string', 'default='=>'string'], 'Yaf\Request\Simple::getRequest' => ['mixed', 'name='=>'string', 'default='=>'string'], 'Yaf\Request\Simple::getRequestUri' => ['string'], 'Yaf\Request\Simple::getServer' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request\Simple::isCli' => ['bool'], 'Yaf\Request\Simple::isDispatched' => ['bool'], 'Yaf\Request\Simple::isGet' => ['bool'], 'Yaf\Request\Simple::isHead' => ['bool'], 'Yaf\Request\Simple::isOptions' => ['bool'], 'Yaf\Request\Simple::isPost' => ['bool'], 'Yaf\Request\Simple::isPut' => ['bool'], 'Yaf\Request\Simple::isRouted' => ['bool'], 'Yaf\Request\Simple::isXmlHttpRequest' => ['bool'], 'Yaf\Request\Simple::setActionName' => ['Yaf\Request_Abstract|bool', 'action'=>'string'], 'Yaf\Request\Simple::setBaseUri' => ['bool', 'uri'=>'string'], 'Yaf\Request\Simple::setControllerName' => ['Yaf\Request_Abstract|bool', 'controller'=>'string'], 'Yaf\Request\Simple::setDispatched' => ['bool'], 'Yaf\Request\Simple::setModuleName' => ['Yaf\Request_Abstract|bool', 'module'=>'string'], 'Yaf\Request\Simple::setParam' => ['Yaf\Request_Abstract|bool', 'name'=>'array|string', 'value='=>'string'], 'Yaf\Request\Simple::setRequestUri' => ['', 'uri'=>'string'], 'Yaf\Request\Simple::setRouted' => ['Yaf\Request_Abstract|bool'], 'Yaf\Request_Abstract::getActionName' => ['string'], 'Yaf\Request_Abstract::getBaseUri' => ['string'], 'Yaf\Request_Abstract::getControllerName' => ['string'], 'Yaf\Request_Abstract::getEnv' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request_Abstract::getException' => ['Yaf\Exception'], 'Yaf\Request_Abstract::getLanguage' => ['string'], 'Yaf\Request_Abstract::getMethod' => ['string'], 'Yaf\Request_Abstract::getModuleName' => ['string'], 'Yaf\Request_Abstract::getParam' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'Yaf\Request_Abstract::getParams' => ['array'], 'Yaf\Request_Abstract::getRequestUri' => ['string'], 'Yaf\Request_Abstract::getServer' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf\Request_Abstract::isCli' => ['bool'], 'Yaf\Request_Abstract::isDispatched' => ['bool'], 'Yaf\Request_Abstract::isGet' => ['bool'], 'Yaf\Request_Abstract::isHead' => ['bool'], 'Yaf\Request_Abstract::isOptions' => ['bool'], 'Yaf\Request_Abstract::isPost' => ['bool'], 'Yaf\Request_Abstract::isPut' => ['bool'], 'Yaf\Request_Abstract::isRouted' => ['bool'], 'Yaf\Request_Abstract::isXmlHttpRequest' => ['bool'], 'Yaf\Request_Abstract::setActionName' => ['Yaf\Request_Abstract|bool', 'action'=>'string'], 'Yaf\Request_Abstract::setBaseUri' => ['bool', 'uri'=>'string'], 'Yaf\Request_Abstract::setControllerName' => ['Yaf\Request_Abstract|bool', 'controller'=>'string'], 'Yaf\Request_Abstract::setDispatched' => ['bool'], 'Yaf\Request_Abstract::setModuleName' => ['Yaf\Request_Abstract|bool', 'module'=>'string'], 'Yaf\Request_Abstract::setParam' => ['Yaf\Request_Abstract|bool', 'name'=>'array|string', 'value='=>'string'], 'Yaf\Request_Abstract::setRequestUri' => ['', 'uri'=>'string'], 'Yaf\Request_Abstract::setRouted' => ['Yaf\Request_Abstract|bool'], 'Yaf\Response\Cli::__clone' => ['void'], 'Yaf\Response\Cli::__construct' => ['void'], 'Yaf\Response\Cli::__destruct' => ['void'], 'Yaf\Response\Cli::__toString' => ['string'], 'Yaf\Response\Cli::appendBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf\Response\Cli::clearBody' => ['bool', 'key='=>'string'], 'Yaf\Response\Cli::getBody' => ['mixed', 'key='=>'?string'], 'Yaf\Response\Cli::prependBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf\Response\Cli::setBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf\Response\Http::__clone' => ['void'], 'Yaf\Response\Http::__construct' => ['void'], 'Yaf\Response\Http::__destruct' => ['void'], 'Yaf\Response\Http::__toString' => ['string'], 'Yaf\Response\Http::appendBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf\Response\Http::clearBody' => ['bool', 'key='=>'string'], 'Yaf\Response\Http::clearHeaders' => ['Yaf\Response_Abstract|false', 'name='=>'string'], 'Yaf\Response\Http::getBody' => ['mixed', 'key='=>'?string'], 'Yaf\Response\Http::getHeader' => ['mixed', 'name='=>'string'], 'Yaf\Response\Http::prependBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf\Response\Http::response' => ['bool'], 'Yaf\Response\Http::setAllHeaders' => ['bool', 'headers'=>'array'], 'Yaf\Response\Http::setBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf\Response\Http::setHeader' => ['bool', 'name'=>'string', 'value'=>'string', 'replace='=>'bool', 'response_code='=>'int'], 'Yaf\Response\Http::setRedirect' => ['bool', 'url'=>'string'], 'Yaf\Response_Abstract::__clone' => ['void'], 'Yaf\Response_Abstract::__construct' => ['void'], 'Yaf\Response_Abstract::__destruct' => ['void'], 'Yaf\Response_Abstract::__toString' => ['void'], 'Yaf\Response_Abstract::appendBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf\Response_Abstract::clearBody' => ['bool', 'key='=>'string'], 'Yaf\Response_Abstract::getBody' => ['mixed', 'key='=>'?string'], 'Yaf\Response_Abstract::prependBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf\Response_Abstract::setBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf\Route\Map::__construct' => ['void', 'controller_prefer='=>'bool', 'delimiter='=>'string'], 'Yaf\Route\Map::assemble' => ['bool', 'info'=>'array', 'query='=>'?array'], 'Yaf\Route\Map::route' => ['bool', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Route\Regex::__construct' => ['void', 'match'=>'string', 'route'=>'array', 'map='=>'?array', 'verify='=>'?array', 'reverse='=>'string'], 'Yaf\Route\Regex::addConfig' => ['Yaf\Router|bool', 'config'=>'Yaf\Config_Abstract'], 'Yaf\Route\Regex::addRoute' => ['Yaf\Router|bool', 'name'=>'string', 'route'=>'Yaf\Route_Interface'], 'Yaf\Route\Regex::assemble' => ['bool', 'info'=>'array', 'query='=>'?array'], 'Yaf\Route\Regex::getCurrentRoute' => ['string'], 'Yaf\Route\Regex::getRoute' => ['Yaf\Route_Interface', 'name'=>'string'], 'Yaf\Route\Regex::getRoutes' => ['Yaf\Route_Interface[]'], 'Yaf\Route\Regex::route' => ['bool', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Route\Rewrite::__construct' => ['void', 'match'=>'string', 'route'=>'array', 'verify='=>'?array', 'reverse='=>'string'], 'Yaf\Route\Rewrite::addConfig' => ['Yaf\Router|bool', 'config'=>'Yaf\Config_Abstract'], 'Yaf\Route\Rewrite::addRoute' => ['Yaf\Router|bool', 'name'=>'string', 'route'=>'Yaf\Route_Interface'], 'Yaf\Route\Rewrite::assemble' => ['bool', 'info'=>'array', 'query='=>'?array'], 'Yaf\Route\Rewrite::getCurrentRoute' => ['string'], 'Yaf\Route\Rewrite::getRoute' => ['Yaf\Route_Interface', 'name'=>'string'], 'Yaf\Route\Rewrite::getRoutes' => ['Yaf\Route_Interface[]'], 'Yaf\Route\Rewrite::route' => ['bool', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Route\Simple::__construct' => ['void', 'module_name'=>'string', 'controller_name'=>'string', 'action_name'=>'string'], 'Yaf\Route\Simple::assemble' => ['bool', 'info'=>'array', 'query='=>'?array'], 'Yaf\Route\Simple::route' => ['bool', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Route\Supervar::__construct' => ['void', 'supervar_name'=>'string'], 'Yaf\Route\Supervar::assemble' => ['bool', 'info'=>'array', 'query='=>'?array'], 'Yaf\Route\Supervar::route' => ['bool', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Route_Interface::__construct' => ['Yaf\Route_Interface'], 'Yaf\Route_Interface::assemble' => ['bool', 'info'=>'array', 'query='=>'?array'], 'Yaf\Route_Interface::route' => ['bool', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Route_Static::assemble' => ['bool', 'info'=>'array', 'query='=>'?array'], 'Yaf\Route_Static::match' => ['bool', 'uri'=>'string'], 'Yaf\Route_Static::route' => ['bool', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Router::__construct' => ['void'], 'Yaf\Router::addConfig' => ['Yaf\Router|false', 'config'=>'Yaf\Config_Abstract'], 'Yaf\Router::addRoute' => ['Yaf\Router|false', 'name'=>'string', 'route'=>'Yaf\Route_Interface'], 'Yaf\Router::getCurrentRoute' => ['string'], 'Yaf\Router::getRoute' => ['Yaf\Route_Interface', 'name'=>'string'], 'Yaf\Router::getRoutes' => ['Yaf\Route_Interface[]'], 'Yaf\Router::route' => ['Yaf\Router|false', 'request'=>'Yaf\Request_Abstract'], 'Yaf\Session::__clone' => ['void'], 'Yaf\Session::__construct' => ['void'], 'Yaf\Session::__get' => ['void', 'name'=>''], 'Yaf\Session::__isset' => ['void', 'name'=>''], 'Yaf\Session::__set' => ['void', 'name'=>'', 'value'=>''], 'Yaf\Session::__sleep' => ['list'], 'Yaf\Session::__unset' => ['void', 'name'=>''], 'Yaf\Session::__wakeup' => ['void'], 'Yaf\Session::count' => ['int'], 'Yaf\Session::current' => ['mixed'], 'Yaf\Session::del' => ['Yaf\Session|false', 'name'=>'string'], 'Yaf\Session::get' => ['mixed', 'name'=>'string'], 'Yaf\Session::getInstance' => ['Yaf\Session'], '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::rewind' => ['void'], 'Yaf\Session::set' => ['Yaf\Session|false', 'name'=>'string', 'value'=>'mixed'], 'Yaf\Session::start' => ['Yaf\Session'], 'Yaf\Session::valid' => ['bool'], 'Yaf\View\Simple::__construct' => ['void', 'template_dir'=>'string', 'options='=>'?array'], 'Yaf\View\Simple::__get' => ['mixed', 'name='=>'null'], 'Yaf\View\Simple::__isset' => ['', 'name'=>'string'], 'Yaf\View\Simple::__set' => ['void', 'name'=>'string', 'value='=>'mixed'], 'Yaf\View\Simple::assign' => ['Yaf\View\Simple', 'name'=>'array|string', 'value='=>'mixed'], 'Yaf\View\Simple::assignRef' => ['Yaf\View\Simple', 'name'=>'string', '&value'=>'mixed'], 'Yaf\View\Simple::clear' => ['Yaf\View\Simple', 'name='=>'string'], 'Yaf\View\Simple::display' => ['bool', 'tpl'=>'string', 'tpl_vars='=>'?array'], 'Yaf\View\Simple::eval' => ['bool|void', 'tpl_str'=>'string', 'vars='=>'?array'], 'Yaf\View\Simple::getScriptPath' => ['string'], 'Yaf\View\Simple::render' => ['string|void', 'tpl'=>'string', 'tpl_vars='=>'?array'], 'Yaf\View\Simple::setScriptPath' => ['Yaf\View\Simple', 'template_dir'=>'string'], 'Yaf\View_Interface::assign' => ['bool', 'name'=>'array|string', 'value'=>'mixed'], 'Yaf\View_Interface::display' => ['bool', 'tpl'=>'string', 'tpl_vars='=>'?array'], 'Yaf\View_Interface::getScriptPath' => ['string'], 'Yaf\View_Interface::render' => ['string', 'tpl'=>'string', 'tpl_vars='=>'?array'], 'Yaf\View_Interface::setScriptPath' => ['void', 'template_dir'=>'string'], 'Yaf_Action_Abstract::__clone' => ['void'], 'Yaf_Action_Abstract::__construct' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract', 'view'=>'Yaf_View_Interface', 'invokeArgs='=>'?array'], 'Yaf_Action_Abstract::display' => ['bool', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf_Action_Abstract::execute' => ['mixed', 'arg='=>'mixed', '...args='=>'mixed'], 'Yaf_Action_Abstract::forward' => ['bool', 'module'=>'string', 'controller='=>'string', 'action='=>'string', 'parameters='=>'?array'], 'Yaf_Action_Abstract::getController' => ['Yaf_Controller_Abstract'], 'Yaf_Action_Abstract::getControllerName' => ['string'], 'Yaf_Action_Abstract::getInvokeArg' => ['mixed|null', 'name'=>'string'], 'Yaf_Action_Abstract::getInvokeArgs' => ['array'], 'Yaf_Action_Abstract::getModuleName' => ['string'], 'Yaf_Action_Abstract::getRequest' => ['Yaf_Request_Abstract'], 'Yaf_Action_Abstract::getResponse' => ['Yaf_Response_Abstract'], 'Yaf_Action_Abstract::getView' => ['Yaf_View_Interface'], 'Yaf_Action_Abstract::getViewpath' => ['string'], 'Yaf_Action_Abstract::init' => [''], 'Yaf_Action_Abstract::initView' => ['Yaf_Response_Abstract', 'options='=>'?array'], 'Yaf_Action_Abstract::redirect' => ['bool', 'url'=>'string'], 'Yaf_Action_Abstract::render' => ['string', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf_Action_Abstract::setViewpath' => ['bool', 'view_directory'=>'string'], 'Yaf_Application::__clone' => ['void'], 'Yaf_Application::__construct' => ['void', 'config'=>'mixed', 'envrion='=>'string'], 'Yaf_Application::__destruct' => ['void'], 'Yaf_Application::__sleep' => ['list'], 'Yaf_Application::__wakeup' => ['void'], 'Yaf_Application::app' => ['?Yaf_Application'], 'Yaf_Application::bootstrap' => ['Yaf_Application', 'bootstrap='=>'Yaf_Bootstrap_Abstract'], 'Yaf_Application::clearLastError' => ['Yaf_Application'], 'Yaf_Application::environ' => ['string'], 'Yaf_Application::execute' => ['void', 'entry'=>'callable', '...args'=>'string'], 'Yaf_Application::getAppDirectory' => ['Yaf_Application'], 'Yaf_Application::getConfig' => ['Yaf_Config_Abstract'], 'Yaf_Application::getDispatcher' => ['Yaf_Dispatcher'], 'Yaf_Application::getLastErrorMsg' => ['string'], 'Yaf_Application::getLastErrorNo' => ['int'], 'Yaf_Application::getModules' => ['array'], 'Yaf_Application::run' => ['void'], 'Yaf_Application::setAppDirectory' => ['Yaf_Application', 'directory'=>'string'], 'Yaf_Config_Abstract::__construct' => ['void'], 'Yaf_Config_Abstract::get' => ['mixed', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Config_Abstract::readonly' => ['bool'], 'Yaf_Config_Abstract::set' => ['Yaf_Config_Abstract'], 'Yaf_Config_Abstract::toArray' => ['array'], 'Yaf_Config_Ini::__construct' => ['void', 'config_file'=>'string', 'section='=>'string'], 'Yaf_Config_Ini::__get' => ['void', 'name='=>'string'], 'Yaf_Config_Ini::__isset' => ['void', 'name'=>'string'], 'Yaf_Config_Ini::__set' => ['void', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Config_Ini::count' => ['void'], 'Yaf_Config_Ini::current' => ['void'], 'Yaf_Config_Ini::get' => ['mixed', 'name='=>'mixed'], 'Yaf_Config_Ini::key' => ['void'], 'Yaf_Config_Ini::next' => ['void'], 'Yaf_Config_Ini::offsetExists' => ['void', 'name'=>'string'], 'Yaf_Config_Ini::offsetGet' => ['void', 'name'=>'string'], 'Yaf_Config_Ini::offsetSet' => ['void', 'name'=>'string', 'value'=>'string'], 'Yaf_Config_Ini::offsetUnset' => ['void', 'name'=>'string'], 'Yaf_Config_Ini::readonly' => ['void'], 'Yaf_Config_Ini::rewind' => ['void'], 'Yaf_Config_Ini::set' => ['Yaf_Config_Abstract', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Config_Ini::toArray' => ['array'], 'Yaf_Config_Ini::valid' => ['void'], 'Yaf_Config_Simple::__construct' => ['void', 'config_file'=>'string', 'section='=>'string'], 'Yaf_Config_Simple::__get' => ['void', 'name='=>'string'], 'Yaf_Config_Simple::__isset' => ['void', 'name'=>'string'], 'Yaf_Config_Simple::__set' => ['void', 'name'=>'string', 'value'=>'string'], 'Yaf_Config_Simple::count' => ['void'], 'Yaf_Config_Simple::current' => ['void'], 'Yaf_Config_Simple::get' => ['mixed', 'name='=>'mixed'], 'Yaf_Config_Simple::key' => ['void'], 'Yaf_Config_Simple::next' => ['void'], 'Yaf_Config_Simple::offsetExists' => ['void', 'name'=>'string'], 'Yaf_Config_Simple::offsetGet' => ['void', 'name'=>'string'], 'Yaf_Config_Simple::offsetSet' => ['void', 'name'=>'string', 'value'=>'string'], 'Yaf_Config_Simple::offsetUnset' => ['void', 'name'=>'string'], 'Yaf_Config_Simple::readonly' => ['void'], 'Yaf_Config_Simple::rewind' => ['void'], 'Yaf_Config_Simple::set' => ['Yaf_Config_Abstract', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Config_Simple::toArray' => ['array'], 'Yaf_Config_Simple::valid' => ['void'], 'Yaf_Controller_Abstract::__clone' => ['void'], 'Yaf_Controller_Abstract::__construct' => ['void'], 'Yaf_Controller_Abstract::display' => ['bool', 'tpl'=>'string', 'parameters='=>'array'], 'Yaf_Controller_Abstract::forward' => ['void', 'action'=>'string', 'parameters='=>'array'], 'Yaf_Controller_Abstract::forward\'1' => ['void', 'controller'=>'string', 'action'=>'string', 'parameters='=>'array'], 'Yaf_Controller_Abstract::forward\'2' => ['void', 'module'=>'string', 'controller'=>'string', 'action'=>'string', 'parameters='=>'array'], 'Yaf_Controller_Abstract::getInvokeArg' => ['void', 'name'=>'string'], 'Yaf_Controller_Abstract::getInvokeArgs' => ['void'], 'Yaf_Controller_Abstract::getModuleName' => ['string'], 'Yaf_Controller_Abstract::getName' => ['string'], 'Yaf_Controller_Abstract::getRequest' => ['Yaf_Request_Abstract'], 'Yaf_Controller_Abstract::getResponse' => ['Yaf_Response_Abstract'], 'Yaf_Controller_Abstract::getView' => ['Yaf_View_Interface'], 'Yaf_Controller_Abstract::getViewpath' => ['void'], 'Yaf_Controller_Abstract::init' => ['void'], 'Yaf_Controller_Abstract::initView' => ['void', 'options='=>'array'], 'Yaf_Controller_Abstract::redirect' => ['bool', 'url'=>'string'], 'Yaf_Controller_Abstract::render' => ['string', 'tpl'=>'string', 'parameters='=>'array'], 'Yaf_Controller_Abstract::setViewpath' => ['void', 'view_directory'=>'string'], 'Yaf_Dispatcher::__clone' => ['void'], 'Yaf_Dispatcher::__construct' => ['void'], 'Yaf_Dispatcher::__sleep' => ['list'], 'Yaf_Dispatcher::__wakeup' => ['void'], 'Yaf_Dispatcher::autoRender' => ['Yaf_Dispatcher', 'flag='=>'bool'], 'Yaf_Dispatcher::catchException' => ['Yaf_Dispatcher', 'flag='=>'bool'], 'Yaf_Dispatcher::disableView' => ['bool'], 'Yaf_Dispatcher::dispatch' => ['Yaf_Response_Abstract', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Dispatcher::enableView' => ['Yaf_Dispatcher'], 'Yaf_Dispatcher::flushInstantly' => ['Yaf_Dispatcher', 'flag='=>'bool'], 'Yaf_Dispatcher::getApplication' => ['Yaf_Application'], 'Yaf_Dispatcher::getDefaultAction' => ['string'], 'Yaf_Dispatcher::getDefaultController' => ['string'], 'Yaf_Dispatcher::getDefaultModule' => ['string'], 'Yaf_Dispatcher::getInstance' => ['Yaf_Dispatcher'], 'Yaf_Dispatcher::getRequest' => ['Yaf_Request_Abstract'], 'Yaf_Dispatcher::getRouter' => ['Yaf_Router'], 'Yaf_Dispatcher::initView' => ['Yaf_View_Interface', 'templates_dir'=>'string', 'options='=>'array'], 'Yaf_Dispatcher::registerPlugin' => ['Yaf_Dispatcher', 'plugin'=>'Yaf_Plugin_Abstract'], 'Yaf_Dispatcher::returnResponse' => ['Yaf_Dispatcher', 'flag'=>'bool'], 'Yaf_Dispatcher::setDefaultAction' => ['Yaf_Dispatcher', 'action'=>'string'], 'Yaf_Dispatcher::setDefaultController' => ['Yaf_Dispatcher', 'controller'=>'string'], 'Yaf_Dispatcher::setDefaultModule' => ['Yaf_Dispatcher', 'module'=>'string'], 'Yaf_Dispatcher::setErrorHandler' => ['Yaf_Dispatcher', 'callback'=>'callable', 'error_types'=>'int'], 'Yaf_Dispatcher::setRequest' => ['Yaf_Dispatcher', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Dispatcher::setView' => ['Yaf_Dispatcher', 'view'=>'Yaf_View_Interface'], 'Yaf_Dispatcher::throwException' => ['Yaf_Dispatcher', 'flag='=>'bool'], 'Yaf_Exception::__construct' => ['void'], 'Yaf_Exception::getPrevious' => ['void'], 'Yaf_Loader::__clone' => ['void'], 'Yaf_Loader::__construct' => ['void'], 'Yaf_Loader::__sleep' => ['list'], 'Yaf_Loader::__wakeup' => ['void'], 'Yaf_Loader::autoload' => ['void'], 'Yaf_Loader::clearLocalNamespace' => ['void'], 'Yaf_Loader::getInstance' => ['Yaf_Loader'], 'Yaf_Loader::getLibraryPath' => ['Yaf_Loader', 'is_global='=>'bool'], 'Yaf_Loader::getLocalNamespace' => ['void'], 'Yaf_Loader::getNamespacePath' => ['string', 'namespaces'=>'string'], 'Yaf_Loader::import' => ['bool'], 'Yaf_Loader::isLocalName' => ['bool'], 'Yaf_Loader::registerLocalNamespace' => ['void', 'prefix'=>'mixed'], 'Yaf_Loader::registerNamespace' => ['bool', 'namespaces'=>'string|array', 'path='=>'string'], 'Yaf_Loader::setLibraryPath' => ['Yaf_Loader', 'directory'=>'string', 'is_global='=>'bool'], 'Yaf_Plugin_Abstract::dispatchLoopShutdown' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::dispatchLoopStartup' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::postDispatch' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::preDispatch' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::preResponse' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::routerShutdown' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::routerStartup' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Registry::__clone' => ['void'], 'Yaf_Registry::__construct' => ['void'], 'Yaf_Registry::del' => ['void', 'name'=>'string'], 'Yaf_Registry::get' => ['mixed', 'name'=>'string'], 'Yaf_Registry::has' => ['bool', 'name'=>'string'], 'Yaf_Registry::set' => ['bool', 'name'=>'string', 'value'=>'string'], 'Yaf_Request_Abstract::clearParams' => ['bool'], 'Yaf_Request_Abstract::getActionName' => ['void'], 'Yaf_Request_Abstract::getBaseUri' => ['void'], 'Yaf_Request_Abstract::getControllerName' => ['void'], 'Yaf_Request_Abstract::getEnv' => ['void', 'name'=>'string', 'default='=>'string'], 'Yaf_Request_Abstract::getException' => ['void'], 'Yaf_Request_Abstract::getLanguage' => ['void'], 'Yaf_Request_Abstract::getMethod' => ['void'], 'Yaf_Request_Abstract::getModuleName' => ['void'], 'Yaf_Request_Abstract::getParam' => ['void', 'name'=>'string', 'default='=>'string'], 'Yaf_Request_Abstract::getParams' => ['void'], 'Yaf_Request_Abstract::getRequestUri' => ['void'], 'Yaf_Request_Abstract::getServer' => ['void', 'name'=>'string', 'default='=>'string'], 'Yaf_Request_Abstract::isCli' => ['void'], 'Yaf_Request_Abstract::isDispatched' => ['void'], 'Yaf_Request_Abstract::isGet' => ['void'], 'Yaf_Request_Abstract::isHead' => ['void'], 'Yaf_Request_Abstract::isOptions' => ['void'], 'Yaf_Request_Abstract::isPost' => ['void'], 'Yaf_Request_Abstract::isPut' => ['void'], 'Yaf_Request_Abstract::isRouted' => ['void'], 'Yaf_Request_Abstract::isXmlHttpRequest' => ['void'], 'Yaf_Request_Abstract::setActionName' => ['void', 'action'=>'string'], 'Yaf_Request_Abstract::setBaseUri' => ['bool', 'uir'=>'string'], 'Yaf_Request_Abstract::setControllerName' => ['void', 'controller'=>'string'], 'Yaf_Request_Abstract::setDispatched' => ['void'], 'Yaf_Request_Abstract::setModuleName' => ['void', 'module'=>'string'], 'Yaf_Request_Abstract::setParam' => ['void', 'name'=>'string', 'value='=>'string'], 'Yaf_Request_Abstract::setRequestUri' => ['void', 'uir'=>'string'], 'Yaf_Request_Abstract::setRouted' => ['void', 'flag='=>'string'], 'Yaf_Request_Http::__clone' => ['void'], 'Yaf_Request_Http::__construct' => ['void'], 'Yaf_Request_Http::get' => ['mixed', 'name'=>'string', 'default='=>'string'], 'Yaf_Request_Http::getActionName' => ['string'], 'Yaf_Request_Http::getBaseUri' => ['string'], 'Yaf_Request_Http::getControllerName' => ['string'], 'Yaf_Request_Http::getCookie' => ['mixed', 'name'=>'string', 'default='=>'string'], 'Yaf_Request_Http::getEnv' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf_Request_Http::getException' => ['Yaf_Exception'], 'Yaf_Request_Http::getFiles' => ['void'], 'Yaf_Request_Http::getLanguage' => ['string'], 'Yaf_Request_Http::getMethod' => ['string'], 'Yaf_Request_Http::getModuleName' => ['string'], 'Yaf_Request_Http::getParam' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'Yaf_Request_Http::getParams' => ['array'], 'Yaf_Request_Http::getPost' => ['mixed', 'name'=>'string', 'default='=>'string'], 'Yaf_Request_Http::getQuery' => ['mixed', 'name'=>'string', 'default='=>'string'], 'Yaf_Request_Http::getRaw' => ['mixed'], 'Yaf_Request_Http::getRequest' => ['void'], 'Yaf_Request_Http::getRequestUri' => ['string'], 'Yaf_Request_Http::getServer' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf_Request_Http::isCli' => ['bool'], 'Yaf_Request_Http::isDispatched' => ['bool'], 'Yaf_Request_Http::isGet' => ['bool'], 'Yaf_Request_Http::isHead' => ['bool'], 'Yaf_Request_Http::isOptions' => ['bool'], 'Yaf_Request_Http::isPost' => ['bool'], 'Yaf_Request_Http::isPut' => ['bool'], 'Yaf_Request_Http::isRouted' => ['bool'], 'Yaf_Request_Http::isXmlHttpRequest' => ['bool'], 'Yaf_Request_Http::setActionName' => ['Yaf_Request_Abstract|bool', 'action'=>'string'], 'Yaf_Request_Http::setBaseUri' => ['bool', 'uri'=>'string'], 'Yaf_Request_Http::setControllerName' => ['Yaf_Request_Abstract|bool', 'controller'=>'string'], 'Yaf_Request_Http::setDispatched' => ['bool'], 'Yaf_Request_Http::setModuleName' => ['Yaf_Request_Abstract|bool', 'module'=>'string'], 'Yaf_Request_Http::setParam' => ['Yaf_Request_Abstract|bool', 'name'=>'array|string', 'value='=>'string'], 'Yaf_Request_Http::setRequestUri' => ['', 'uri'=>'string'], 'Yaf_Request_Http::setRouted' => ['Yaf_Request_Abstract|bool'], 'Yaf_Request_Simple::__clone' => ['void'], 'Yaf_Request_Simple::__construct' => ['void'], 'Yaf_Request_Simple::get' => ['void'], 'Yaf_Request_Simple::getActionName' => ['string'], 'Yaf_Request_Simple::getBaseUri' => ['string'], 'Yaf_Request_Simple::getControllerName' => ['string'], 'Yaf_Request_Simple::getCookie' => ['void'], 'Yaf_Request_Simple::getEnv' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf_Request_Simple::getException' => ['Yaf_Exception'], 'Yaf_Request_Simple::getFiles' => ['void'], 'Yaf_Request_Simple::getLanguage' => ['string'], 'Yaf_Request_Simple::getMethod' => ['string'], 'Yaf_Request_Simple::getModuleName' => ['string'], 'Yaf_Request_Simple::getParam' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'Yaf_Request_Simple::getParams' => ['array'], 'Yaf_Request_Simple::getPost' => ['void'], 'Yaf_Request_Simple::getQuery' => ['void'], 'Yaf_Request_Simple::getRequest' => ['void'], 'Yaf_Request_Simple::getRequestUri' => ['string'], 'Yaf_Request_Simple::getServer' => ['mixed', 'name='=>'string', 'default='=>'mixed'], 'Yaf_Request_Simple::isCli' => ['bool'], 'Yaf_Request_Simple::isDispatched' => ['bool'], 'Yaf_Request_Simple::isGet' => ['bool'], 'Yaf_Request_Simple::isHead' => ['bool'], 'Yaf_Request_Simple::isOptions' => ['bool'], 'Yaf_Request_Simple::isPost' => ['bool'], 'Yaf_Request_Simple::isPut' => ['bool'], 'Yaf_Request_Simple::isRouted' => ['bool'], 'Yaf_Request_Simple::isXmlHttpRequest' => ['void'], 'Yaf_Request_Simple::setActionName' => ['Yaf_Request_Abstract|bool', 'action'=>'string'], 'Yaf_Request_Simple::setBaseUri' => ['bool', 'uri'=>'string'], 'Yaf_Request_Simple::setControllerName' => ['Yaf_Request_Abstract|bool', 'controller'=>'string'], 'Yaf_Request_Simple::setDispatched' => ['bool'], 'Yaf_Request_Simple::setModuleName' => ['Yaf_Request_Abstract|bool', 'module'=>'string'], 'Yaf_Request_Simple::setParam' => ['Yaf_Request_Abstract|bool', 'name'=>'array|string', 'value='=>'string'], 'Yaf_Request_Simple::setRequestUri' => ['', 'uri'=>'string'], 'Yaf_Request_Simple::setRouted' => ['Yaf_Request_Abstract|bool'], 'Yaf_Response_Abstract::__clone' => ['void'], 'Yaf_Response_Abstract::__construct' => ['void'], 'Yaf_Response_Abstract::__destruct' => ['void'], 'Yaf_Response_Abstract::__toString' => ['string'], 'Yaf_Response_Abstract::appendBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf_Response_Abstract::clearBody' => ['bool', 'key='=>'string'], 'Yaf_Response_Abstract::clearHeaders' => ['void'], 'Yaf_Response_Abstract::getBody' => ['mixed', 'key='=>'string'], 'Yaf_Response_Abstract::getHeader' => ['void'], 'Yaf_Response_Abstract::prependBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf_Response_Abstract::response' => ['void'], 'Yaf_Response_Abstract::setAllHeaders' => ['void'], 'Yaf_Response_Abstract::setBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf_Response_Abstract::setHeader' => ['void'], 'Yaf_Response_Abstract::setRedirect' => ['void'], 'Yaf_Response_Cli::__clone' => ['void'], 'Yaf_Response_Cli::__construct' => ['void'], 'Yaf_Response_Cli::__destruct' => ['void'], 'Yaf_Response_Cli::__toString' => ['string'], 'Yaf_Response_Cli::appendBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf_Response_Cli::clearBody' => ['bool', 'key='=>'string'], 'Yaf_Response_Cli::getBody' => ['mixed', 'key='=>'?string'], 'Yaf_Response_Cli::prependBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf_Response_Cli::setBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf_Response_Http::__clone' => ['void'], 'Yaf_Response_Http::__construct' => ['void'], 'Yaf_Response_Http::__destruct' => ['void'], 'Yaf_Response_Http::__toString' => ['string'], 'Yaf_Response_Http::appendBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf_Response_Http::clearBody' => ['bool', 'key='=>'string'], 'Yaf_Response_Http::clearHeaders' => ['Yaf_Response_Abstract|false', 'name='=>'string'], 'Yaf_Response_Http::getBody' => ['mixed', 'key='=>'?string'], 'Yaf_Response_Http::getHeader' => ['mixed', 'name='=>'string'], 'Yaf_Response_Http::prependBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf_Response_Http::response' => ['bool'], 'Yaf_Response_Http::setAllHeaders' => ['bool', 'headers'=>'array'], 'Yaf_Response_Http::setBody' => ['bool', 'content'=>'string', 'key='=>'string'], 'Yaf_Response_Http::setHeader' => ['bool', 'name'=>'string', 'value'=>'string', 'replace='=>'bool', 'response_code='=>'int'], 'Yaf_Response_Http::setRedirect' => ['bool', 'url'=>'string'], 'Yaf_Route_Interface::__construct' => ['void'], 'Yaf_Route_Interface::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Interface::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Map::__construct' => ['void', 'controller_prefer='=>'string', 'delimiter='=>'string'], 'Yaf_Route_Map::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Map::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Regex::__construct' => ['void', 'match'=>'string', 'route'=>'array', 'map='=>'array', 'verify='=>'array', 'reverse='=>'string'], 'Yaf_Route_Regex::addConfig' => ['Yaf_Router|bool', 'config'=>'Yaf_Config_Abstract'], 'Yaf_Route_Regex::addRoute' => ['Yaf_Router|bool', 'name'=>'string', 'route'=>'Yaf_Route_Interface'], 'Yaf_Route_Regex::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Regex::getCurrentRoute' => ['string'], 'Yaf_Route_Regex::getRoute' => ['Yaf_Route_Interface', 'name'=>'string'], 'Yaf_Route_Regex::getRoutes' => ['Yaf_Route_Interface[]'], 'Yaf_Route_Regex::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Rewrite::__construct' => ['void', 'match'=>'string', 'route'=>'array', 'verify='=>'array'], 'Yaf_Route_Rewrite::addConfig' => ['Yaf_Router|bool', 'config'=>'Yaf_Config_Abstract'], 'Yaf_Route_Rewrite::addRoute' => ['Yaf_Router|bool', 'name'=>'string', 'route'=>'Yaf_Route_Interface'], 'Yaf_Route_Rewrite::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Rewrite::getCurrentRoute' => ['string'], 'Yaf_Route_Rewrite::getRoute' => ['Yaf_Route_Interface', 'name'=>'string'], 'Yaf_Route_Rewrite::getRoutes' => ['Yaf_Route_Interface[]'], 'Yaf_Route_Rewrite::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Simple::__construct' => ['void', 'module_name'=>'string', 'controller_name'=>'string', 'action_name'=>'string'], 'Yaf_Route_Simple::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Simple::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Static::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Static::match' => ['void', 'uri'=>'string'], 'Yaf_Route_Static::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Supervar::__construct' => ['void', 'supervar_name'=>'string'], 'Yaf_Route_Supervar::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Supervar::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Router::__construct' => ['void'], 'Yaf_Router::addConfig' => ['bool', 'config'=>'Yaf_Config_Abstract'], 'Yaf_Router::addRoute' => ['bool', 'name'=>'string', 'route'=>'Yaf_Route_Interface'], 'Yaf_Router::getCurrentRoute' => ['string'], 'Yaf_Router::getRoute' => ['Yaf_Route_Interface', 'name'=>'string'], 'Yaf_Router::getRoutes' => ['mixed'], 'Yaf_Router::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Session::__clone' => ['void'], 'Yaf_Session::__construct' => ['void'], 'Yaf_Session::__get' => ['void', 'name'=>'string'], 'Yaf_Session::__isset' => ['void', 'name'=>'string'], 'Yaf_Session::__set' => ['void', 'name'=>'string', 'value'=>'string'], 'Yaf_Session::__sleep' => ['list'], 'Yaf_Session::__unset' => ['void', 'name'=>'string'], 'Yaf_Session::__wakeup' => ['void'], 'Yaf_Session::count' => ['void'], 'Yaf_Session::current' => ['void'], 'Yaf_Session::del' => ['void', 'name'=>'string'], 'Yaf_Session::get' => ['mixed', 'name'=>'string'], 'Yaf_Session::getInstance' => ['void'], 'Yaf_Session::has' => ['void', 'name'=>'string'], 'Yaf_Session::key' => ['void'], 'Yaf_Session::next' => ['void'], 'Yaf_Session::offsetExists' => ['void', 'name'=>'string'], 'Yaf_Session::offsetGet' => ['void', 'name'=>'string'], 'Yaf_Session::offsetSet' => ['void', 'name'=>'string', 'value'=>'string'], 'Yaf_Session::offsetUnset' => ['void', 'name'=>'string'], 'Yaf_Session::rewind' => ['void'], 'Yaf_Session::set' => ['Yaf_Session|bool', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Session::start' => ['void'], 'Yaf_Session::valid' => ['void'], 'Yaf_View_Interface::assign' => ['bool', 'name'=>'string', 'value='=>'string'], 'Yaf_View_Interface::display' => ['bool', 'tpl'=>'string', 'tpl_vars='=>'array'], 'Yaf_View_Interface::getScriptPath' => ['string'], 'Yaf_View_Interface::render' => ['string', 'tpl'=>'string', 'tpl_vars='=>'array'], 'Yaf_View_Interface::setScriptPath' => ['void', 'template_dir'=>'string'], 'Yaf_View_Simple::__construct' => ['void', 'tempalte_dir'=>'string', 'options='=>'array'], 'Yaf_View_Simple::__get' => ['void', 'name='=>'string'], 'Yaf_View_Simple::__isset' => ['void', 'name'=>'string'], 'Yaf_View_Simple::__set' => ['void', 'name'=>'string', 'value'=>'mixed'], 'Yaf_View_Simple::assign' => ['bool', 'name'=>'string', 'value='=>'mixed'], 'Yaf_View_Simple::assignRef' => ['bool', 'name'=>'string', '&rw_value'=>'mixed'], 'Yaf_View_Simple::clear' => ['bool', 'name='=>'string'], 'Yaf_View_Simple::display' => ['bool', 'tpl'=>'string', 'tpl_vars='=>'array'], 'Yaf_View_Simple::eval' => ['string', 'tpl_content'=>'string', 'tpl_vars='=>'array'], 'Yaf_View_Simple::getScriptPath' => ['string'], 'Yaf_View_Simple::render' => ['string', 'tpl'=>'string', 'tpl_vars='=>'array'], 'Yaf_View_Simple::setScriptPath' => ['bool', 'template_dir'=>'string'], 'yaml_emit' => ['string', 'data'=>'mixed', 'encoding='=>'int', 'linebreak='=>'int'], 'yaml_emit_file' => ['bool', 'filename'=>'string', 'data'=>'mixed', 'encoding='=>'int', 'linebreak='=>'int'], 'yaml_parse' => ['mixed|false', 'input'=>'string', 'pos='=>'int', '&w_ndocs='=>'int', 'callbacks='=>'array'], 'yaml_parse_file' => ['mixed|false', 'filename'=>'string', 'pos='=>'int', '&w_ndocs='=>'int', 'callbacks='=>'array'], 'yaml_parse_url' => ['mixed|false', 'url'=>'string', 'pos='=>'int', '&w_ndocs='=>'int', 'callbacks='=>'array'], 'Yar_Client::__call' => ['void', 'method'=>'string', 'parameters'=>'array'], 'Yar_Client::__construct' => ['void', 'url'=>'string'], 'Yar_Client::setOpt' => ['Yar_Client|false', 'name'=>'int', 'value'=>'mixed'], 'Yar_Client_Exception::__clone' => ['void'], 'Yar_Client_Exception::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'Yar_Client_Exception::__toString' => ['string'], 'Yar_Client_Exception::__wakeup' => ['void'], 'Yar_Client_Exception::getCode' => ['int'], 'Yar_Client_Exception::getFile' => ['string'], 'Yar_Client_Exception::getLine' => ['int'], 'Yar_Client_Exception::getMessage' => ['string'], 'Yar_Client_Exception::getPrevious' => ['?Exception|?Throwable'], 'Yar_Client_Exception::getTrace' => ['list>'], 'Yar_Client_Exception::getTraceAsString' => ['string'], 'Yar_Client_Exception::getType' => ['string'], 'Yar_Concurrent_Client::call' => ['int', 'uri'=>'string', 'method'=>'string', 'parameters'=>'array', 'callback='=>'callable'], 'Yar_Concurrent_Client::loop' => ['bool', 'callback='=>'callable', 'error_callback='=>'callable'], 'Yar_Concurrent_Client::reset' => ['bool'], 'Yar_Server::__construct' => ['void', 'object'=>'Object'], 'Yar_Server::handle' => ['bool'], 'Yar_Server_Exception::__clone' => ['void'], 'Yar_Server_Exception::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Exception|?Throwable'], 'Yar_Server_Exception::__toString' => ['string'], 'Yar_Server_Exception::__wakeup' => ['void'], 'Yar_Server_Exception::getCode' => ['int'], 'Yar_Server_Exception::getFile' => ['string'], 'Yar_Server_Exception::getLine' => ['int'], 'Yar_Server_Exception::getMessage' => ['string'], 'Yar_Server_Exception::getPrevious' => ['?Exception|?Throwable'], 'Yar_Server_Exception::getTrace' => ['list>'], 'Yar_Server_Exception::getTraceAsString' => ['string'], 'Yar_Server_Exception::getType' => ['string'], 'yaz_addinfo' => ['string', 'id'=>'resource'], 'yaz_ccl_conf' => ['void', 'id'=>'resource', 'config'=>'array'], 'yaz_ccl_parse' => ['bool', 'id'=>'resource', 'query'=>'string', '&w_result'=>'array'], 'yaz_close' => ['bool', 'id'=>'resource'], 'yaz_connect' => ['mixed', 'zurl'=>'string', 'options='=>'mixed'], 'yaz_database' => ['bool', 'id'=>'resource', 'databases'=>'string'], 'yaz_element' => ['bool', 'id'=>'resource', 'elementset'=>'string'], 'yaz_errno' => ['int', 'id'=>'resource'], 'yaz_error' => ['string', 'id'=>'resource'], 'yaz_es' => ['void', 'id'=>'resource', 'type'=>'string', 'args'=>'array'], 'yaz_es_result' => ['array', 'id'=>'resource'], 'yaz_get_option' => ['string', 'id'=>'resource', 'name'=>'string'], 'yaz_hits' => ['int', 'id'=>'resource', 'searchresult='=>'array'], 'yaz_itemorder' => ['void', 'id'=>'resource', 'args'=>'array'], 'yaz_present' => ['bool', 'id'=>'resource'], 'yaz_range' => ['void', 'id'=>'resource', 'start'=>'int', 'number'=>'int'], 'yaz_record' => ['string', 'id'=>'resource', 'pos'=>'int', 'type'=>'string'], 'yaz_scan' => ['void', 'id'=>'resource', 'type'=>'string', 'startterm'=>'string', 'flags='=>'array'], 'yaz_scan_result' => ['array', 'id'=>'resource', 'result='=>'array'], 'yaz_schema' => ['void', 'id'=>'resource', 'schema'=>'string'], 'yaz_search' => ['bool', 'id'=>'resource', 'type'=>'string', 'query'=>'string'], 'yaz_set_option' => ['', 'id'=>'', 'name'=>'string', 'value'=>'string', 'options'=>'array'], 'yaz_sort' => ['void', 'id'=>'resource', 'criteria'=>'string'], 'yaz_syntax' => ['void', 'id'=>'resource', 'syntax'=>'string'], 'yaz_wait' => ['mixed', '&rw_options='=>'array'], 'yp_all' => ['void', 'domain'=>'string', 'map'=>'string', 'callback'=>'string'], 'yp_cat' => ['array', 'domain'=>'string', 'map'=>'string'], 'yp_err_string' => ['string', 'errorcode'=>'int'], 'yp_errno' => ['int'], 'yp_first' => ['array', 'domain'=>'string', 'map'=>'string'], 'yp_get_default_domain' => ['string'], 'yp_master' => ['string', 'domain'=>'string', 'map'=>'string'], 'yp_match' => ['string', 'domain'=>'string', 'map'=>'string', 'key'=>'string'], 'yp_next' => ['array', 'domain'=>'string', 'map'=>'string', 'key'=>'string'], 'yp_order' => ['int', 'domain'=>'string', 'map'=>'string'], 'zem_get_extension_info_by_id' => [''], 'zem_get_extension_info_by_name' => [''], 'zem_get_extensions_info' => [''], 'zem_get_license_info' => [''], 'zend_current_obfuscation_level' => ['int'], 'zend_disk_cache_clear' => ['bool', 'namespace='=>'mixed|string'], 'zend_disk_cache_delete' => ['mixed|null', 'key'=>'string'], 'zend_disk_cache_fetch' => ['mixed|null', 'key'=>'string'], 'zend_disk_cache_store' => ['bool', 'key'=>'', 'value'=>'', 'ttl='=>'int|mixed'], 'zend_get_id' => ['array', 'all_ids='=>'all_ids|false'], 'zend_is_configuration_changed' => [''], 'zend_loader_current_file' => ['string'], 'zend_loader_enabled' => ['bool'], 'zend_loader_file_encoded' => ['bool'], 'zend_loader_file_licensed' => ['array'], 'zend_loader_install_license' => ['bool', 'license_file'=>'string', 'override'=>'bool'], 'zend_logo_guid' => ['string'], 'zend_obfuscate_class_name' => ['string', 'class_name'=>'string'], 'zend_obfuscate_function_name' => ['string', 'function_name'=>'string'], 'zend_optimizer_version' => ['string'], 'zend_runtime_obfuscate' => ['void'], 'zend_send_buffer' => ['null|false', 'buffer'=>'string', 'mime_type='=>'string', 'custom_headers='=>'string'], 'zend_send_file' => ['null|false', 'filename'=>'string', 'mime_type='=>'string', 'custom_headers='=>'string'], 'zend_set_configuration_changed' => [''], 'zend_shm_cache_clear' => ['bool', 'namespace='=>'mixed|string'], 'zend_shm_cache_delete' => ['mixed|null', 'key'=>'string'], 'zend_shm_cache_fetch' => ['mixed|null', 'key'=>'string'], 'zend_shm_cache_store' => ['bool', 'key'=>'', 'value'=>'', 'ttl='=>'int|mixed'], 'zend_thread_id' => ['int'], 'zend_version' => ['string'], 'ZendAPI_Job::addJobToQueue' => ['int', 'jobqueue_url'=>'string', 'password'=>'string'], 'ZendAPI_Job::getApplicationID' => [''], 'ZendAPI_Job::getEndTime' => [''], 'ZendAPI_Job::getGlobalVariables' => [''], 'ZendAPI_Job::getHost' => [''], 'ZendAPI_Job::getID' => [''], 'ZendAPI_Job::getInterval' => [''], 'ZendAPI_Job::getJobDependency' => [''], 'ZendAPI_Job::getJobName' => [''], 'ZendAPI_Job::getJobPriority' => [''], 'ZendAPI_Job::getJobStatus' => ['int'], 'ZendAPI_Job::getLastPerformedStatus' => ['int'], 'ZendAPI_Job::getOutput' => ['An'], 'ZendAPI_Job::getPreserved' => [''], 'ZendAPI_Job::getProperties' => ['array'], 'ZendAPI_Job::getScheduledTime' => [''], 'ZendAPI_Job::getScript' => [''], 'ZendAPI_Job::getTimeToNextRepeat' => ['int'], 'ZendAPI_Job::getUserVariables' => [''], 'ZendAPI_Job::setApplicationID' => ['', 'app_id'=>''], 'ZendAPI_Job::setGlobalVariables' => ['', 'vars'=>''], 'ZendAPI_Job::setJobDependency' => ['', 'job_id'=>''], 'ZendAPI_Job::setJobName' => ['', 'name'=>''], 'ZendAPI_Job::setJobPriority' => ['', 'priority'=>'int'], 'ZendAPI_Job::setPreserved' => ['', 'preserved'=>''], 'ZendAPI_Job::setRecurrenceData' => ['', 'interval'=>'', 'end_time='=>'mixed'], 'ZendAPI_Job::setScheduledTime' => ['', 'timestamp'=>''], 'ZendAPI_Job::setScript' => ['', 'script'=>''], 'ZendAPI_Job::setUserVariables' => ['', 'vars'=>''], 'ZendAPI_Job::ZendAPI_Job' => ['Job', 'script'=>'script'], 'ZendAPI_Queue::addJob' => ['int', '&job'=>'Job'], 'ZendAPI_Queue::getAllApplicationIDs' => ['array'], 'ZendAPI_Queue::getAllhosts' => ['array'], 'ZendAPI_Queue::getHistoricJobs' => ['array', 'status'=>'int', 'start_time'=>'', 'end_time'=>'', 'index'=>'int', 'count'=>'int', '&total'=>'int'], 'ZendAPI_Queue::getJob' => ['Job', 'job_id'=>'int'], 'ZendAPI_Queue::getJobsInQueue' => ['array', 'filter_options='=>'array', 'max_jobs='=>'int', 'with_globals_and_output='=>'bool'], 'ZendAPI_Queue::getLastError' => ['string'], 'ZendAPI_Queue::getNumOfJobsInQueue' => ['int', 'filter_options='=>'array'], 'ZendAPI_Queue::getStatistics' => ['array'], 'ZendAPI_Queue::isScriptExists' => ['bool', 'path'=>'string'], 'ZendAPI_Queue::isSuspend' => ['bool'], 'ZendAPI_Queue::login' => ['bool', 'password'=>'string', 'application_id='=>'int'], 'ZendAPI_Queue::removeJob' => ['bool', 'job_id'=>'array|int'], 'ZendAPI_Queue::requeueJob' => ['bool', 'job'=>'Job'], 'ZendAPI_Queue::resumeJob' => ['bool', 'job_id'=>'array|int'], 'ZendAPI_Queue::resumeQueue' => ['bool'], 'ZendAPI_Queue::setMaxHistoryTime' => ['bool'], 'ZendAPI_Queue::suspendJob' => ['bool', 'job_id'=>'array|int'], 'ZendAPI_Queue::suspendQueue' => ['bool'], 'ZendAPI_Queue::updateJob' => ['int', '&job'=>'Job'], 'ZendAPI_Queue::zendapi_queue' => ['ZendAPI_Queue', 'queue_url'=>'string'], 'zip_close' => ['void', 'zip'=>'resource'], 'zip_entry_close' => ['bool', 'zip_ent'=>'resource'], 'zip_entry_compressedsize' => ['int', 'zip_entry'=>'resource'], 'zip_entry_compressionmethod' => ['string', 'zip_entry'=>'resource'], 'zip_entry_filesize' => ['int', 'zip_entry'=>'resource'], 'zip_entry_name' => ['string', 'zip_entry'=>'resource'], 'zip_entry_open' => ['bool', 'zip_dp'=>'resource', 'zip_entry'=>'resource', 'mode='=>'string'], 'zip_entry_read' => ['string|false', 'zip_entry'=>'resource', 'length='=>'int'], 'zip_open' => ['resource|int|false', 'filename'=>'string'], 'zip_read' => ['resource', 'zip'=>'resource'], 'ZipArchive::addEmptyDir' => ['bool', 'dirname'=>'string'], 'ZipArchive::addFile' => ['bool', 'filepath'=>'string', 'entryname='=>'string', 'start='=>'int', 'length='=>'int'], 'ZipArchive::addFromString' => ['bool', 'entryname'=>'string', 'content'=>'string'], 'ZipArchive::addGlob' => ['bool', 'pattern'=>'string', 'flags='=>'int', 'options='=>'array'], 'ZipArchive::addPattern' => ['bool', 'pattern'=>'string', 'path='=>'string', 'options='=>'array'], 'ZipArchive::close' => ['bool'], 'ZipArchive::count' => ['int'], 'ZipArchive::createEmptyDir' => ['bool', 'dirname'=>'string'], 'ZipArchive::deleteIndex' => ['bool', 'index'=>'int'], 'ZipArchive::deleteName' => ['bool', 'name'=>'string'], 'ZipArchive::extractTo' => ['bool', 'pathto'=>'string', 'files='=>'string[]|string'], 'ZipArchive::getArchiveComment' => ['string|false', 'flags='=>'int'], 'ZipArchive::getCommentIndex' => ['string|false', 'index'=>'int', 'flags='=>'int'], 'ZipArchive::getCommentName' => ['string|false', 'name'=>'string', 'flags='=>'int'], 'ZipArchive::getExternalAttributesIndex' => ['bool', 'index'=>'int', '&w_opsys'=>'int', '&w_attr'=>'int', 'flags='=>'int'], 'ZipArchive::getExternalAttributesName' => ['bool', 'name'=>'string', '&w_opsys'=>'int', '&w_attr'=>'int', 'flags='=>'int'], 'ZipArchive::getFromIndex' => ['string|false', 'index'=>'int', 'length='=>'int', 'flags='=>'int'], 'ZipArchive::getFromName' => ['string|false', 'entryname'=>'string', 'length='=>'int', 'flags='=>'int'], 'ZipArchive::getNameIndex' => ['string|false', 'index'=>'int', 'flags='=>'int'], 'ZipArchive::getStatusString' => ['string|false'], 'ZipArchive::getStream' => ['resource|false', 'entryname'=>'string'], 'ZipArchive::isCompressionMethodSupported' => ['bool', 'method'=>'int', 'encode='=>'bool'], 'ZipArchive::isEncryptionMethodSupported' => ['bool', 'method'=>'int', 'encode='=>'bool'], 'ZipArchive::locateName' => ['int|false', 'filename'=>'string', 'flags='=>'int'], 'ZipArchive::open' => ['int|bool', 'source'=>'string', 'flags='=>'int'], 'ZipArchive::registerCancelCallback' => ['bool', 'callback'=>'callable'], 'ZipArchive::registerProgressCallback' => ['bool', 'rate'=>'float', 'callback'=>'callable'], 'ZipArchive::renameIndex' => ['bool', 'index'=>'int', 'new_name'=>'string'], 'ZipArchive::renameName' => ['bool', 'name'=>'string', 'new_name'=>'string'], 'ZipArchive::replaceFile' => ['bool', 'filename'=>'string', 'index'=>'int', 'start='=>'int', 'length='=>'int', 'flags='=>'int'], 'ZipArchive::setArchiveComment' => ['bool', 'comment'=>'string'], 'ZipArchive::setCommentIndex' => ['bool', 'index'=>'int', 'comment'=>'string'], 'ZipArchive::setCommentName' => ['bool', 'name'=>'string', 'comment'=>'string'], 'ZipArchive::setCompressionIndex' => ['bool', 'index'=>'int', 'comp_method'=>'int', 'comp_flags='=>'int'], 'ZipArchive::setCompressionName' => ['bool', 'name'=>'string', 'comp_method'=>'int', 'comp_flags='=>'int'], 'ZipArchive::setEncryptionIndex' => ['bool', 'index'=>'int', 'method'=>'string', 'password='=>'string'], 'ZipArchive::setEncryptionName' => ['bool', 'name'=>'string', 'method'=>'int', 'password='=>'string'], 'ZipArchive::setExternalAttributesIndex' => ['bool', 'index'=>'int', 'opsys'=>'int', 'attr'=>'int', 'flags='=>'int'], 'ZipArchive::setExternalAttributesName' => ['bool', 'name'=>'string', 'opsys'=>'int', 'attr'=>'int', 'flags='=>'int'], 'ZipArchive::setMtimeIndex' => ['bool', 'index'=>'int', 'timestamp'=>'int', 'flags='=>'int'], 'ZipArchive::setMtimeName' => ['bool', 'name'=>'string', 'timestamp'=>'int', 'flags='=>'int'], 'ZipArchive::setPassword' => ['bool', 'password'=>'string'], 'ZipArchive::statIndex' => ['array|false', 'index'=>'int', 'flags='=>'int'], 'ZipArchive::statName' => ['array|false', 'filename'=>'string', 'flags='=>'int'], 'ZipArchive::unchangeAll' => ['bool'], 'ZipArchive::unchangeArchive' => ['bool'], 'ZipArchive::unchangeIndex' => ['bool', 'index'=>'int'], 'ZipArchive::unchangeName' => ['bool', 'name'=>'string'], 'zlib_decode' => ['string|false', 'data'=>'string', 'max_decoded_len='=>'int'], 'zlib_encode' => ['string', 'data'=>'string', 'encoding'=>'int', 'level='=>'string|int'], 'zlib_get_coding_type' => ['string|false'], 'ZMQ::__construct' => ['void'], 'ZMQContext::__construct' => ['void', 'io_threads='=>'int', 'is_persistent='=>'bool'], 'ZMQContext::getOpt' => ['int|string', 'key'=>'string'], 'ZMQContext::getSocket' => ['ZMQSocket', 'type'=>'int', 'persistent_id='=>'string', 'on_new_socket='=>'callable'], 'ZMQContext::isPersistent' => ['bool'], 'ZMQContext::setOpt' => ['ZMQContext', 'key'=>'int', 'value'=>'mixed'], 'ZMQDevice::__construct' => ['void', 'frontend'=>'ZMQSocket', 'backend'=>'ZMQSocket', 'listener='=>'ZMQSocket'], 'ZMQDevice::getIdleTimeout' => ['ZMQDevice'], 'ZMQDevice::getTimerTimeout' => ['ZMQDevice'], 'ZMQDevice::run' => ['void'], 'ZMQDevice::setIdleCallback' => ['ZMQDevice', 'cb_func'=>'callable', 'timeout'=>'int', 'user_data='=>'mixed'], 'ZMQDevice::setIdleTimeout' => ['ZMQDevice', 'timeout'=>'int'], 'ZMQDevice::setTimerCallback' => ['ZMQDevice', 'cb_func'=>'callable', 'timeout'=>'int', 'user_data='=>'mixed'], 'ZMQDevice::setTimerTimeout' => ['ZMQDevice', 'timeout'=>'int'], 'ZMQPoll::add' => ['string', 'entry'=>'mixed', 'type'=>'int'], 'ZMQPoll::clear' => ['ZMQPoll'], 'ZMQPoll::count' => ['int'], 'ZMQPoll::getLastErrors' => ['array'], 'ZMQPoll::poll' => ['int', '&w_readable'=>'array', '&w_writable'=>'array', 'timeout='=>'int'], 'ZMQPoll::remove' => ['bool', 'item'=>'mixed'], 'ZMQSocket::__construct' => ['void', 'context'=>'ZMQContext', 'type'=>'int', 'persistent_id='=>'string', 'on_new_socket='=>'callable'], 'ZMQSocket::bind' => ['ZMQSocket', 'dsn'=>'string', 'force='=>'bool'], 'ZMQSocket::connect' => ['ZMQSocket', 'dsn'=>'string', 'force='=>'bool'], 'ZMQSocket::disconnect' => ['ZMQSocket', 'dsn'=>'string'], 'ZMQSocket::getEndpoints' => ['array'], 'ZMQSocket::getPersistentId' => ['?string'], 'ZMQSocket::getSocketType' => ['int'], 'ZMQSocket::getSockOpt' => ['int|string', 'key'=>'string'], 'ZMQSocket::isPersistent' => ['bool'], 'ZMQSocket::recv' => ['string', 'mode='=>'int'], 'ZMQSocket::recvMulti' => ['string[]', 'mode='=>'int'], 'ZMQSocket::send' => ['ZMQSocket', 'message'=>'array', 'mode='=>'int'], 'ZMQSocket::send\'1' => ['ZMQSocket', 'message'=>'string', 'mode='=>'int'], 'ZMQSocket::sendmulti' => ['ZMQSocket', 'message'=>'array', 'mode='=>'int'], 'ZMQSocket::setSockOpt' => ['ZMQSocket', 'key'=>'int', 'value'=>'mixed'], 'ZMQSocket::unbind' => ['ZMQSocket', 'dsn'=>'string'], 'Zookeeper::addAuth' => ['bool', 'scheme'=>'string', 'cert'=>'string', 'completion_cb='=>'callable'], 'Zookeeper::close' => ['void'], 'Zookeeper::connect' => ['void', 'host'=>'string', 'watcher_cb='=>'callable', 'recv_timeout='=>'int'], 'Zookeeper::create' => ['string', 'path'=>'string', 'value'=>'string', 'acls'=>'array', 'flags='=>'int'], 'Zookeeper::delete' => ['bool', 'path'=>'string', 'version='=>'int'], 'Zookeeper::exists' => ['bool', 'path'=>'string', 'watcher_cb='=>'callable'], 'Zookeeper::get' => ['string', 'path'=>'string', 'watcher_cb='=>'callable', 'stat='=>'array', 'max_size='=>'int'], 'Zookeeper::getAcl' => ['array', 'path'=>'string'], 'Zookeeper::getChildren' => ['array|false', 'path'=>'string', 'watcher_cb='=>'callable'], 'Zookeeper::getClientId' => ['int'], 'Zookeeper::getConfig' => ['ZookeeperConfig'], 'Zookeeper::getRecvTimeout' => ['int'], 'Zookeeper::getState' => ['int'], 'Zookeeper::isRecoverable' => ['bool'], 'Zookeeper::set' => ['bool', 'path'=>'string', 'value'=>'string', 'version='=>'int', 'stat='=>'array'], 'Zookeeper::setAcl' => ['bool', 'path'=>'string', 'version'=>'int', 'acl'=>'array'], 'Zookeeper::setDebugLevel' => ['bool', 'logLevel'=>'int'], 'Zookeeper::setDeterministicConnOrder' => ['bool', 'yesOrNo'=>'bool'], 'Zookeeper::setLogStream' => ['bool', 'stream'=>'resource'], 'Zookeeper::setWatcher' => ['bool', 'watcher_cb'=>'callable'], 'zookeeper_dispatch' => ['void'], 'ZookeeperConfig::add' => ['void', 'members'=>'string', 'version='=>'int', 'stat='=>'array'], 'ZookeeperConfig::get' => ['string', 'watcher_cb='=>'callable', 'stat='=>'array'], 'ZookeeperConfig::remove' => ['void', 'id_list'=>'string', 'version='=>'int', 'stat='=>'array'], 'ZookeeperConfig::set' => ['void', 'members'=>'string', 'version='=>'int', 'stat='=>'array'], ]; [ 'DOMNodeList::count' => ['int'], 'ftp_append' => ['bool', 'ftp'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int'], 'hash_copy' => ['HashContext', 'context'=>'HashContext'], 'hash_final' => ['string', 'context'=>'HashContext', 'raw_output='=>'bool'], 'hash_hmac_algos' => ['array'], 'hash_init' => ['HashContext', 'algo'=>'string', 'options='=>'int', 'key='=>'string'], 'hash_update' => ['bool', 'context'=>'HashContext', 'data'=>'string'], 'hash_update_file' => ['bool', 'context='=>'HashContext', 'filename'=>'string', 'scontext='=>'?HashContext'], 'hash_update_stream' => ['int', 'context'=>'HashContext', 'handle'=>'', 'length='=>'int'], 'imagebmp' => ['bool', 'image'=>'resource', 'to='=>'mixed', 'compressed='=>'bool'], 'imagecreatefrombmp' => ['resource', 'filename'=>'string'], 'imageopenpolygon' => ['bool', 'image'=>'resource', 'points'=>'array', 'num_points'=>'int', 'color'=>'int'], 'imageresolution' => ['mixed', 'image'=>'resource', 'res_x='=>'int', 'res_y='=>'int'], 'imagesetclip' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int'], 'ldap_exop' => ['mixed', 'link'=>'resource', 'reqoid'=>'string', 'reqdata='=>'string', 'servercontrols='=>'array', 'retdata='=>'string', 'retoid='=>'string'], 'ldap_exop_passwd' => ['mixed', 'link'=>'resource', 'user='=>'string', 'oldpw='=>'string', 'newpw='=>'string', 'serverctrls='=>'array'], 'ldap_exop_refresh' => ['int', 'link'=>'resource', 'dn'=>'string', 'ttl'=>'int'], 'ldap_exop_whoami' => ['string', 'link'=>'resource'], 'ldap_parse_exop' => ['bool', 'link'=>'resource', 'result'=>'resource', 'retdata='=>'string', 'retoid='=>'string'], 'mb_chr' => ['string', 'cp'=>'int', 'encoding='=>'string'], 'mb_ord' => ['int', 'str'=>'string', 'enc='=>'string'], 'mb_scrub' => ['string', 'str'=>'string', 'enc='=>'string'], 'oci_register_taf_callback' => ['bool', 'connection'=>'resource', 'callback='=>'callable'], 'oci_unregister_taf_callback' => ['bool', 'connection'=>'resource'], 'ReflectionClass::isIterable' => ['bool'], 'SQLite3::openBlob' => ['resource', 'table'=>'string', 'column'=>'string', 'rowid'=>'int', 'dbname'=>'string', 'flags='=>'int'], 'sapi_windows_vt100_support' => ['bool', 'stream'=>'resource', 'enable='=>'bool'], 'socket_addrinfo_bind' => ['resource', 'addrinfo'=>'resource'], 'socket_addrinfo_connect' => ['resource', 'addrinfo'=>'resource'], 'socket_addrinfo_explain' => ['array', 'addrinfo'=>'resource'], 'socket_addrinfo_lookup' => ['resource[]', 'node'=>'string', 'service='=>'mixed', 'hints='=>'array'], 'sodium_add' => ['string', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_base642bin' => ['string', 'base64'=>'string', 'variant'=>'int', 'ignore='=>'string'], 'sodium_bin2base64' => ['string', 'binary'=>'string', 'variant'=>'int'], 'sodium_bin2hex' => ['string', 'binary'=>'string'], 'sodium_compare' => ['int', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_crypto_aead_aes256gcm_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_aes256gcm_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_aes256gcm_is_available' => ['bool'], 'sodium_crypto_aead_aes256gcm_keygen' => ['string'], 'sodium_crypto_aead_chacha20poly1305_decrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_keygen' => ['string'], 'sodium_crypto_aead_chacha20poly1305_keygen' => ['string'], 'sodium_crypto_aead_xchacha20poly1305_ietf_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_xchacha20poly1305_ietf_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_xchacha20poly1305_ietf_keygen' => ['string'], 'sodium_crypto_auth' => ['string', 'message'=>'string', 'key'=>'string'], 'sodium_crypto_auth_keygen' => ['string'], 'sodium_crypto_auth_verify' => ['bool', 'mac'=>'string', 'message'=>'string', 'key'=>'string'], 'sodium_crypto_box' => ['string', 'string'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_box_keypair' => ['string'], 'sodium_crypto_box_keypair_from_secretkey_and_publickey' => ['string', 'secret_key'=>'string', 'public_key'=>'string'], 'sodium_crypto_box_open' => ['string|false', 'message'=>'string', 'nonce'=>'string', 'message_keypair'=>'string'], 'sodium_crypto_box_publickey' => ['string', 'keypair'=>'string'], 'sodium_crypto_box_publickey_from_secretkey' => ['string', 'secretkey'=>'string'], 'sodium_crypto_box_seal' => ['string', 'message'=>'string', 'publickey'=>'string'], 'sodium_crypto_box_seal_open' => ['string|false', 'message'=>'string', 'recipient_keypair'=>'string'], 'sodium_crypto_box_secretkey' => ['string', 'keypair'=>'string'], 'sodium_crypto_box_seed_keypair' => ['string', 'seed'=>'string'], 'sodium_crypto_generichash' => ['string', 'msg'=>'string', 'key='=>'?string', 'length='=>'?int'], 'sodium_crypto_generichash_final' => ['string', 'state'=>'string', 'length='=>'?int'], 'sodium_crypto_generichash_init' => ['string', 'key='=>'?string', 'length='=>'?int'], 'sodium_crypto_generichash_keygen' => ['string'], 'sodium_crypto_generichash_update' => ['bool', 'state'=>'string', 'string'=>'string'], 'sodium_crypto_kdf_derive_from_key' => ['string', 'subkey_len'=>'int', 'subkey_id'=>'int', 'context'=>'string', 'key'=>'string'], 'sodium_crypto_kdf_keygen' => ['string'], 'sodium_crypto_kx_client_session_keys' => ['string', 'client_keypair'=>'string', 'server_key'=>'string'], 'sodium_crypto_kx_keypair' => ['string'], 'sodium_crypto_kx_publickey' => ['string', 'keypair'=>'string'], 'sodium_crypto_kx_secretkey' => ['string', 'keypair'=>'string'], 'sodium_crypto_kx_seed_keypair' => ['string', 'seed'=>'string'], 'sodium_crypto_kx_server_session_keys' => ['string', 'server_keypair'=>'string', 'client_key'=>'string'], 'sodium_crypto_pwhash' => ['string', 'length'=>'int', 'password'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int', 'alg='=>'int'], 'sodium_crypto_pwhash_scryptsalsa208sha256' => ['string', 'length'=>'int', 'password'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_scryptsalsa208sha256_str' => ['string', 'password'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_scryptsalsa208sha256_str_verify' => ['bool', 'hash'=>'string', 'password'=>'string'], 'sodium_crypto_pwhash_str' => ['string', 'password'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_str_needs_rehash' => ['bool', 'password'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_str_verify' => ['bool', 'hash'=>'string', 'password'=>'string'], 'sodium_crypto_scalarmult' => ['string', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_crypto_scalarmult_base' => ['string', 'secretkey'=>'string'], 'sodium_crypto_secretbox' => ['string', 'plaintext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_secretbox_keygen' => ['string'], 'sodium_crypto_secretbox_open' => ['string|false', 'ciphertext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_init_pull' => ['string', 'header'=>'string', 'key'=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_init_push' => ['array', 'key'=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_keygen' => ['string'], 'sodium_crypto_secretstream_xchacha20poly1305_pull' => ['array', 'state'=>'string', 'c'=>'string', 'ad='=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_push' => ['string', 'state'=>'string', 'msg'=>'string', 'ad='=>'string', 'tag='=>'int'], 'sodium_crypto_secretstream_xchacha20poly1305_rekey' => ['void', 'state'=>'string'], 'sodium_crypto_shorthash' => ['string', 'message'=>'string', 'key'=>'string'], 'sodium_crypto_shorthash_keygen' => ['string'], 'sodium_crypto_sign' => ['string', 'message'=>'string', 'secretkey'=>'string'], 'sodium_crypto_sign_detached' => ['string', 'message'=>'string', 'secretkey'=>'string'], 'sodium_crypto_sign_ed25519_pk_to_curve25519' => ['string', 'ed25519pk'=>'string'], 'sodium_crypto_sign_ed25519_sk_to_curve25519' => ['string', 'ed25519sk'=>'string'], 'sodium_crypto_sign_keypair' => ['string'], 'sodium_crypto_sign_keypair_from_secretkey_and_publickey' => ['string', 'secret_key'=>'string', 'public_key'=>'string'], 'sodium_crypto_sign_open' => ['string|false', 'message'=>'string', 'publickey'=>'string'], 'sodium_crypto_sign_publickey' => ['string', 'keypair'=>'string'], 'sodium_crypto_sign_publickey_from_secretkey' => ['string', 'secretkey'=>'string'], 'sodium_crypto_sign_secretkey' => ['string', 'keypair'=>'string'], 'sodium_crypto_sign_seed_keypair' => ['string', 'seed'=>'string'], 'sodium_crypto_sign_verify_detached' => ['bool', 'signature'=>'string', 'message'=>'string', 'publickey'=>'string'], 'sodium_crypto_stream' => ['string', 'length'=>'int', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_stream_keygen' => ['string'], 'sodium_crypto_stream_xor' => ['string', 'message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_hex2bin' => ['string', 'hex'=>'string', 'ignore='=>'string'], 'sodium_increment' => ['string', '&binary_string'=>'string'], 'sodium_memcmp' => ['int', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_memzero' => ['void', '&secret'=>'string'], 'sodium_pad' => ['string', 'unpadded'=>'string', 'length'=>'int'], 'sodium_unpad' => ['string', 'padded'=>'string', 'length'=>'int'], 'stream_isatty' => ['bool', 'stream'=>'resource'], 'ZipArchive::count' => ['int'], 'ZipArchive::setEncryptionIndex' => ['bool', 'index'=>'int', 'method'=>'string', 'password='=>'string'], 'ZipArchive::setEncryptionName' => ['bool', 'name'=>'string', 'method'=>'int', 'password='=>'string'], ], 'old' => [ 'hash_copy' => ['resource', 'context'=>'resource'], 'hash_final' => ['string', 'context'=>'resource', 'raw_output='=>'bool'], 'hash_hkdf' => ['string', 'algo'=>'string', 'ikm'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'], 'hash_init' => ['resource', 'algo'=>'string', 'options='=>'int', 'key='=>'string'], 'hash_pbkdf2' => ['string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'], 'hash_update' => ['bool', 'context'=>'resource', 'data'=>'string'], 'hash_update_file' => ['bool', 'hcontext'=>'resource', 'filename'=>'string', 'scontext='=>'?resource'], 'hash_update_stream' => ['int', 'context'=>'resource', 'handle'=>'resource', 'length='=>'int'], 'SQLite3::openBlob' => ['resource', 'table'=>'string', 'column'=>'string', 'rowid'=>'int', 'dbname'=>'string'], ] ]; [ 'array_key_first' => ['int|string|null', 'array'=>'array'], 'array_key_last' => ['int|string|null', 'array'=>'array'], 'DateTime::createFromImmutable' => ['static', 'datetime'=>'DateTimeImmutable'], 'fpm_get_status' => ['array'], 'gmp_binomial' => ['GMP', 'n'=>'GMP|string|int', 'k'=>'GMP|string|int'], 'gmp_lcm' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_perfect_power' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_kronecker' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'JsonException::__clone' => [''], 'JsonException::__construct' => [''], 'JsonException::__toString' => [''], 'JsonException::__wakeup' => [''], 'JsonException::getCode' => [''], 'JsonException::getFile' => [''], 'JsonException::getLine' => [''], 'JsonException::getMessage' => [''], 'JsonException::getPrevious' => [''], 'JsonException::getTrace' => [''], 'JsonException::getTraceAsString' => [''], 'net_get_interfaces' => ['array>|false'], 'openssl_pkey_derive' => ['string|false', 'peer_pub_key'=>'mixed', 'priv_key'=>'mixed', 'keylen='=>'?int'], 'gc_status' => ['array{runs:int,collected:int,threshold:int,roots:int}'], 'hrtime' => ['array{0:int,1:int}|false', 'get_as_number='=>'false'], 'hrtime\'1' => ['int|float|false', 'get_as_number='=>'true'], 'is_countable' => ['bool', 'var'=>'mixed'], 'session_set_cookie_params\'1' => ['bool', 'options'=>'array{lifetime?:int,path?:string,domain?:?string,secure?:bool,httponly?:bool}'], 'setcookie' => ['bool', 'name'=>'string', 'value='=>'string', 'options='=>'array'], 'setrawcookie' => ['bool', 'name'=>'string', 'value='=>'string', 'options='=>'array'], 'socket_wsaprotocol_info_export' => ['string|false', 'sock='=>'resource','pid'=>'int'], 'socket_wsaprotocol_info_import' => ['resource|false', 'id'=>'string'], 'socket_wsaprotocol_info_release' => ['bool', 'id'=>'string'], 'SplPriorityQueue::isCorrupted' => ['bool'], ], 'old' => [ 'setcookie' => ['bool', 'name'=>'string', 'value='=>'string', 'expires='=>'int', 'path='=>'string', 'domain='=>'string', 'secure='=>'bool', 'httponly='=>'bool'], 'setrawcookie' => ['bool', 'name'=>'string', 'value='=>'string', 'expires='=>'int', 'path='=>'string', 'domain='=>'string', 'secure='=>'bool', 'httponly='=>'bool'], ] ]; strtolower($a) <=> strtolower($b)); foreach ($new_local as $name => $data) { if (!is_array($data)) { throw new \UnexpectedValueException('bad data for ' . $name); } $return_type = array_shift($data); echo '\'' . str_replace("'", "\'", $name) . '\' => [\'' . str_replace("'", "\'", $return_type) . '\''; if ($data) { $signature = []; foreach ($data as $param_name => $type) { $signature[] = '\'' . str_replace("'", "\'", $param_name) . '\'=>\'' . str_replace("'", "\'", $type) . '\''; } echo ', ' . implode(', ', $signature); } echo '],' . "\n"; } function get_changed_functions(array $a, array $b) { $changed_functions = []; foreach (array_intersect_key($a, $b) as $function_name => $a_data) { if (json_encode($b[$function_name]) !== json_encode($a_data)) { $changed_functions[$function_name] = $b[$function_name]; } } return $changed_functions; } [ 'password_hash' => ['string|null', 'password'=>'string', 'algo'=>'int|string|null', 'options='=>'array'], 'password_needs_rehash' => ['bool', 'hash'=>'string', 'algo'=>'int|string|null', 'options='=>'array'], 'proc_open' => ['resource|false', 'command'=>'string|array', 'descriptorspec'=>'array', '&w_pipes'=>'resource[]', 'cwd='=>'?string', 'env='=>'?array', 'other_options='=>'array'], 'ReflectionProperty::getType' => ['?ReflectionType'], ], 'old' => [ 'password_hash' => ['string|false', 'password'=>'string', 'algo'=>'int', 'options='=>'array'], 'password_needs_rehash' => ['bool', 'hash'=>'string', 'algo'=>'int', 'options='=>'array'], 'proc_open' => ['resource|false', 'command'=>'string', 'descriptorspec'=>'array', '&w_pipes'=>'resource[]', 'cwd='=>'?string', 'env='=>'?array', 'other_options='=>'array'], ] ]; [ 'array_combine' => ['associative-array', 'keys'=>'string[]|int[]', 'values'=>'array'], 'bcdiv' => ['string', 'dividend'=>'string', 'divisor'=>'string', 'scale='=>'int'], 'bcmod' => ['string', 'dividend'=>'string', 'divisor'=>'string', 'scale='=>'int'], 'bcpowmod' => ['string', 'base'=>'string', 'exponent'=>'string', 'modulus'=>'string', 'scale='=>'int'], 'com_load_typelib' => ['bool', 'typelib_name'=>'string', 'case_insensitive='=>'true'], 'count_chars' => ['array|string', 'input'=>'string', 'mode='=>'int'], 'curl_close' => ['void', 'ch'=>'CurlHandle'], 'curl_copy_handle' => ['CurlHandle', 'ch'=>'CurlHandle'], 'curl_errno' => ['int', 'ch'=>'CurlHandle'], 'curl_error' => ['string', 'ch'=>'CurlHandle'], 'curl_escape' => ['string|false', 'ch'=>'CurlHandle', 'string'=>'string'], 'curl_exec' => ['bool|string', 'ch'=>'CurlHandle'], 'curl_getinfo' => ['mixed', 'ch'=>'CurlHandle', 'option='=>'int'], 'curl_init' => ['CurlHandle|false', 'url='=>'string'], 'curl_multi_add_handle' => ['int', 'mh'=>'CurlMultiHandle', 'ch'=>'CurlHandle'], 'curl_multi_close' => ['void', 'mh'=>'CurlMultiHandle'], 'curl_multi_errno' => ['int', 'mh'=>'CurlMultiHandle'], 'curl_multi_exec' => ['int', 'mh'=>'CurlMultiHandle', '&w_still_running'=>'int'], 'curl_multi_getcontent' => ['string', 'ch'=>'CurlMultiHandle'], 'curl_multi_info_read' => ['array|false', 'mh'=>'CurlMultiHandle', '&w_msgs_in_queue='=>'int'], 'curl_multi_init' => ['CurlMultiHandle|false'], 'curl_multi_remove_handle' => ['int', 'mh'=>'CurlMultiHandle', 'ch'=>'CurlHandle'], 'curl_multi_select' => ['int', 'mh'=>'CurlMultiHandle', 'timeout='=>'float'], 'curl_multi_setopt' => ['bool', 'mh'=>'CurlMultiHandle', 'option'=>'int', 'value'=>'mixed'], 'curl_pause' => ['int', 'ch'=>'CurlHandle', 'bitmask'=>'int'], 'curl_reset' => ['void', 'ch'=>'CurlHandle'], 'curl_setopt' => ['bool', 'ch'=>'CurlHandle', 'option'=>'int', 'value'=>'callable|mixed'], 'curl_setopt_array' => ['bool', 'ch'=>'CurlHandle', 'options'=>'array'], 'curl_share_close' => ['void', 'sh'=>'CurlShareHandle'], 'curl_share_errno' => ['int', 'sh'=>'CurlShareHandle'], 'curl_share_init' => ['CurlShareHandle'], 'curl_share_setopt' => ['bool', 'sh'=>'CurlShareHandle', 'option'=>'int', 'value'=>'mixed'], 'curl_unescape' => ['string|false', 'ch'=>'CurlShareHandle', 'string'=>'string'], 'date_add' => ['DateTime', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_date_set' => ['DateTime', 'object'=>'DateTime', 'year'=>'int', 'month'=>'int', 'day'=>'int'], 'date_diff' => ['DateInterval', 'obj1'=>'DateTimeInterface', 'obj2'=>'DateTimeInterface', 'absolute='=>'bool'], 'date_format' => ['string', 'object'=>'DateTimeInterface', 'format'=>'string'], 'date_isodate_set' => ['DateTime', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'day='=>'int|mixed'], 'date_parse' => ['array', 'date'=>'string'], 'date_sub' => ['DateTime', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_sun_info' => ['array', 'time'=>'int', 'latitude'=>'float', 'longitude'=>'float'], 'date_time_set' => ['DateTime', 'object'=>'DateTime', 'hour'=>'int', 'minute'=>'int', 'second='=>'int', 'microseconds='=>'int'], 'date_timestamp_set' => ['DateTime', 'object'=>'DateTime', 'unixtimestamp'=>'int'], 'date_timezone_set' => ['DateTime', 'object'=>'DateTime', 'timezone'=>'DateTimeZone'], 'explode' => ['array', 'separator'=>'string', 'str'=>'string', 'limit='=>'int'], 'fdiv' => ['float', 'dividend'=>'float', 'divisor'=>'float'], 'get_debug_type' => ['string', 'var'=>'mixed'], 'get_resource_id' => ['int', 'res'=>'resource'], 'gmdate' => ['string', 'format'=>'string', 'timestamp='=>'int'], 'gmmktime' => ['int|false', 'hour'=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'hash_hkdf' => ['string', 'algo'=>'string', 'ikm'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'], 'imageaffine' => ['false|GdImage', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'], 'imagecreate' => ['false|GdImage', 'x_size'=>'int', 'y_size'=>'int'], 'imagecreatefrombmp' => ['false|GdImage', 'filename'=>'string'], 'imagecreatefromgd' => ['false|GdImage', 'filename'=>'string'], 'imagecreatefromgd2' => ['false|GdImage', 'filename'=>'string'], 'imagecreatefromgd2part' => ['false|GdImage', 'filename'=>'string', 'srcx'=>'int', 'srcy'=>'int', 'width'=>'int', 'height'=>'int'], 'imagecreatefromgif' => ['false|GdImage', 'filename'=>'string'], 'imagecreatefromjpeg' => ['false|GdImage', 'filename'=>'string'], 'imagecreatefrompng' => ['false|GdImage', 'filename'=>'string'], 'imagecreatefromstring' => ['false|GdImage', 'image'=>'string'], 'imagecreatefromwbmp' => ['false|GdImage', 'filename'=>'string'], 'imagecreatefromwebp' => ['false|GdImage', 'filename'=>'string'], 'imagecreatefromxbm' => ['false|GdImage', 'filename'=>'string'], 'imagecreatefromxpm' => ['false|GdImage', 'filename'=>'string'], 'imagecreatetruecolor' => ['false|GdImage', 'x_size'=>'int', 'y_size'=>'int'], 'imagecrop' => ['false|GdImage', 'im'=>'resource', 'rect'=>'array'], 'imagecropauto' => ['false|GdImage', 'im'=>'resource', 'mode'=>'int', 'threshold'=>'float', 'color'=>'int'], 'imagegetclip' => ['array', 'im'=>'resource'], 'imagegrabscreen' => ['false|GdImage'], 'imagegrabwindow' => ['false|GdImage', 'window_handle'=>'int', 'client_area='=>'int'], 'imagerotate' => ['false|GdImage', 'src_im'=>'resource', 'angle'=>'float', 'bgdcolor'=>'int', 'ignoretransparent='=>'int'], 'imagescale' => ['false|GdImage', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'], 'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string'], 'mktime' => ['int|false', 'hour'=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'parse_str' => ['void', 'encoded_string'=>'string', '&w_result'=>'array'], 'password_hash' => ['string', 'password'=>'string', 'algo'=>'?string|?int', 'options='=>'array'], 'PhpToken::getAll' => ['list', 'code'=>'string', 'flags='=>'int'], 'PhpToken::is' => ['bool', 'kind'=>'string|int|string[]|int[]'], 'PhpToken::isIgnorable' => ['bool'], 'PhpToken::getTokenName' => ['string'], 'proc_get_status' => ['array', 'process'=>'resource'], 'socket_accept' => ['Socket|false', 'socket'=>'Socket'], 'socket_addrinfo_bind' => ['?Socket', 'addrinfo'=>'AddressInfo'], 'socket_addrinfo_connect' => ['?Socket', 'addrinfo'=>'AddressInfo'], 'socket_addrinfo_explain' => ['array', 'addrinfo'=>'AddressInfo'], 'socket_addrinfo_lookup' => ['AddressInfo[]', 'node'=>'string', 'service='=>'mixed', 'hints='=>'array'], 'socket_bind' => ['bool', 'socket'=>'Socket', 'addr'=>'string', 'port='=>'int'], 'socket_clear_error' => ['void', 'socket='=>'Socket'], 'socket_close' => ['void', 'socket'=>'Socket'], 'socket_connect' => ['bool', 'socket'=>'Socket', 'addr'=>'string', 'port='=>'int'], 'socket_create' => ['Socket|false', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int'], 'socket_create_listen' => ['Socket|false', 'port'=>'int', 'backlog='=>'int'], 'socket_create_pair' => ['bool', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int', '&w_fd'=>'Socket[]'], 'socket_export_stream' => ['resource|false', 'socket'=>'Socket'], 'socket_get_option' => ['mixed|false', 'socket'=>'Socket', 'level'=>'int', 'optname'=>'int'], 'socket_get_status' => ['array', 'stream'=>'Socket'], 'socket_getopt' => ['mixed', 'socket'=>'Socket', 'level'=>'int', 'optname'=>'int'], 'socket_getpeername' => ['bool', 'socket'=>'Socket', '&w_addr'=>'string', '&w_port='=>'int'], 'socket_getsockname' => ['bool', 'socket'=>'Socket', '&w_addr'=>'string', '&w_port='=>'int'], 'socket_import_stream' => ['Socket|false|null', 'stream'=>'resource'], 'socket_last_error' => ['int', 'socket='=>'Socket'], 'socket_listen' => ['bool', 'socket'=>'Socket', 'backlog='=>'int'], 'socket_read' => ['string|false', 'socket'=>'Socket', 'length'=>'int', 'type='=>'int'], 'socket_recv' => ['int|false', 'socket'=>'Socket', '&w_buf'=>'string', 'length'=>'int', 'flags'=>'int'], 'socket_recvfrom' => ['int|false', 'socket'=>'Socket', '&w_buf'=>'string', 'length'=>'int', 'flags'=>'int', '&w_name'=>'string', '&w_port='=>'int'], 'socket_recvmsg' => ['int|false', 'socket'=>'Socket', '&w_message'=>'string', 'flags='=>'int'], 'socket_select' => ['int|false', '&rw_read_fds'=>'Socket[]|null', '&rw_write_fds'=>'Socket[]|null', '&rw_except_fds'=>'Socket[]|null', 'tv_sec'=>'int', 'tv_usec='=>'int'], 'socket_send' => ['int|false', 'socket'=>'Socket', 'buf'=>'string', 'length'=>'int', 'flags'=>'int'], 'socket_sendmsg' => ['int|false', 'socket'=>'Socket', 'message'=>'array', 'flags'=>'int'], 'socket_sendto' => ['int|false', 'socket'=>'Socket', 'buf'=>'string', 'length'=>'int', 'flags'=>'int', 'addr'=>'string', 'port='=>'int'], 'socket_set_block' => ['bool', 'socket'=>'Socket'], 'socket_set_blocking' => ['bool', 'socket'=>'Socket', 'mode'=>'int'], 'socket_set_nonblock' => ['bool', 'socket'=>'Socket'], 'socket_set_option' => ['bool', 'socket'=>'Socket', 'level'=>'int', 'optname'=>'int', 'optval'=>'int|string|array'], 'socket_set_timeout' => ['bool', 'stream'=>'resource', 'seconds'=>'int', 'microseconds='=>'int'], 'socket_setopt' => ['void', 'socket'=>'Socket', 'level'=>'int', 'optname'=>'int', 'optval'=>'int|string|array'], 'socket_shutdown' => ['bool', 'socket'=>'Socket', 'how='=>'int'], 'socket_strerror' => ['string', 'errno'=>'int'], 'socket_write' => ['int|false', 'socket'=>'Socket', 'buf'=>'string', 'length='=>'int'], 'socket_wsaprotocol_info_export' => ['string|false', 'stream'=>'resource', 'target_pid'=>'int'], 'socket_wsaprotocol_info_import' => ['Socket|false', 'id'=>'string'], 'socket_wsaprotocol_info_release' => ['bool', 'id'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'str_contains' => ['bool', 'haystack'=>'string', 'needle'=>'string'], 'str_ends_with' => ['bool', 'haystack'=>'string', 'needle'=>'string'], 'str_starts_with' => ['bool', 'haystack'=>'string', 'needle'=>'string'], 'strchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'before_needle='=>'bool'], 'stripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'before_needle='=>'bool'], 'strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'strrchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string'], 'strripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'before_needle='=>'bool'], 'xml_parser_create' => ['XMLParser', 'encoding='=>'string'], 'xml_parser_create_ns' => ['XMLParser', 'encoding='=>'string', 'sep='=>'string'], 'xml_parser_free' => ['bool', 'parser'=>'XMLParser'], 'xml_parser_get_option' => ['mixed|false', 'parser'=>'XMLParser', 'option'=>'int'], 'xml_parser_set_option' => ['bool', 'parser'=>'XMLParser', 'option'=>'int', 'value'=>'mixed'], 'xmlwriter_end_attribute' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_cdata' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_comment' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_document' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_dtd' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_dtd_attlist' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_dtd_element' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_dtd_entity' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_element' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_pi' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_flush' => ['mixed', 'xmlwriter'=>'XMLWriter', 'empty='=>'bool'], 'xmlwriter_full_end_element' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_open_memory' => ['XMLWriter'], 'xmlwriter_open_uri' => ['XMLWriter', 'source'=>'string'], 'xmlwriter_output_memory' => ['string', 'xmlwriter'=>'XMLWriter', 'flush='=>'bool'], 'xmlwriter_set_indent' => ['bool', 'xmlwriter'=>'XMLWriter', 'indent'=>'bool'], 'xmlwriter_set_indent_string' => ['bool', 'xmlwriter'=>'XMLWriter', 'indentstring'=>'string'], 'xmlwriter_start_attribute' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string'], 'xmlwriter_start_attribute_ns' => ['bool', 'xmlwriter'=>'XMLWriter', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'xmlwriter_start_cdata' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_start_comment' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_start_document' => ['bool', 'xmlwriter'=>'XMLWriter', 'version='=>'string', 'encoding='=>'string', 'standalone='=>'string'], 'xmlwriter_start_dtd' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string'], 'xmlwriter_start_dtd_attlist' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string'], 'xmlwriter_start_dtd_element' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string'], 'xmlwriter_start_dtd_entity' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'isparam'=>'bool'], 'xmlwriter_start_element' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string'], 'xmlwriter_start_element_ns' => ['bool', 'xmlwriter'=>'XMLWriter', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'xmlwriter_start_pi' => ['bool', 'xmlwriter'=>'XMLWriter', 'target'=>'string'], 'xmlwriter_text' => ['bool', 'xmlwriter'=>'XMLWriter', 'content'=>'string'], 'xmlwriter_write_attribute' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_attribute_ns' => ['bool', 'xmlwriter'=>'XMLWriter', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_cdata' => ['bool', 'xmlwriter'=>'XMLWriter', 'content'=>'string'], 'xmlwriter_write_comment' => ['bool', 'xmlwriter'=>'XMLWriter', 'content'=>'string'], 'xmlwriter_write_dtd' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string', 'subset='=>'string'], 'xmlwriter_write_dtd_attlist' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_element' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_entity' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string', 'pe'=>'bool', 'publicid'=>'string', 'sysid'=>'string', 'ndataid'=>'string'], 'xmlwriter_write_element' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_element_ns' => ['bool', 'xmlwriter'=>'XMLWriter', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_pi' => ['bool', 'xmlwriter'=>'XMLWriter', 'target'=>'string', 'content'=>'string'], 'xmlwriter_write_raw' => ['bool', 'xmlwriter'=>'XMLWriter', 'content'=>'string'], ], 'old' => [ 'array_combine' => ['associative-array|false', 'keys'=>'string[]|int[]', 'values'=>'array'], 'bcdiv' => ['?string', 'dividend'=>'string', 'divisor'=>'string', 'scale='=>'int'], 'bcmod' => ['?string', 'dividend'=>'string', 'divisor'=>'string', 'scale='=>'int'], 'bcpowmod' => ['?string', 'base'=>'string', 'exponent'=>'string', 'modulus'=>'string', 'scale='=>'int'], 'com_load_typelib' => ['bool', 'typelib_name'=>'string', 'case_insensitive='=>'bool'], 'count_chars' => ['array|false|string', 'input'=>'string', 'mode='=>'int'], 'create_function' => ['string', 'args'=>'string', 'code'=>'string'], 'curl_close' => ['void', 'ch'=>'resource'], 'curl_copy_handle' => ['resource', 'ch'=>'resource'], 'curl_errno' => ['int', 'ch'=>'resource'], 'curl_error' => ['string', 'ch'=>'resource'], 'curl_escape' => ['string|false', 'ch'=>'resource', 'string'=>'string'], 'curl_exec' => ['bool|string', 'ch'=>'resource'], 'curl_file_create' => ['CURLFile', 'filename'=>'string', 'mimetype='=>'string', 'postfilename='=>'string'], 'curl_getinfo' => ['mixed', 'ch'=>'resource', 'option='=>'int'], 'curl_init' => ['resource|false', 'url='=>'string'], 'curl_multi_add_handle' => ['int', 'mh'=>'resource', 'ch'=>'resource'], 'curl_multi_close' => ['void', 'mh'=>'resource'], 'curl_multi_errno' => ['int', 'mh'=>'resource'], 'curl_multi_exec' => ['int', 'mh'=>'resource', '&w_still_running'=>'int'], 'curl_multi_getcontent' => ['string', 'ch'=>'resource'], 'curl_multi_info_read' => ['array|false', 'mh'=>'resource', '&w_msgs_in_queue='=>'int'], 'curl_multi_init' => ['resource|false'], 'curl_multi_remove_handle' => ['int', 'mh'=>'resource', 'ch'=>'resource'], 'curl_multi_select' => ['int', 'mh'=>'resource', 'timeout='=>'float'], 'curl_multi_setopt' => ['bool', 'mh'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'curl_pause' => ['int', 'ch'=>'resource', 'bitmask'=>'int'], 'curl_reset' => ['void', 'ch'=>'resource'], 'curl_setopt' => ['bool', 'ch'=>'resource', 'option'=>'int', 'value'=>'callable|mixed'], 'curl_setopt_array' => ['bool', 'ch'=>'resource', 'options'=>'array'], 'curl_share_close' => ['void', 'sh'=>'resource'], 'curl_share_errno' => ['int', 'sh'=>'resource'], 'curl_share_init' => ['resource'], 'curl_share_setopt' => ['bool', 'sh'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'curl_unescape' => ['string|false', 'ch'=>'resource', 'string'=>'string'], 'date_add' => ['DateTime|false', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_date_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'month'=>'int', 'day'=>'int'], 'date_diff' => ['DateInterval|false', 'obj1'=>'DateTimeInterface', 'obj2'=>'DateTimeInterface', 'absolute='=>'bool'], 'date_format' => ['string|false', 'object'=>'DateTimeInterface', 'format'=>'string'], 'date_isodate_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'day='=>'int|mixed'], 'date_parse' => ['array|false', 'date'=>'string'], 'date_sub' => ['DateTime|false', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_sun_info' => ['array|false', 'time'=>'int', 'latitude'=>'float', 'longitude'=>'float'], 'date_time_set' => ['DateTime|false', 'object'=>'DateTime', 'hour'=>'int', 'minute'=>'int', 'second='=>'int', 'microseconds='=>'int'], 'date_timestamp_set' => ['DateTime|false', 'object'=>'DateTime', 'unixtimestamp'=>'int'], 'date_timezone_set' => ['DateTime|false', 'object'=>'DateTime', 'timezone'=>'DateTimeZone'], 'each' => ['array{0:int|string,key:int|string,1:mixed,value:mixed}', '&r_arr'=>'array'], 'explode' => ['list', 'separator'=>'string', 'str'=>'string', 'limit='=>'int'], 'gmdate' => ['string|false', 'format'=>'string', 'timestamp='=>'int'], 'gmmktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'gmp_random' => ['GMP', 'limiter='=>'int'], 'gzgetss' => ['string|false', 'zp'=>'resource', 'length'=>'int', 'allowable_tags='=>'string'], 'hash_hkdf' => ['string|false', 'algo'=>'string', 'ikm'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'], 'image2wbmp' => ['bool', 'im'=>'resource', 'filename='=>'?string', 'threshold='=>'int'], 'imageaffine' => ['resource|false', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'], 'imagecreate' => ['resource|false', 'x_size'=>'int', 'y_size'=>'int'], 'imagecreatefrombmp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd2' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd2part' => ['resource|false', 'filename'=>'string', 'srcx'=>'int', 'srcy'=>'int', 'width'=>'int', 'height'=>'int'], 'imagecreatefromgif' => ['resource|false', 'filename'=>'string'], 'imagecreatefromjpeg' => ['resource|false', 'filename'=>'string'], 'imagecreatefrompng' => ['resource|false', 'filename'=>'string'], 'imagecreatefromstring' => ['resource|false', 'image'=>'string'], 'imagecreatefromwbmp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromwebp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxbm' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxpm' => ['resource|false', 'filename'=>'string'], 'imagecreatetruecolor' => ['resource|false', 'x_size'=>'int', 'y_size'=>'int'], 'imagecrop' => ['resource|false', 'im'=>'resource', 'rect'=>'array'], 'imagecropauto' => ['resource|false', 'im'=>'resource', 'mode'=>'int', 'threshold'=>'float', 'color'=>'int'], 'imagegetclip' => ['array|false', 'im'=>'resource'], 'imagegrabscreen' => ['false|resource'], 'imagegrabwindow' => ['false|resource', 'window_handle'=>'int', 'client_area='=>'int'], 'imagerotate' => ['resource|false', 'src_im'=>'resource', 'angle'=>'float', 'bgdcolor'=>'int', 'ignoretransparent='=>'int'], 'imagescale' => ['resource|false', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'], 'jpeg2wbmp' => ['bool', 'jpegname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'], 'ldap_sort' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', 'sortfilter'=>'string'], 'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string', 'is_hex='=>'bool'], 'mktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'parse_str' => ['void', 'encoded_string'=>'string', '&w_result='=>'array'], 'password_hash' => ['string|false|null', 'password'=>'string', 'algo'=>'?string|?int', 'options='=>'array'], 'png2wbmp' => ['bool', 'pngname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'], 'proc_get_status' => ['array|false', 'process'=>'resource'], 'read_exif_data' => ['array', 'filename'=>'string', 'sections_needed='=>'string', 'sub_arrays='=>'bool', 'read_thumbnail='=>'bool'], 'socket_addrinfo_lookup' => ['resource[]', 'node'=>'string', 'service='=>'mixed', 'hints='=>'array'], 'socket_accept' => ['resource|false', 'socket'=>'resource'], 'socket_addrinfo_bind' => ['?resource', 'addrinfo'=>'resource'], 'socket_addrinfo_connect' => ['?resource', 'addrinfo'=>'resource'], 'socket_addrinfo_explain' => ['array', 'addrinfo'=>'resource'], 'socket_addrinfo_lookup' => ['resource[]', 'node'=>'string', 'service='=>'mixed', 'hints='=>'array'], 'socket_bind' => ['bool', 'socket'=>'resource', 'addr'=>'string', 'port='=>'int'], 'socket_clear_error' => ['void', 'socket='=>'resource'], 'socket_close' => ['void', 'socket'=>'resource'], 'socket_connect' => ['bool', 'socket'=>'resource', 'addr'=>'string', 'port='=>'int'], 'socket_create' => ['resource|false', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int'], 'socket_create_listen' => ['resource|false', 'port'=>'int', 'backlog='=>'int'], 'socket_create_pair' => ['bool', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int', '&w_fd'=>'resource[]'], 'socket_export_stream' => ['resource|false', 'socket'=>'resource'], 'socket_get_option' => ['mixed|false', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int'], 'socket_get_status' => ['array', 'stream'=>'resource'], 'socket_getopt' => ['mixed', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int'], 'socket_getpeername' => ['bool', 'socket'=>'resource', '&w_addr'=>'string', '&w_port='=>'int'], 'socket_getsockname' => ['bool', 'socket'=>'resource', '&w_addr'=>'string', '&w_port='=>'int'], 'socket_import_stream' => ['resource|false|null', 'stream'=>'resource'], 'socket_last_error' => ['int', 'socket='=>'resource'], 'socket_listen' => ['bool', 'socket'=>'resource', 'backlog='=>'int'], 'socket_read' => ['string|false', 'socket'=>'resource', 'length'=>'int', 'type='=>'int'], 'socket_recv' => ['int|false', 'socket'=>'resource', '&w_buf'=>'string', 'length'=>'int', 'flags'=>'int'], 'socket_recvfrom' => ['int|false', 'socket'=>'resource', '&w_buf'=>'string', 'length'=>'int', 'flags'=>'int', '&w_name'=>'string', '&w_port='=>'int'], 'socket_recvmsg' => ['int|false', 'socket'=>'resource', '&w_message'=>'string', 'flags='=>'int'], 'socket_select' => ['int|false', '&rw_read_fds'=>'resource[]|null', '&rw_write_fds'=>'resource[]|null', '&rw_except_fds'=>'resource[]|null', 'tv_sec'=>'int', 'tv_usec='=>'int'], 'socket_send' => ['int|false', 'socket'=>'resource', 'buf'=>'string', 'length'=>'int', 'flags'=>'int'], 'socket_sendmsg' => ['int|false', 'socket'=>'resource', 'message'=>'array', 'flags'=>'int'], 'socket_sendto' => ['int|false', 'socket'=>'resource', 'buf'=>'string', 'length'=>'int', 'flags'=>'int', 'addr'=>'string', 'port='=>'int'], 'socket_set_block' => ['bool', 'socket'=>'resource'], 'socket_set_blocking' => ['bool', 'socket'=>'resource', 'mode'=>'int'], 'socket_set_nonblock' => ['bool', 'socket'=>'resource'], 'socket_set_option' => ['bool', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int', 'optval'=>'int|string|array'], 'socket_set_timeout' => ['bool', 'stream'=>'resource', 'seconds'=>'int', 'microseconds='=>'int'], 'socket_setopt' => ['void', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int', 'optval'=>'int|string|array'], 'socket_shutdown' => ['bool', 'socket'=>'resource', 'how='=>'int'], 'socket_strerror' => ['string', 'errno'=>'int'], 'socket_write' => ['int|false', 'socket'=>'resource', 'buf'=>'string', 'length='=>'int'], 'socket_wsaprotocol_info_export' => ['string|false', 'stream'=>'resource', 'target_pid'=>'int'], 'socket_wsaprotocol_info_import' => ['resource|false', 'id'=>'string'], 'socket_wsaprotocol_info_release' => ['bool', 'id'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => ['?string|?false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'SplFileObject::fgetss' => ['string|false', 'allowable_tags='=>'string'], 'strchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string|int', 'before_needle='=>'bool'], 'stripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'string|int', 'before_needle='=>'bool'], 'strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strrchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string|int'], 'strripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'string|int', 'before_needle='=>'bool'], 'xml_parser_create' => ['resource', 'encoding='=>'string'], 'xml_parser_create_ns' => ['resource', 'encoding='=>'string', 'sep='=>'string'], 'xml_parser_free' => ['bool', 'parser'=>'resource'], 'xml_parser_get_option' => ['mixed|false', 'parser'=>'resource', 'option'=>'int'], 'xml_parser_set_option' => ['bool', 'parser'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'xmlwriter_end_attribute' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_cdata' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_comment' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_document' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_attlist' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_entity' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_pi' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_flush' => ['mixed', 'xmlwriter'=>'resource', 'empty='=>'bool'], 'xmlwriter_full_end_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_open_memory' => ['resource'], 'xmlwriter_open_uri' => ['resource', 'source'=>'string'], 'xmlwriter_output_memory' => ['string', 'xmlwriter'=>'resource', 'flush='=>'bool'], 'xmlwriter_set_indent' => ['bool', 'xmlwriter'=>'resource', 'indent'=>'bool'], 'xmlwriter_set_indent_string' => ['bool', 'xmlwriter'=>'resource', 'indentstring'=>'string'], 'xmlwriter_start_attribute' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_attribute_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'xmlwriter_start_cdata' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_start_comment' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_start_document' => ['bool', 'xmlwriter'=>'resource', 'version='=>'string', 'encoding='=>'string', 'standalone='=>'string'], 'xmlwriter_start_dtd' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string'], 'xmlwriter_start_dtd_attlist' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_dtd_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_dtd_entity' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'isparam'=>'bool'], 'xmlwriter_start_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_element_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'xmlwriter_start_pi' => ['bool', 'xmlwriter'=>'resource', 'target'=>'string'], 'xmlwriter_text' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_attribute' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_attribute_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_cdata' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_comment' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_dtd' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string', 'subset='=>'string'], 'xmlwriter_write_dtd_attlist' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_entity' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string', 'pe'=>'bool', 'publicid'=>'string', 'sysid'=>'string', 'ndataid'=>'string'], 'xmlwriter_write_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_element_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_pi' => ['bool', 'xmlwriter'=>'resource', 'target'=>'string', 'content'=>'string'], 'xmlwriter_write_raw' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], ] ]; [ 'Closure::fromCallable' => ['Closure', 'callable'=>'callable'], 'SQLite3::createFunction' => ['bool', 'name'=>'string', 'callback'=>'callable', 'argument_count='=>'int', 'flags='=>'int'], 'curl_multi_errno' => ['int', 'mh'=>'resource'], 'curl_share_errno' => ['int', 'sh'=>'resource'], 'curl_share_strerror' => ['string', 'code'=>'int'], 'get_headers' => ['array|false', 'url'=>'string', 'format='=>'int', 'context='=>'resource'], 'getenv\'1' => ['array'], 'getopt' => ['array|array|array>', 'options'=>'string', 'longopts='=>'array', '&w_optind='=>'int'], 'hash_hkdf' => ['string', 'algo'=>'string', 'ikm'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'], 'is_iterable' => ['bool', 'var'=>'mixed'], 'openssl_get_curve_names' => ['array'], 'pcntl_async_signals' => ['bool', 'on='=>'bool'], 'pcntl_signal_get_handler' => ['int|string', 'signo'=>'int'], 'pg_fetch_all' => ['array', 'result'=>'resource', 'result_type='=>'int'], 'pg_last_error' => ['string', 'connection='=>'resource', 'operation='=>'int'], 'pg_select' => ['mixed', 'db'=>'resource', 'table'=>'string', 'ids'=>'array', 'options='=>'int', 'result_type='=>'int'], 'sapi_windows_cp_conv' => ['string', 'in_codepage'=>'int|string', 'out_codepage'=>'int|string', 'subject'=>'string'], 'sapi_windows_cp_get' => ['int'], 'sapi_windows_cp_is_utf8' => ['bool'], 'sapi_windows_cp_set' => ['bool', 'code_page'=>'int'], 'session_create_id' => ['string', 'prefix='=>'string'], 'session_gc' => ['int'], 'unpack' => ['array', 'format'=>'string', 'data'=>'string', 'offset='=>'int'], ], 'old' => [ 'SQLite3::createFunction' => ['bool', 'name'=>'string', 'callback'=>'callable', 'argument_count='=>'int'], 'get_headers' => ['array|false', 'url'=>'string', 'format='=>'int'], 'getopt' => ['array|array|array>', 'options'=>'string', 'longopts='=>'array'], 'pg_fetch_all' => ['array', 'result'=>'resource'], 'pg_last_error' => ['string', 'connection='=>'resource'], 'pg_select' => ['mixed', 'db'=>'resource', 'table'=>'string', 'ids'=>'array', 'options='=>'int'], 'unpack' => ['array', 'format'=>'string', 'data'=>'string'], ], ]; [['shell']], 'create_function' => [['text'], ['text']], 'file_get_contents' => [['text']], 'file_put_contents' => [['shell']], 'fopen' => [['shell']], 'header' => [['text']], 'igbinary_unserialize' => [['text']], 'ldap_search' => [['text']], 'mysqli_query' => [[], ['sql']], 'mysqli::query' => [['sql']], 'mysqli_real_query' => [[], ['sql']], 'mysqli::real_query' => [['sql']], 'mysqli_multi_query' => [[], ['sql']], 'mysqli::multi_query' => [['sql']], 'mysqli_prepare' => [[], ['sql']], 'mysqli::prepare' => [['sql']], 'mysqli_stmt::__construct' => [[], ['sql']], 'mysqli_stmt_prepare' => [[], ['sql']], 'mysqli_stmt::prepare' => [['sql']], 'passthru' => [['shell']], 'pcntl_exec' => [['shell']], 'PDO::prepare' => [['sql']], 'PDO::query' => [['sql']], 'PDO::exec' => [['sql']], 'pg_exec' => [[], ['sql']], 'pg_prepare' => [[], [], ['sql']], 'pg_put_line' => [[], ['sql']], 'pg_query' => [[], ['sql']], 'pg_query_params' => [[], ['sql']], 'pg_send_prepare' => [[], [], ['sql']], 'pg_send_query' => [[], ['sql']], 'pg_send_query_params' => [[], ['sql'], []], 'setcookie' => [['text'], ['text']], 'shell_exec' => [['shell']], 'system' => [['shell']], 'unserialize' => [['text']], ]; [ 'name' => 'string', ], 'limititerator' => [ 'name' => 'string', ], 'solrdocumentfield' => [ 'name' => 'string', 'boost' => 'float', 'values' => 'array', ], 'domprocessinginstruction' => [ 'target' => 'string', 'data' => 'string', ], 'recursivearrayiterator' => [ 'name' => 'string', ], 'eventbuffer' => [ 'length' => 'int', 'contiguous-space' => 'int', ], 'mongocursor' => [ 'slaveokay' => 'boolean', 'timeout' => 'integer', ], 'domxpath' => [ 'document' => 'DOMDocument', ], 'domentity' => [ 'publicId' => 'string', 'systemId' => 'string', 'notationName' => 'string', 'actualEncoding' => 'string', 'encoding' => 'string', 'version' => 'string', ], 'splminheap' => [ 'name' => 'string', ], 'mongodb-driver-exception-writeexception' => [ 'writeresult' => 'MongoDBDriverWriteResult', ], 'ziparchive' => [ 'status' => 'int', 'statusSys' => 'int', 'numFiles' => 'int', 'filename' => 'string', 'comment' => 'string', ], 'solrexception' => [ 'sourceline' => 'integer', 'sourcefile' => 'string', 'zif-name' => 'string', ], 'arrayiterator' => [ 'name' => 'string', ], 'mongoid' => [ 'id' => 'string', ], 'dateinterval' => [ 'y' => 'integer', 'm' => 'integer', 'd' => 'integer', 'h' => 'integer', 'i' => 'integer', 's' => 'integer', 'f' => 'float', // only present from 7.1 onwards 'invert' => 'integer', 'days' => 'false|int', ], 'tokyotyrantexception' => [ 'code' => 'int', ], 'tidy' => [ 'errorbuffer' => 'string', ], 'filteriterator' => [ 'name' => 'string', ], 'parentiterator' => [ 'name' => 'string', ], 'recursiveregexiterator' => [ 'name' => 'string', ], 'error' => [ 'message' => 'string', 'code' => 'int', 'file' => 'string', 'line' => 'int', ], 'domexception' => [ 'code' => 'int', ], 'domentityreference' => [ 'name' => 'string', ], 'spldoublylinkedlist' => [ 'name' => 'string', ], 'domdocumentfragment' => [ 'name' => 'string', ], 'collator' => [ 'name' => 'string', ], 'streamwrapper' => [ 'context' => 'resource', ], 'pdostatement' => [ 'querystring' => 'string', ], 'domnotation' => [ 'publicId' => 'string', 'systemId' => 'string', ], 'snmpexception' => [ 'code' => 'string', ], 'directoryiterator' => [ 'name' => 'string', ], 'splqueue' => [ 'name' => 'string', ], 'locale' => [ 'name' => 'string', ], 'directory' => [ 'path' => 'string', 'handle' => 'resource', ], 'splheap' => [ 'name' => 'string', ], 'domnodelist' => [ 'length' => 'int', ], 'mongodb' => [ 'w' => 'integer', 'wtimeout' => 'integer', ], 'splpriorityqueue' => [ 'name' => 'string', ], 'mongoclient' => [ 'connected' => 'boolean', 'status' => 'string', ], 'domdocument' => [ 'actualEncoding' => 'string', 'config' => 'null', 'doctype' => 'DOMDocumentType', 'documentElement' => 'DOMElement', 'documentURI' => 'string', 'encoding' => 'string', 'formatOutput' => 'bool', 'implementation' => 'DOMImplementation', 'preserveWhiteSpace' => 'bool', 'recover' => 'bool', 'resolveExternals' => 'bool', 'standalone' => 'bool', 'strictErrorChecking' => 'bool', 'substituteEntities' => 'bool', 'validateOnParse' => 'bool', 'version' => 'string', 'xmlEncoding' => 'string', 'xmlStandalone' => 'bool', 'xmlVersion' => 'string', 'ownerDocument' => 'null', 'parentNode' => 'null', ], 'libxmlerror' => [ 'level' => 'int', 'code' => 'int', 'column' => 'int', 'message' => 'string', 'file' => 'string', 'line' => 'int', ], 'domimplementation' => [ 'name' => 'string', ], 'normalizer' => [ 'name' => 'string', ], 'norewinditerator' => [ 'name' => 'string', ], 'event' => [ 'pending' => 'bool', ], 'domdocumenttype' => [ 'publicId' => 'string', 'systemId' => 'string', 'name' => 'string', 'entities' => 'DOMNamedNodeMap', 'notations' => 'DOMNamedNodeMap', 'internalSubset' => 'string', ], 'errorexception' => [ 'severity' => 'int', ], 'recursivedirectoryiterator' => [ 'name' => 'string', ], 'domcharacterdata' => [ 'data' => 'string', 'length' => 'int', ], 'mongocollection' => [ 'db' => 'MongoDB', 'w' => 'integer', 'wtimeout' => 'integer', ], 'mongoint64' => [ 'value' => 'string', ], 'mysqli' => [ 'affected_rows' => 'int', 'client_info' => 'string', 'client_version' => 'int', 'connect_errno' => 'int', 'connect_error' => 'string', 'errno' => 'int', 'error' => 'string', 'error_list' => 'array', 'field_count' => 'int', 'host_info' => 'string', 'info' => 'string', 'insert_id' => 'int', 'protocol_version' => 'string', 'server_info' => 'string', 'server_version' => 'int', 'sqlstate' => 'string', 'thread_id' => 'int', 'warning_count' => 'int', ], 'mysqli_driver' => [ 'client_info' => 'string', 'client_version' => 'string', 'driver_version' => 'string', 'embedded' => 'string', 'reconnect' => 'bool', 'report_mode' => 'int' ], 'mysqli_result' => [ 'current_field' => 'int', 'field_count' => 'int', 'lengths' => 'array', 'num_rows' => 'int', 'type' => 'mixed', ], 'mysqli_sql_exception' => [ 'sqlstate' => 'string' ], 'mysqli_stmt' => [ 'affected_rows' => 'int', 'errno' => 'int', 'error' => 'string', 'error_list' => 'array', 'field_count' => 'int', 'id' => 'mixed', 'insert_id' => 'int', 'num_rows' => 'int', 'param_count' => 'int', 'sqlstate' => 'string', ], 'mysqli_warning' => [ 'errno' => 'int', 'message' => 'string', 'sqlstate' => 'string', ], 'eventlistener' => [ 'fd' => 'int', ], 'splmaxheap' => [ 'name' => 'string', ], 'regexiterator' => [ 'name' => 'string', ], 'domelement' => [ 'schemaTypeInfo' => 'bool', 'tagName' => 'string', 'attributes' => 'DOMNamedNodeMap', ], 'tidynode' => [ 'value' => 'string', 'name' => 'string', 'type' => 'int', 'line' => 'int', 'column' => 'int', 'proprietary' => 'bool', 'id' => 'int', 'attribute' => 'array', 'child' => '?array', ], 'recursivecachingiterator' => [ 'name' => 'string', ], 'solrresponse' => [ 'http-status' => 'integer', 'parser-mode' => 'integer', 'success' => 'bool', 'http-status-message' => 'string', 'http-request-url' => 'string', 'http-raw-request-headers' => 'string', 'http-raw-request' => 'string', 'http-raw-response-headers' => 'string', 'http-raw-response' => 'string', 'http-digested-response' => 'string', ], 'domnamednodemap' => [ 'length' => 'int', ], 'splstack' => [ 'name' => 'string', ], 'numberformatter' => [ 'name' => 'string', ], 'eventsslcontext' => [ 'local-cert' => 'string', 'local-pk' => 'string', ], 'pdoexception' => [ 'errorinfo' => 'array', 'code' => 'string', ], 'domnode' => [ 'nodeName' => 'string', 'nodeValue' => 'string', 'nodeType' => 'int', 'parentNode' => 'DOMNode|null', 'childNodes' => 'DOMNodeList', 'firstChild' => 'DOMNode|null', 'lastChild' => 'DOMNode|null', 'previousSibling' => 'DOMNode|null', 'nextSibling' => 'DOMNode|null', 'attributes' => 'null', 'ownerDocument' => 'DOMDocument|null', 'namespaceURI' => 'string|null', 'prefix' => 'string', 'localName' => 'string', 'baseURI' => 'string|null', 'textContent' => 'string', ], 'domattr' => [ 'name' => 'string', 'ownerElement' => 'DOMElement', 'schemaTypeInfo' => 'bool', 'specified' => 'bool', 'value' => 'string', ], 'simplexmliterator' => [ 'name' => 'string', ], 'snmp' => [ 'max-oids' => 'int', 'valueretrieval' => 'int', 'quick-print' => 'bool', 'enum-print' => 'bool', 'oid-output-format' => 'int', 'oid-increasing-check' => 'bool', 'exceptions-enabled' => 'int', 'info' => 'array', ], 'mongoint32' => [ 'value' => 'string', ], 'xmlreader' => [ 'attributeCount' => 'int', 'baseURI' => 'string', 'depth' => 'int', 'hasAttributes' => 'bool', 'hasValue' => 'bool', 'isDefault' => 'bool', 'isEmptyElement' => 'bool', 'localName' => 'string', 'name' => 'string', 'namespaceURI' => 'string', 'nodeType' => 'int', 'prefix' => 'string', 'value' => 'string', 'xmlLang' => 'string', ], 'eventbufferevent' => [ 'fd' => 'integer', 'priority' => 'integer', 'input' => 'EventBuffer', 'output' => 'EventBuffer', ], 'domtext' => [ 'wholeText' => 'string', ], 'exception' => [ 'message' => 'string', 'code' => 'int', 'file' => 'string', 'line' => 'int', ], 'reflectionclass' => [ 'name' => 'string', ], 'reflectionmethod' => [ 'class' => 'string', 'name' => 'string', ], 'reflectionparameter' => [ 'name' => 'string', ], 'phpparser\\node\\expr\\funccall' => [ 'args' => 'array', ], 'phpparser\\node\\expr\\new_' => [ 'args' => 'array', ], 'phpparser\\node\\expr\\array_' => [ 'items' => 'array', ], 'phpparser\\node\\expr\\list_' => [ 'items' => 'array', ], 'phpparser\\node\\expr\\methodcall' => [ 'args' => 'array', ], 'phpparser\\node\\expr\\staticcall' => [ 'args' => 'array', ], 'phpparser\\node\\name' => [ 'parts' => 'non-empty-array', ], 'phpparser\\node\\stmt\\namespace_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\if_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\elseif_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\else_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\for_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\foreach_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\trycatch' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\catch_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\finally_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\case_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\while_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\do_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\class_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\trait_' => [ 'stmts' => 'array', ], 'phpparser\\node\\stmt\\interface_' => [ 'stmts' => 'array', ], 'phpparser\\node\\matcharm' => [ 'conds' => 'null|non-empty-list', ], 'rdkafka\\message' => [ 'err' => 'int', 'topic_name' => 'string', 'partition' => 'int', 'payload' => 'string', 'key' => 'string|null', 'offset' => 'int', 'timestamp' => 'int', 'headers' => 'array|null', ], ]; $vendorDir . '/composer/semver/src/Comparator.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\AbstractConstraint' => $vendorDir . '/composer/semver/src/Constraint/AbstractConstraint.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\Constraint' => $vendorDir . '/composer/semver/src/Constraint/Constraint.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\ConstraintInterface' => $vendorDir . '/composer/semver/src/Constraint/ConstraintInterface.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\EmptyConstraint' => $vendorDir . '/composer/semver/src/Constraint/EmptyConstraint.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\MultiConstraint' => $vendorDir . '/composer/semver/src/Constraint/MultiConstraint.php', 'HumbugBox383\\Composer\\Semver\\Semver' => $vendorDir . '/composer/semver/src/Semver.php', 'HumbugBox383\\Composer\\Semver\\VersionParser' => $vendorDir . '/composer/semver/src/VersionParser.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\Checker' => $baseDir . '/src/Checker.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\IO' => $baseDir . '/src/IO.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\IsExtensionFulfilled' => $baseDir . '/src/IsExtensionFulfilled.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\IsFulfilled' => $baseDir . '/src/IsFulfilled.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\IsPhpVersionFulfilled' => $baseDir . '/src/IsPhpVersionFulfilled.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\Printer' => $baseDir . '/src/Printer.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\Requirement' => $baseDir . '/src/Requirement.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\RequirementCollection' => $baseDir . '/src/RequirementCollection.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\Terminal' => $baseDir . '/src/Terminal.php', ); array ( 'HumbugBox383\\KevinGH\\RequirementChecker\\' => 40, 'HumbugBox383\\Composer\\Semver\\' => 29, ), ); public static $prefixDirsPsr4 = array ( 'HumbugBox383\\KevinGH\\RequirementChecker\\' => array ( 0 => __DIR__ . '/../..' . '/src', ), 'HumbugBox383\\Composer\\Semver\\' => array ( 0 => __DIR__ . '/..' . '/composer/semver/src', ), ); public static $classMap = array ( 'HumbugBox383\\Composer\\Semver\\Comparator' => __DIR__ . '/..' . '/composer/semver/src/Comparator.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\AbstractConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/AbstractConstraint.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\Constraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/Constraint.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\ConstraintInterface' => __DIR__ . '/..' . '/composer/semver/src/Constraint/ConstraintInterface.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\EmptyConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/EmptyConstraint.php', 'HumbugBox383\\Composer\\Semver\\Constraint\\MultiConstraint' => __DIR__ . '/..' . '/composer/semver/src/Constraint/MultiConstraint.php', 'HumbugBox383\\Composer\\Semver\\Semver' => __DIR__ . '/..' . '/composer/semver/src/Semver.php', 'HumbugBox383\\Composer\\Semver\\VersionParser' => __DIR__ . '/..' . '/composer/semver/src/VersionParser.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\Checker' => __DIR__ . '/../..' . '/src/Checker.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\IO' => __DIR__ . '/../..' . '/src/IO.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\IsExtensionFulfilled' => __DIR__ . '/../..' . '/src/IsExtensionFulfilled.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\IsFulfilled' => __DIR__ . '/../..' . '/src/IsFulfilled.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\IsPhpVersionFulfilled' => __DIR__ . '/../..' . '/src/IsPhpVersionFulfilled.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\Printer' => __DIR__ . '/../..' . '/src/Printer.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\Requirement' => __DIR__ . '/../..' . '/src/Requirement.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\RequirementCollection' => __DIR__ . '/../..' . '/src/RequirementCollection.php', 'HumbugBox383\\KevinGH\\RequirementChecker\\Terminal' => __DIR__ . '/../..' . '/src/Terminal.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInit4dcc0e1d4584ae7b8040cfa1b3dfe9e3::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit4dcc0e1d4584ae7b8040cfa1b3dfe9e3::$prefixDirsPsr4; $loader->classMap = ComposerStaticInit4dcc0e1d4584ae7b8040cfa1b3dfe9e3::$classMap; }, null, ClassLoader::class); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Autoload; /** * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. * * $loader = new \Composer\Autoload\ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * // activate the autoloader * $loader->register(); * * // to enable searching the include path (eg. for PEAR packages) * $loader->setUseIncludePath(true); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * This class is loosely based on the Symfony UniversalClassLoader. * * @author Fabien Potencier * @author Jordi Boggiano * @see http://www.php-fig.org/psr/psr-0/ * @see http://www.php-fig.org/psr/psr-4/ */ class ClassLoader { // PSR-4 private $prefixLengthsPsr4 = array(); private $prefixDirsPsr4 = array(); private $fallbackDirsPsr4 = array(); // PSR-0 private $prefixesPsr0 = array(); private $fallbackDirsPsr0 = array(); private $useIncludePath = false; private $classMap = array(); private $classMapAuthoritative = false; private $missingClasses = array(); private $apcuPrefix; public function getPrefixes() { if (!empty($this->prefixesPsr0)) { return call_user_func_array('array_merge', $this->prefixesPsr0); } return array(); } public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } public function getFallbackDirs() { return $this->fallbackDirsPsr0; } public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } public function getClassMap() { return $this->classMap; } /** * @param array $classMap Class to filename map */ public function addClassMap(array $classMap) { if ($this->classMap) { $this->classMap = array_merge($this->classMap, $classMap); } else { $this->classMap = $classMap; } } /** * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * * @param string $prefix The prefix * @param array|string $paths The PSR-0 root directories * @param bool $prepend Whether to prepend the directories */ public function add($prefix, $paths, $prepend = false) { if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( (array) $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, (array) $paths ); } return; } $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { $this->prefixesPsr0[$first][$prefix] = (array) $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( (array) $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], (array) $paths ); } } /** * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException */ public function addPsr4($prefix, $paths, $prepend = false) { if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( (array) $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, (array) $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { // Register directories for a new namespace. $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixDirsPsr4[$prefix] = (array) $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( (array) $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], (array) $paths ); } } /** * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * * @param string $prefix The prefix * @param array|string $paths The PSR-0 base directories */ public function set($prefix, $paths) { if (!$prefix) { $this->fallbackDirsPsr0 = (array) $paths; } else { $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; } } /** * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException */ public function setPsr4($prefix, $paths) { if (!$prefix) { $this->fallbackDirsPsr4 = (array) $paths; } else { $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixDirsPsr4[$prefix] = (array) $paths; } } /** * Turns on searching the include path for class files. * * @param bool $useIncludePath */ public function setUseIncludePath($useIncludePath) { $this->useIncludePath = $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return bool */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Turns off searching the prefix and fallback directories for classes * that have not been registered with the class map. * * @param bool $classMapAuthoritative */ public function setClassMapAuthoritative($classMapAuthoritative) { $this->classMapAuthoritative = $classMapAuthoritative; } /** * Should class lookup fail if not found in the current class map? * * @return bool */ public function isClassMapAuthoritative() { return $this->classMapAuthoritative; } /** * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix */ public function setApcuPrefix($apcuPrefix) { $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** * The APCu prefix in use, or null if APCu caching is not enabled. * * @return string|null */ public function getApcuPrefix() { return $this->apcuPrefix; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * @return bool|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { includeFile($file); return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|false The path if found, false otherwise */ public function findFile($class) { // class map lookup if (isset($this->classMap[$class])) { return $this->classMap[$class]; } if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { return false; } if (null !== $this->apcuPrefix) { $file = apcu_fetch($this->apcuPrefix.$class, $hit); if ($hit) { return $file; } } $file = $this->findFileWithExtension($class, '.php'); // Search for Hack files if we are running on HHVM if (false === $file && defined('HHVM_VERSION')) { $file = $this->findFileWithExtension($class, '.hh'); } if (null !== $this->apcuPrefix) { apcu_add($this->apcuPrefix.$class, $file); } if (false === $file) { // Remember that this class does not exist. $this->missingClasses[$class] = true; } return $file; } private function findFileWithExtension($class, $ext) { // PSR-4 lookup $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; $first = $class[0]; if (isset($this->prefixLengthsPsr4[$first])) { $subPath = $class; while (false !== $lastPos = strrpos($subPath, '\\')) { $subPath = substr($subPath, 0, $lastPos); $search = $subPath . '\\'; if (isset($this->prefixDirsPsr4[$search])) { $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { if (file_exists($file = $dir . $pathEnd)) { return $file; } } } } } // PSR-4 fallback dirs foreach ($this->fallbackDirsPsr4 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { return $file; } } // PSR-0 lookup if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); } else { // PEAR-like class name $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; } if (isset($this->prefixesPsr0[$first])) { foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos($class, $prefix)) { foreach ($dirs as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } } } } // PSR-0 fallback dirs foreach ($this->fallbackDirsPsr0 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } // PSR-0 include paths. if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { return $file; } return false; } } /** * Scope isolated include. * * Prevents access to $this/self from included files. */ function includeFile($file) { include $file; } array($baseDir . '/src'), 'HumbugBox383\\Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'), ); Copyright (c) Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { require_once __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInit4dcc0e1d4584ae7b8040cfa1b3dfe9e3::getInitializer($loader)); } else { $classMap = require __DIR__ . '/autoload_classmap.php'; if ($classMap) { $loader->addClassMap($classMap); } } $loader->setClassMapAuthoritative(true); $loader->register(true); return $loader; } } expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? \ltrim($matches[$index + 1], '.-') : ''); } if (!empty($matches[$index + 2])) { $version .= '-dev'; } return $version; } if (\preg_match('{(.*?)[.-]?dev$}i', $version, $match)) { try { return $this->normalizeBranch($match[1]); } catch (\Exception $e) { } } $extraMessage = ''; if (\preg_match('{ +as +' . \preg_quote($version) . '$}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version'; } elseif (\preg_match('{^' . \preg_quote($version) . ' +as +}', $fullVersion)) { $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-'; } throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage); } public function parseNumericAliasPrefix($branch) { if (\preg_match('{^(?P(\\d++\\.)*\\d++)(?:\\.x)?-dev$}i', $branch, $matches)) { return $matches['version'] . '.'; } return \false; } public function normalizeBranch($name) { $name = \trim($name); if (\in_array($name, array('master', 'trunk', 'default'))) { return $this->normalize($name); } if (\preg_match('{^v?(\\d++)(\\.(?:\\d++|[xX*]))?(\\.(?:\\d++|[xX*]))?(\\.(?:\\d++|[xX*]))?$}i', $name, $matches)) { $version = ''; for ($i = 1; $i < 5; ++$i) { $version .= isset($matches[$i]) ? \str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x'; } return \str_replace('x', '9999999', $version) . '-dev'; } return 'dev-' . $name; } public function parseConstraints($constraints) { $prettyConstraint = $constraints; if (\preg_match('{^([^,\\s]*?)@(' . \implode('|', self::$stabilities) . ')$}i', $constraints, $match)) { $constraints = empty($match[1]) ? '*' : $match[1]; } if (\preg_match('{^(dev-[^,\\s@]+?|[^,\\s@]+?\\.x-dev)#.+$}i', $constraints, $match)) { $constraints = $match[1]; } $orConstraints = \preg_split('{\\s*\\|\\|?\\s*}', \trim($constraints)); $orGroups = array(); foreach ($orConstraints as $constraints) { $andConstraints = \preg_split('{(?< ,]) *(? 1) { $constraintObjects = array(); foreach ($andConstraints as $constraint) { foreach ($this->parseConstraint($constraint) as $parsedConstraint) { $constraintObjects[] = $parsedConstraint; } } } else { $constraintObjects = $this->parseConstraint($andConstraints[0]); } if (1 === \count($constraintObjects)) { $constraint = $constraintObjects[0]; } else { $constraint = new \HumbugBox383\Composer\Semver\Constraint\MultiConstraint($constraintObjects); } $orGroups[] = $constraint; } if (1 === \count($orGroups)) { $constraint = $orGroups[0]; } elseif (2 === \count($orGroups) && $orGroups[0] instanceof \HumbugBox383\Composer\Semver\Constraint\MultiConstraint && $orGroups[1] instanceof \HumbugBox383\Composer\Semver\Constraint\MultiConstraint && 2 === \count($orGroups[0]->getConstraints()) && 2 === \count($orGroups[1]->getConstraints()) && ($a = (string) $orGroups[0]) && \substr($a, 0, 3) === '[>=' && \false !== ($posA = \strpos($a, '<', 4)) && ($b = (string) $orGroups[1]) && \substr($b, 0, 3) === '[>=' && \false !== ($posB = \strpos($b, '<', 4)) && \substr($a, $posA + 2, -1) === \substr($b, 4, $posB - 5)) { $constraint = new \HumbugBox383\Composer\Semver\Constraint\MultiConstraint(array(new \HumbugBox383\Composer\Semver\Constraint\Constraint('>=', \substr($a, 4, $posA - 5)), new \HumbugBox383\Composer\Semver\Constraint\Constraint('<', \substr($b, $posB + 2, -1)))); } else { $constraint = new \HumbugBox383\Composer\Semver\Constraint\MultiConstraint($orGroups, \false); } $constraint->setPrettyString($prettyConstraint); return $constraint; } private function parseConstraint($constraint) { if (\preg_match('{^([^,\\s]+?)@(' . \implode('|', self::$stabilities) . ')$}i', $constraint, $match)) { $constraint = $match[1]; if ($match[2] !== 'stable') { $stabilityModifier = $match[2]; } } if (\preg_match('{^v?[xX*](\\.[xX*])*$}i', $constraint)) { return array(new \HumbugBox383\Composer\Semver\Constraint\EmptyConstraint()); } $versionRegex = 'v?(\\d++)(?:\\.(\\d++))?(?:\\.(\\d++))?(?:\\.(\\d++))?' . self::$modifierRegex . '(?:\\+[^\\s]+)?'; if (\preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) { if (\substr($constraint, 0, 2) === '~>') { throw new \UnexpectedValueException('Could not parse version constraint ' . $constraint . ': ' . 'Invalid operator "~>", you probably meant to use the "~" operator'); } if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) { $position = 4; } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(\substr($constraint . $stabilitySuffix, 1)); $lowerBound = new \HumbugBox383\Composer\Semver\Constraint\Constraint('>=', $lowVersion); $highPosition = \max(1, $position - 1); $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev'; $upperBound = new \HumbugBox383\Composer\Semver\Constraint\Constraint('<', $highVersion); return array($lowerBound, $upperBound); } if (\preg_match('{^\\^' . $versionRegex . '($)}i', $constraint, $matches)) { if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) { $position = 1; } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) { $position = 2; } else { $position = 3; } $stabilitySuffix = ''; if (empty($matches[5]) && empty($matches[7])) { $stabilitySuffix .= '-dev'; } $lowVersion = $this->normalize(\substr($constraint . $stabilitySuffix, 1)); $lowerBound = new \HumbugBox383\Composer\Semver\Constraint\Constraint('>=', $lowVersion); $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; $upperBound = new \HumbugBox383\Composer\Semver\Constraint\Constraint('<', $highVersion); return array($lowerBound, $upperBound); } if (\preg_match('{^v?(\\d++)(?:\\.(\\d++))?(?:\\.(\\d++))?(?:\\.[xX*])++$}', $constraint, $matches)) { if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { $position = 3; } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { $position = 2; } else { $position = 1; } $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev'; $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; if ($lowVersion === '0.0.0.0-dev') { return array(new \HumbugBox383\Composer\Semver\Constraint\Constraint('<', $highVersion)); } return array(new \HumbugBox383\Composer\Semver\Constraint\Constraint('>=', $lowVersion), new \HumbugBox383\Composer\Semver\Constraint\Constraint('<', $highVersion)); } if (\preg_match('{^(?P' . $versionRegex . ') +- +(?P' . $versionRegex . ')($)}i', $constraint, $matches)) { $lowStabilitySuffix = ''; if (empty($matches[6]) && empty($matches[8])) { $lowStabilitySuffix = '-dev'; } $lowVersion = $this->normalize($matches['from']); $lowerBound = new \HumbugBox383\Composer\Semver\Constraint\Constraint('>=', $lowVersion . $lowStabilitySuffix); $empty = function ($x) { return $x === 0 || $x === '0' ? \false : empty($x); }; if (!$empty($matches[11]) && !$empty($matches[12]) || !empty($matches[14]) || !empty($matches[16])) { $highVersion = $this->normalize($matches['to']); $upperBound = new \HumbugBox383\Composer\Semver\Constraint\Constraint('<=', $highVersion); } else { $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]); $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev'; $upperBound = new \HumbugBox383\Composer\Semver\Constraint\Constraint('<', $highVersion); } return array($lowerBound, $upperBound); } if (\preg_match('{^(<>|!=|>=?|<=?|==?)?\\s*(.*)}', $constraint, $matches)) { try { $version = $this->normalize($matches[2]); if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') { $version .= '-' . $stabilityModifier; } elseif ('<' === $matches[1] || '>=' === $matches[1]) { if (!\preg_match('/-' . self::$modifierRegex . '$/', \strtolower($matches[2]))) { if (\substr($matches[2], 0, 4) !== 'dev-') { $version .= '-dev'; } } } return array(new \HumbugBox383\Composer\Semver\Constraint\Constraint($matches[1] ?: '=', $version)); } catch (\Exception $e) { } } $message = 'Could not parse version constraint ' . $constraint; if (isset($e)) { $message .= ': ' . $e->getMessage(); } throw new \UnexpectedValueException($message); } private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0') { for ($i = 4; $i > 0; --$i) { if ($i > $position) { $matches[$i] = $pad; } elseif ($i === $position && $increment) { $matches[$i] += $increment; if ($matches[$i] < 0) { $matches[$i] = $pad; --$position; if ($i === 1) { return; } } } } return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4]; } private function expandStability($stability) { $stability = \strtolower($stability); switch ($stability) { case 'a': return 'alpha'; case 'b': return 'beta'; case 'p': case 'pl': return 'patch'; case 'rc': return 'RC'; default: return $stability; } } } normalize($version)); $constraints = $versionParser->parseConstraints($constraints); return $constraints->matches($provider); } public static function satisfiedBy(array $versions, $constraints) { $versions = \array_filter($versions, function ($version) use($constraints) { return \HumbugBox383\Composer\Semver\Semver::satisfies($version, $constraints); }); return \array_values($versions); } public static function sort(array $versions) { return self::usort($versions, self::SORT_ASC); } public static function rsort(array $versions) { return self::usort($versions, self::SORT_DESC); } private static function usort(array $versions, $direction) { if (null === self::$versionParser) { self::$versionParser = new \HumbugBox383\Composer\Semver\VersionParser(); } $versionParser = self::$versionParser; $normalized = array(); foreach ($versions as $key => $version) { $normalized[] = array($versionParser->normalize($version), $key); } \usort($normalized, function (array $left, array $right) use($direction) { if ($left[0] === $right[0]) { return 0; } if (\HumbugBox383\Composer\Semver\Comparator::lessThan($left[0], $right[0])) { return -$direction; } return $direction; }); $sorted = array(); foreach ($normalized as $item) { $sorted[] = $versions[$item[1]]; } return $sorted; } } self::OP_EQ, '==' => self::OP_EQ, '<' => self::OP_LT, '<=' => self::OP_LE, '>' => self::OP_GT, '>=' => self::OP_GE, '<>' => self::OP_NE, '!=' => self::OP_NE); private static $transOpInt = array(self::OP_EQ => '==', self::OP_LT => '<', self::OP_LE => '<=', self::OP_GT => '>', self::OP_GE => '>=', self::OP_NE => '!='); protected $operator; protected $version; protected $prettyString; public function matches(\HumbugBox383\Composer\Semver\Constraint\ConstraintInterface $provider) { if ($provider instanceof $this) { return $this->matchSpecific($provider); } return $provider->matches($this); } public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return $this->__toString(); } public static function getSupportedOperators() { return \array_keys(self::$transOpStr); } public function __construct($operator, $version) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(\sprintf('Invalid operator "%s" given, expected one of: %s', $operator, \implode(', ', self::getSupportedOperators()))); } $this->operator = self::$transOpStr[$operator]; $this->version = $version; } public function versionCompare($a, $b, $operator, $compareBranches = \false) { if (!isset(self::$transOpStr[$operator])) { throw new \InvalidArgumentException(\sprintf('Invalid operator "%s" given, expected one of: %s', $operator, \implode(', ', self::getSupportedOperators()))); } $aIsBranch = 'dev-' === \substr($a, 0, 4); $bIsBranch = 'dev-' === \substr($b, 0, 4); if ($aIsBranch && $bIsBranch) { return $operator === '==' && $a === $b; } if (!$compareBranches && ($aIsBranch || $bIsBranch)) { return \false; } return \version_compare($a, $b, $operator); } public function matchSpecific(\HumbugBox383\Composer\Semver\Constraint\Constraint $provider, $compareBranches = \false) { $noEqualOp = \str_replace('=', '', self::$transOpInt[$this->operator]); $providerNoEqualOp = \str_replace('=', '', self::$transOpInt[$provider->operator]); $isEqualOp = self::OP_EQ === $this->operator; $isNonEqualOp = self::OP_NE === $this->operator; $isProviderEqualOp = self::OP_EQ === $provider->operator; $isProviderNonEqualOp = self::OP_NE === $provider->operator; if ($isNonEqualOp || $isProviderNonEqualOp) { return !$isEqualOp && !$isProviderEqualOp || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches); } if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) { return \true; } if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) { if ($provider->version === $this->version && self::$transOpInt[$provider->operator] === $providerNoEqualOp && self::$transOpInt[$this->operator] !== $noEqualOp) { return \false; } return \true; } return \false; } public function __toString() { return self::$transOpInt[$this->operator] . ' ' . $this->version; } } constraints = $constraints; $this->conjunctive = $conjunctive; } public function getConstraints() { return $this->constraints; } public function isConjunctive() { return $this->conjunctive; } public function isDisjunctive() { return !$this->conjunctive; } public function matches(\HumbugBox383\Composer\Semver\Constraint\ConstraintInterface $provider) { if (\false === $this->conjunctive) { foreach ($this->constraints as $constraint) { if ($constraint->matches($provider)) { return \true; } } return \false; } foreach ($this->constraints as $constraint) { if (!$constraint->matches($provider)) { return \false; } } return \true; } public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return $this->__toString(); } public function __toString() { $constraints = array(); foreach ($this->constraints as $constraint) { $constraints[] = (string) $constraint; } return '[' . \implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']'; } } prettyString = $prettyString; } public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return $this->__toString(); } public function __toString() { return '[]'; } } matchSpecific($provider); } return $provider->matches($this); } public function setPrettyString($prettyString) { $this->prettyString = $prettyString; } public function getPrettyString() { if ($this->prettyString) { return $this->prettyString; } return $this->__toString(); } } ', $version2); } public static function greaterThanOrEqualTo($version1, $version2) { return self::compare($version1, '>=', $version2); } public static function lessThan($version1, $version2) { return self::compare($version1, '<', $version2); } public static function lessThanOrEqualTo($version1, $version2) { return self::compare($version1, '<=', $version2); } public static function equalTo($version1, $version2) { return self::compare($version1, '==', $version2); } public static function notEqualTo($version1, $version2) { return self::compare($version1, '!=', $version2); } public static function compare($version1, $operator, $version2) { $constraint = new \HumbugBox383\Composer\Semver\Constraint\Constraint($operator, $version2); return $constraint->matches(new \HumbugBox383\Composer\Semver\Constraint\Constraint('==', $version1)); } } evaluateRequirements(); $io = new \HumbugBox383\KevinGH\RequirementChecker\IO(); self::printCheck($checkPassed, new \HumbugBox383\KevinGH\RequirementChecker\Printer($io->getVerbosity(), $io->hasColorSupport()), $requirements); return $checkPassed; } public static function printCheck($checkPassed, \HumbugBox383\KevinGH\RequirementChecker\Printer $printer, \HumbugBox383\KevinGH\RequirementChecker\RequirementCollection $requirements) { if (\false === $checkPassed && \HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_VERY_VERBOSE > $printer->getVerbosity()) { $printer->setVerbosity(\HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_VERY_VERBOSE); } $verbosity = \HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_VERY_VERBOSE; $iniPath = $requirements->getPhpIniPath(); $printer->title('Box Requirements Checker', $verbosity); $printer->printv('> Using PHP ', $verbosity); $printer->printvln(\PHP_VERSION, $verbosity, 'green'); $printer->printvln('> PHP is using the following php.ini file:', $verbosity); if ($iniPath) { $printer->printvln(' ' . $iniPath, $verbosity, 'green'); } else { $printer->printvln(' WARNING: No configuration file (php.ini) used by PHP!', $verbosity, 'yellow'); } $printer->printvln('', $verbosity); if (\count($requirements) > 0) { $printer->printvln('> Checking Box requirements:', $verbosity); $printer->printv(' ', $verbosity); } else { $printer->printvln('> No requirements found.', $verbosity); } $errorMessages = array(); foreach ($requirements->getRequirements() as $requirement) { if ($errorMessage = $printer->getRequirementErrorMessage($requirement)) { if (\HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_DEBUG === $printer->getVerbosity()) { $printer->printvln('✘ ' . $requirement->getTestMessage(), \HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_DEBUG, 'red'); $printer->printv(' ', \HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_DEBUG); $errorMessages[] = $errorMessage; } else { $printer->printv('E', $verbosity, 'red'); $errorMessages[] = $errorMessage; } continue; } if (\HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_DEBUG === $printer->getVerbosity()) { $printer->printvln('✔ ' . $requirement->getHelpText(), \HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_DEBUG, 'green'); $printer->printv(' ', \HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_DEBUG); } else { $printer->printv('.', $verbosity, 'green'); } } if (\HumbugBox383\KevinGH\RequirementChecker\IO::VERBOSITY_DEBUG !== $printer->getVerbosity() && \count($requirements) > 0) { $printer->printvln('', $verbosity); } if ($requirements->evaluateRequirements()) { $printer->block('OK', 'Your system is ready to run the application.', $verbosity, 'success'); } else { $printer->block('ERROR', 'Your system is not ready to run the application.', $verbosity, 'error'); $printer->title('Fix the following mandatory requirements:', $verbosity, 'red'); foreach ($errorMessages as $errorMessage) { $printer->printv(' * ' . $errorMessage, $verbosity); } } $printer->printvln('', $verbosity); } private static function retrieveRequirements() { if (null === self::$requirementsConfig) { self::$requirementsConfig = __DIR__ . '/../.requirements.php'; } $config = (require self::$requirementsConfig); $requirements = new \HumbugBox383\KevinGH\RequirementChecker\RequirementCollection(); foreach ($config as $constraint) { $requirements->addRequirement('php' === $constraint['type'] ? new \HumbugBox383\KevinGH\RequirementChecker\IsPhpVersionFulfilled($constraint['condition']) : new \HumbugBox383\KevinGH\RequirementChecker\IsExtensionFulfilled($constraint['condition']), $constraint['message'], $constraint['helpMessage']); } return $requirements; } } requirements); } public function count() { return \count($this->requirements); } public function add(\HumbugBox383\KevinGH\RequirementChecker\Requirement $requirement) { $this->requirements[] = $requirement; } public function addRequirement($checkIsFulfilled, $testMessage, $helpText) { $this->add(new \HumbugBox383\KevinGH\RequirementChecker\Requirement($checkIsFulfilled, $testMessage, $helpText)); } public function getRequirements() { return $this->requirements; } public function getPhpIniPath() { return \get_cfg_var('cfg_file_path'); } public function evaluateRequirements() { return \array_reduce($this->requirements, function ($checkPassed, \HumbugBox383\KevinGH\RequirementChecker\Requirement $requirement) { return $checkPassed && $requirement->isFulfilled(); }, \true); } } options = \implode(' ', $_SERVER['argv']); $shellVerbosity = $this->configureVerbosity(); $this->interactive = $this->checkInteractivity($shellVerbosity); $this->colorSupport = $this->checkColorSupport(); } public function isInteractive() { return $this->interactive; } public function getVerbosity() { return $this->verbosity; } public function hasColorSupport() { return $this->colorSupport; } public function hasParameter($values) { $values = (array) $values; foreach ($values as $value) { $regexp = \sprintf('/\\s%s\\b/', \str_replace(' ', '\\s+', \preg_quote($value, '/'))); if (1 === \preg_match($regexp, $this->options)) { return \true; } } return \false; } private function checkInteractivity($shellVerbosity) { if (-1 === $shellVerbosity) { return \false; } if (\true === $this->hasParameter(array('--no-interaction', '-n'))) { return \false; } if (\function_exists('posix_isatty') && !@\posix_isatty(\STDOUT) && \false === \getenv('SHELL_INTERACTIVE')) { return \false; } return \true; } private function configureVerbosity() { switch ($shellVerbosity = (int) \getenv('SHELL_VERBOSITY')) { case -1: $this->verbosity = self::VERBOSITY_QUIET; break; case 1: $this->verbosity = self::VERBOSITY_VERBOSE; break; case 2: $this->verbosity = self::VERBOSITY_VERY_VERBOSE; break; case 3: $this->verbosity = self::VERBOSITY_DEBUG; break; default: $shellVerbosity = 0; break; } if ($this->hasParameter(array('--quiet', '-q'))) { $this->verbosity = self::VERBOSITY_QUIET; $shellVerbosity = -1; } elseif ($this->hasParameter(array('-vvv', '--verbose=3', '--verbose 3'))) { $this->verbosity = self::VERBOSITY_DEBUG; $shellVerbosity = 3; } elseif ($this->hasParameter(array('-vv', '--verbose=2', '--verbose 2'))) { $this->verbosity = self::VERBOSITY_VERY_VERBOSE; $shellVerbosity = 2; } elseif ($this->hasParameter(array('-v', '--verbose=1', '--verbose 1', '--verbose'))) { $this->verbosity = self::VERBOSITY_VERBOSE; $shellVerbosity = 1; } return $shellVerbosity; } /** @symfony */ private function checkColorSupport() { if ($this->hasParameter(array('--ansi'))) { return \true; } if ($this->hasParameter(array('--no-ansi'))) { return \false; } if (\DIRECTORY_SEPARATOR === '\\') { return \function_exists('sapi_windows_vt100_support') && \sapi_windows_vt100_support(\STDOUT) || \false !== \getenv('ANSICON') || 'ON' === \getenv('ConEmuANSI') || 'xterm' === \getenv('TERM'); } if (\function_exists('stream_isatty')) { return \stream_isatty(\STDOUT); } if (\function_exists('posix_isatty')) { return \posix_isatty(\STDOUT); } $stat = \fstat(\STDOUT); return $stat ? 020000 === ($stat['mode'] & 0170000) : \false; } } requiredExtension = $requiredExtension; } public function __invoke() { return \extension_loaded($this->requiredExtension); } } checkIsFulfilled = $checkIsFulfilled; $this->testMessage = $testMessage; $this->helpText = $helpText; } public function isFulfilled() { if (null === $this->fulfilled) { $this->fulfilled = $this->checkIsFulfilled->__invoke(); } return (bool) $this->fulfilled; } public function getIsFullfilledChecker() { return $this->checkIsFulfilled; } public function getTestMessage() { return $this->testMessage; } public function getHelpText() { return $this->helpText; } } &1', $output, $exitcode); return self::$stty = 0 === $exitcode; } private static function initDimensions() { if ('\\' === \DIRECTORY_SEPARATOR) { if (\preg_match('/^(\\d+)x(\\d+)(?: \\((\\d+)x(\\d+)\\))?$/', \trim(\getenv('ANSICON')), $matches)) { self::$width = (int) $matches[1]; self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { self::initDimensionsUsingStty(); } elseif (null !== ($dimensions = self::getConsoleMode())) { self::$width = (int) $dimensions[0]; self::$height = (int) $dimensions[1]; } } else { self::initDimensionsUsingStty(); } } private static function hasVt100Support() { return \function_exists('sapi_windows_vt100_support') && \sapi_windows_vt100_support(\fopen('php://stdout', 'wb')); } private static function initDimensionsUsingStty() { if ($sttyString = self::getSttyColumns()) { if (\preg_match('/rows.(\\d+);.columns.(\\d+);/i', $sttyString, $matches)) { self::$width = (int) $matches[2]; self::$height = (int) $matches[1]; } elseif (\preg_match('/;.(\\d+).rows;.(\\d+).columns/i', $sttyString, $matches)) { self::$width = (int) $matches[2]; self::$height = (int) $matches[1]; } } } private static function getConsoleMode() { $info = self::readFromProcess('mode CON'); if (null === $info || !\preg_match('/--------+\\r?\\n.+?(\\d+)\\r?\\n.+?(\\d+)\\r?\\n/', $info, $matches)) { return null; } return array((int) $matches[2], (int) $matches[1]); } private static function getSttyColumns() { return self::readFromProcess('stty -a | grep columns'); } private static function readFromProcess($command) { if (!\function_exists('proc_open')) { return null; } $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $process = \proc_open($command, $descriptorspec, $pipes, null, null, array('suppress_errors' => \true)); if (!\is_resource($process)) { return null; } $info = \stream_get_contents($pipes[1]); \fclose($pipes[1]); \fclose($pipes[2]); \proc_close($process); return $info; } } requiredPhpVersion = $requiredPhpVersion; } public function __invoke() { return \HumbugBox383\Composer\Semver\Semver::satisfies(\sprintf('%d.%d.%d', \PHP_MAJOR_VERSION, \PHP_MINOR_VERSION, \PHP_RELEASE_VERSION), $this->requiredPhpVersion); } } "\33[0m", 'red' => "\33[31m", 'green' => "\33[32m", 'yellow' => "\33[33m", 'title' => "\33[33m", 'error' => "\33[37;41m", 'success' => "\33[30;42m"); private $verbosity; private $supportColors; private $width; public function __construct($verbosity, $supportColors, $width = null) { if (null === $width) { $terminal = new \HumbugBox383\KevinGH\RequirementChecker\Terminal(); $width = \min($terminal->getWidth(), 80); } $this->verbosity = $verbosity; $this->supportColors = $supportColors; $this->width = $width; } public function getVerbosity() { return $this->verbosity; } public function setVerbosity($verbosity) { $this->verbosity = $verbosity; } public function title($title, $verbosity, $style = null) { if (null === $style) { $style = 'title'; } $this->printvln('', $verbosity, $style); $this->printvln($title, $verbosity, $style); $this->printvln(\str_repeat('=', \min(\strlen($title), $this->width)), $verbosity, $style); $this->printvln('', $verbosity, $style); } public function getRequirementErrorMessage(\HumbugBox383\KevinGH\RequirementChecker\Requirement $requirement) { if ($requirement->isFulfilled()) { return null; } $errorMessage = \wordwrap($requirement->getTestMessage(), $this->width - 3, \PHP_EOL . ' ') . \PHP_EOL; return $errorMessage; } public function block($title, $message, $verbosity, $style = null) { $prefix = ' [' . $title . '] '; $message = $prefix . \trim($message); $lines = array(); $remainingMessage = $message; while ($remainingMessage !== '') { $wrapped = \wordwrap($remainingMessage, $this->width - 3, '¬'); $exploded = \explode('¬', $wrapped); $line = $exploded[0]; $remainingMessage = \ltrim(\substr($remainingMessage, \strlen($line))); if ($remainingMessage !== '') { $remainingMessage = \str_repeat(' ', \strlen($prefix)) . $remainingMessage; } $lines[] = \str_pad($line, $this->width, ' ', \STR_PAD_RIGHT); } $this->printvln('', $verbosity); $this->printvln(\str_repeat(' ', $this->width), $verbosity, $style); foreach ($lines as $line) { $this->printvln($line, $verbosity, $style); } $this->printv(\str_repeat(' ', $this->width), $verbosity, $style); $this->printvln('', $verbosity); } public function printvln($message, $verbosity, $style = null) { $this->printv($message, $verbosity, $style); $this->printv(\PHP_EOL, $verbosity, null); } public function printv($message, $verbosity, $style = null) { if ($verbosity > $this->verbosity) { return; } $message = \wordwrap($message, $this->width); $message = \sprintf('%s%s%s', $this->supportColors && isset($this->styles[$style]) ? $this->styles[$style] : '', $message, $this->supportColors ? $this->styles['reset'] : ''); echo $message; } } array ( 'type' => 'php', 'condition' => '^7.3|^8', 'message' => 'The application requires the version "^7.3|^8" or greater.', 'helpMessage' => 'The application requires the version "^7.3|^8" or greater.', ), 1 => array ( 'type' => 'extension', 'condition' => 'simplexml', 'message' => 'The application requires the extension "simplexml". Enable it or install a polyfill.', 'helpMessage' => 'The application requires the extension "simplexml".', ), 2 => array ( 'type' => 'extension', 'condition' => 'dom', 'message' => 'The application requires the extension "dom". Enable it or install a polyfill.', 'helpMessage' => 'The application requires the extension "dom".', ), 3 => array ( 'type' => 'extension', 'condition' => 'json', 'message' => 'The application requires the extension "json". Enable it or install a polyfill.', 'helpMessage' => 'The application requires the extension "json".', ), 4 => array ( 'type' => 'extension', 'condition' => 'json', 'message' => 'The package "netresearch/jsonmapper" requires the extension "json". Enable it or install a polyfill.', 'helpMessage' => 'The package "netresearch/jsonmapper" requires the extension "json".', ), 5 => array ( 'type' => 'extension', 'condition' => 'libxml', 'message' => 'The application requires the extension "libxml". Enable it or install a polyfill.', 'helpMessage' => 'The application requires the extension "libxml".', ), 6 => array ( 'type' => 'extension', 'condition' => 'tokenizer', 'message' => 'The application requires the extension "tokenizer". Enable it or install a polyfill.', 'helpMessage' => 'The application requires the extension "tokenizer".', ), 7 => array ( 'type' => 'extension', 'condition' => 'tokenizer', 'message' => 'The package "nikic/php-parser" requires the extension "tokenizer". Enable it or install a polyfill.', 'helpMessage' => 'The package "nikic/php-parser" requires the extension "tokenizer".', ), 8 => array ( 'type' => 'extension', 'condition' => 'pcre', 'message' => 'The package "netresearch/jsonmapper" requires the extension "pcre". Enable it or install a polyfill.', 'helpMessage' => 'The package "netresearch/jsonmapper" requires the extension "pcre".', ), 9 => array ( 'type' => 'extension', 'condition' => 'reflection', 'message' => 'The package "netresearch/jsonmapper" requires the extension "reflection". Enable it or install a polyfill.', 'helpMessage' => 'The package "netresearch/jsonmapper" requires the extension "reflection".', ), 10 => array ( 'type' => 'extension', 'condition' => 'spl', 'message' => 'The package "netresearch/jsonmapper" requires the extension "spl". Enable it or install a polyfill.', 'helpMessage' => 'The package "netresearch/jsonmapper" requires the extension "spl".', ), 11 => array ( 'type' => 'extension', 'condition' => 'filter', 'message' => 'The package "phpdocumentor/reflection-docblock" requires the extension "filter". Enable it or install a polyfill.', 'helpMessage' => 'The package "phpdocumentor/reflection-docblock" requires the extension "filter".', ), );composer.phar /vendor/ # Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file # composer.lock { "name": "psalm/phar", "description": "Composer-based Psalm Phar", "license": ["MIT"], "require": { "php": "^7.1" }, "conflict": { "vimeo/psalm" : "*" }, "bin": ["psalm.phar"] } This allows you to install [Psalm](https://github.com/vimeo/psalm) without worrying about composer conflicts. Default is runtime-specific: if not present, Psalm will only load the Xdebug stub if psalm has unloaded the extension. ;Հ~q# GBMB